From 03d3cc50f08b227cd17e55a086fd3023ddb824db Mon Sep 17 00:00:00 2001 From: Benjamin Koch <bbbsnowball@gmail.com> Date: Sun, 11 Jun 2023 00:25:22 +0200 Subject: [PATCH] add extra layer of pointers for program info -> program name is displayed in `picotool info` --- firmware/rust1-bootloader/src/main.rs | 10 ++- firmware/rust1/src/bin/heizung.rs | 115 ++++++++++++++++++++++---- 2 files changed, 108 insertions(+), 17 deletions(-) diff --git a/firmware/rust1-bootloader/src/main.rs b/firmware/rust1-bootloader/src/main.rs index 73e995e..e62b5b8 100644 --- a/firmware/rust1-bootloader/src/main.rs +++ b/firmware/rust1-bootloader/src/main.rs @@ -104,6 +104,10 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { // the predefined linker script is .Reset so let's add it to that. const BINARY_INFO_MARKER_START: u32 = 0x7188ebf2; const BINARY_INFO_MARKER_END: u32 = 0xe71aa390; +const PROGRAM_INFO_FLASH_OFFSET: u32 = 0x10087000 - PROGRAM_INFO_TOTAL_SIZE; // last 4k of active partition +const PROGRAM_INFO_TOTAL_SIZE: u32 = 4096; +const PROGRAM_INFO_TABLE_SIZE: u32 = 128; // one pointer (4 bytes) for each piece of data, all must be valid pointers +const PROGRAM_INFO_COPY_TABLE_SIZE: u32 = 128; // 3*u32 for each entry, picotool stops after 10 entries #[used] #[link_section = ".Reset"] pub static PROGRAM_INFO: [u32; 5] = { @@ -115,9 +119,9 @@ pub static PROGRAM_INFO: [u32; 5] = { BINARY_INFO_MARKER_START, //&__bootloader_active_program_info_start as *const u32 as u32, //&__bootloader_active_program_info_end as *const u32 as u32, - 0x10086000, - 0x10087000, - 0x10087000 - 128, // copy table can have up to 10 entries of 3*u32 each + PROGRAM_INFO_FLASH_OFFSET, + PROGRAM_INFO_FLASH_OFFSET + PROGRAM_INFO_TABLE_SIZE, + PROGRAM_INFO_FLASH_OFFSET + PROGRAM_INFO_TOTAL_SIZE - PROGRAM_INFO_COPY_TABLE_SIZE, BINARY_INFO_MARKER_END ] }; diff --git a/firmware/rust1/src/bin/heizung.rs b/firmware/rust1/src/bin/heizung.rs index cd9d730..1845fe3 100644 --- a/firmware/rust1/src/bin/heizung.rs +++ b/firmware/rust1/src/bin/heizung.rs @@ -707,10 +707,18 @@ struct ProgramInfoBuilder { buf: [u8; 4096], info_pos: usize, data_pos: usize, + info_table_size: usize, + data_end_offset: usize, } impl ProgramInfoBuilder { - const fn new(addr: u32, copy_table_size: usize) -> Self { + const fn new(addr: u32, info_table_size: u32, copy_table_size: u32) -> Self { + let copy_table_size = copy_table_size as usize; + let dummy_item_ptr = addr + info_table_size; + let dummy_item_size = 4; + + core::assert!(info_table_size % 4 == 0); + ProgramInfoBuilder { addr, buf: { @@ -723,23 +731,86 @@ impl ProgramInfoBuilder { x }, info_pos: 0, - data_pos: 4096 - copy_table_size, + data_pos: info_table_size as usize + dummy_item_size, + data_end_offset: 4096 - copy_table_size as usize, + info_table_size: info_table_size as usize, } } - const fn build(self: Self) -> [u8; 4096] { + const fn build(mut self: Self) -> [u8; 4096] { + if self.info_pos < self.info_table_size { + self = self.align(); + let addr = self.addr + self.data_pos as u32; + self = self.push_u32(0xffffffff).fill_info_table(addr); + } self.buf } - const fn push(mut self: Self, value: u8) -> Self { + const fn push_info_u8(mut self: Self, value: u8) -> Self { self.buf[self.info_pos] = value; self.info_pos += 1; - if self.info_pos > self.data_pos { + if self.info_pos > self.info_table_size { + core::panic!("ProgramInfoBuilder: too much data for info table") + } + self + } + + const fn push_info_ptr(mut self: Self, value: u32) -> Self { + self + .push_info_u8((value & 0xff) as u8) + .push_info_u8(((value >> 8) & 0xff) as u8) + .push_info_u8(((value >> 16) & 0xff) as u8) + .push_info_u8(((value >> 24) & 0xff) as u8) + } + + const fn push_current_info_ptr(mut self: Self) -> Self { + self = self.align(); + let addr = self.addr + self.data_pos as u32; + self.push_info_ptr(addr) + } + + const fn fill_info_table(mut self: Self, value: u32) -> Self { + if self.info_pos < self.info_table_size { + self = self.push_info_ptr(value); + } + if self.info_pos < self.info_table_size { + self = self.push_info_ptr(value); + } + if self.info_pos < self.info_table_size { + self = self.push_info_ptr(value); + } + if self.info_pos < self.info_table_size { + self = self.push_info_ptr(value); + } + if self.info_pos < self.info_table_size { + self.fill_info_table(value) + } else { + self + } + } + + const fn push(mut self: Self, value: u8) -> Self { + self.buf[self.data_pos] = value; + self.data_pos += 1; + if self.data_pos > self.data_end_offset { core::panic!("ProgramInfoBuilder: too much data") } self } + const fn align(mut self: Self) -> Self { + if self.data_pos % 4 != 0 { + self = self.push(0xff); + } + if self.data_pos % 4 != 0 { + self = self.push(0xff); + } + if self.data_pos % 4 != 0 { + self = self.push(0xff); + } + self + } + const fn push_u16(self: Self, value: u16) -> Self { self .push((value & 0xff) as u8) @@ -763,7 +834,7 @@ impl ProgramInfoBuilder { if self.data_pos - self.info_pos < value.len() { core::panic!("ProgramInfoBuilder: too much data") } - let offset = self.data_pos - value.len(); + let offset = self.data_pos; //self.buf[offset..self.data_pos].copy_from_slice(value); //for i in 0..value.len() { // self.buf[offset+i] = value[i]; @@ -778,7 +849,7 @@ impl ProgramInfoBuilder { if value.len() > 7 { self.buf[offset+7] = value[7]; } if value.len() > 8 { core::panic!("too long") } - self.data_pos -= value.len(); + self.data_pos += value.len(); let addr = self.addr + offset as u32; (self, addr) } @@ -787,9 +858,19 @@ impl ProgramInfoBuilder { if self.data_pos - self.info_pos < value.len() { core::panic!("ProgramInfoBuilder: too much data") } - (self, _) = self.push_extra_data(&[0]); + let x1 = self.data_pos; + self = self.push_u32(0); + let (self2, addr) = self.push_extra_data(value.as_bytes()); - self2.push_u32(addr) + self = self2; + (self, _) = self.push_extra_data(&[0]); + + let x2 = self.data_pos; + self.data_pos = x1; + self = self.push_u32(addr); + self.data_pos = x2; + + self } const BINARY_INFO_TYPE_ID_AND_INT: u16 = 5; @@ -798,25 +879,31 @@ impl ProgramInfoBuilder { const BINARY_INFO_ID_RP_BINARY_END: u32 = 0x68f465de; const fn push_program_name(self: Self, value: &str) -> Self { - self.push_raspberry_tag() + self.push_current_info_ptr() .push_u16(Self::BINARY_INFO_TYPE_ID_AND_STRING) + .push_raspberry_tag() .push_u32(Self::BINARY_INFO_ID_RP_PROGRAM_NAME) .push_string(value) } + #[allow(unused)] const fn push_binary_end(self: Self, value: &str) -> Self { - self.push_raspberry_tag() + self.push_current_info_ptr() .push_u16(Self::BINARY_INFO_TYPE_ID_AND_INT) + .push_raspberry_tag() .push_u32(Self::BINARY_INFO_ID_RP_BINARY_END) .push_string(value) } } const fn make_program_info() -> [u8; 4096] { - const PROGRAM_INFO_START: u32 = 0x10086000; - const COPY_TABLE_SIZE: usize = 128; // must match bootloader + // all of these must match the values in the bootloader + const PROGRAM_INFO_FLASH_OFFSET: u32 = 0x10087000 - PROGRAM_INFO_TOTAL_SIZE; // last 4k of active partition + const PROGRAM_INFO_TOTAL_SIZE: u32 = 4096; + const PROGRAM_INFO_TABLE_SIZE: u32 = 128; // one pointer (4 bytes) for each piece of data, all must be valid pointers + const PROGRAM_INFO_COPY_TABLE_SIZE: u32 = 128; // 3*u32 for each entry, picotool stops after 10 entries - ProgramInfoBuilder::new(PROGRAM_INFO_START, COPY_TABLE_SIZE) + ProgramInfoBuilder::new(PROGRAM_INFO_FLASH_OFFSET, PROGRAM_INFO_TABLE_SIZE, PROGRAM_INFO_COPY_TABLE_SIZE) .push_program_name("Test 123") .build() } -- GitLab