firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
0

Configure Feed

Select the types of activity you want to include in your feed.

1use core::marker::PhantomData; 2use core::str::Utf8Error; 3use defmt::debug; 4use fw16_epd_program_interface::ProgramFunctionTable; 5 6#[link_section = ".prog1"] 7#[used] 8static PROG1: [u32; 11] = [ 9 0, // block_erase_cycles 10 1419452448, // crc 11 44, // len 12 4, // name_len 13 32, // name_offset 14 5, // version_len 15 36, // version_offset 16 0, // entry_offset 17 0x74736554, 18 0x2E302E30, 19 0x00000032, 20]; 21 22const XIP_BASE: *const u8 = 0x10000000 as *const u8; 23 24const SLOT_SIZE: usize = 0x80000; 25 26pub(crate) const unsafe fn slot<'a>(id: u8) -> &'a ProgramSlotHeader { 27 if id < 1 || id > 31 { 28 panic!("slot ID must be between 1 and 31"); 29 } 30 31 &*XIP_BASE.add(SLOT_SIZE * id as usize).cast::<ProgramSlotHeader>() 32} 33 34#[repr(C)] 35pub(crate) struct ProgramSlotHeader { 36 pub(crate) block_erase_cycles: usize, 37 pub(crate) crc: u32, 38 pub(crate) len: usize, 39 pub(crate) name_len: usize, 40 pub(crate) name_offset: usize, 41 pub(crate) version_len: usize, 42 pub(crate) version_offset: usize, 43 pub(crate) entry_offset: usize, 44} 45 46impl ProgramSlotHeader { 47 fn ptr(&self) -> *const u8 { 48 (&raw const *self).cast() 49 } 50 51 pub(crate) fn is_valid_program(&self) -> bool { 52 self.len != 0 53 && self.check_crc() 54 && self.name_offset.saturating_add(self.name_len) <= self.len 55 && self.version_offset.saturating_add(self.version_len) <= self.len 56 && self.entry_offset < self.len 57 && self.name().is_ok() 58 && self.version_string().is_ok() 59 } 60 61 pub(crate) fn check_crc(&self) -> bool { 62 if self.len >= SLOT_SIZE || self.len < size_of::<ProgramSlotHeader>() { 63 return false; 64 } 65 66 let ptr = unsafe { self.ptr().add(8) }; 67 let slice = unsafe { core::slice::from_raw_parts(ptr, self.len - 8) }; 68 let crc = crc32fast::hash(slice); 69 crc == self.crc 70 } 71 72 pub(crate) fn name(&self) -> Result<&str, Utf8Error> { 73 let ptr = unsafe { self.ptr().add(self.name_offset) }; 74 let slice = unsafe { core::slice::from_raw_parts(ptr, self.name_len) }; 75 core::str::from_utf8(slice) 76 } 77 78 pub(crate) fn version_string(&self) -> Result<&str, Utf8Error> { 79 let ptr = unsafe { self.ptr().add(self.version_offset) }; 80 let slice = unsafe { core::slice::from_raw_parts(ptr, self.version_len) }; 81 core::str::from_utf8(slice) 82 } 83 84 pub(crate) unsafe fn entry(&self) -> unsafe extern "C" fn(&ProgramFunctionTable) -> () { 85 let ptr = self.ptr().add(self.entry_offset); 86 core::mem::transmute(ptr) 87 } 88} 89 90pub(crate) struct Programs<'a> { 91 id: u8, 92 _phantom: PhantomData<&'a ProgramSlotHeader>, 93} 94 95impl<'a> Programs<'a> { 96 pub(crate) fn new() -> Self { 97 Self { id: 0, _phantom: PhantomData } 98 } 99} 100 101impl<'a> Iterator for Programs<'a> { 102 type Item = &'a ProgramSlotHeader; 103 104 fn next(&mut self) -> Option<Self::Item> { 105 loop { 106 self.id += 1; 107 108 if self.id == 32 { 109 return None; 110 } 111 112 let s = unsafe { slot(self.id) }; 113 114 if s.is_valid_program() { 115 debug!("Found program {} version {} in slot {}", s.name().unwrap(), s.version_string().unwrap(), self.id); 116 return Some(s); 117 } else { 118 debug!("No program found in slot {}", self.id); 119 } 120 121 } 122 } 123 124 fn size_hint(&self) -> (usize, Option<usize>) { 125 (0, Some(32 - self.id as usize)) 126 } 127}