From 33cdcb09a43ecff02d3ad3245efac047956f0e02 Mon Sep 17 00:00:00 2001 From: Nahla Date: Sun, 17 Nov 2024 18:22:05 -0700 Subject: [PATCH 01/15] add basic safe api for get_sys_info --- rp235x-hal/src/rom_data.rs | 370 +++++++++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index ef9440b97..113f139ca 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -109,6 +109,376 @@ pub fn rom_data_lookup(tag: RomFnTableCode, mask: u32) -> usize { } } +/// bootrom API function return codes as defined by section 5.4.3 in the rp2350 data sheet +/// See: https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf +#[repr(i32)] +pub enum BootRomApiErrorCode { + /// The operation was disallowed by a security constraint + NotPermitted = -4, + /// One or more parameters passed to the function is outside the range of + /// supported values; BOOTROM_ERROR_INVALID_ADDRESS and + /// BOOTROM_ERROR_BAD_ALIGNMENT are more specific errors. + InvalidArg = -5, + /// An address argument was out-of-bounds or was determined to be an address + /// that the caller may not access + InvalidAddress = -10, + /// An address passed to the function was not correctly aligned + BadAlignment = -11, + /// Something happened or failed to happen in the past, and consequently the + /// request cannot currently be serviced. + InvalidState = -12, + /// A user-allocated buffer was too small to hold the result or working state + /// of the function + BufferTooSmall = -13, + /// The call failed because another bootrom function must be called first. + PreconditionNotMet = -14, + /// Cached data was determined to be inconsistent with the full version of + /// the data it was copied from + ModifiedData = -15, + /// The contents of a data structure are invalid + InvalidData = -16, + /// An attempt was made to access something that does not exist; or, a search failed + NotFound = -17, + /// Modification is impossible based on current state; e.g. attempted to clear + /// an OTP bit. + UnsupportedModification = -18, + /// A required lock is not owned. See Section 5.4.4. + LockRequired = -19, +} + +impl From for BootRomApiErrorCode { + fn from(value: i32) -> Self { + match value { + -4 => Self::NotPermitted, + -5 => Self::InvalidArg, + -19..=-10 => unsafe { core::mem::transmute(value) }, + _ => panic!("Attempted to convert an i32 to BootRomApiErrorCode with an invalid value"), + } + } +} + +#[allow(unused)] +mod sys_info_api { + use super::BootRomApiErrorCode; + + /// Flags that the `get_sys_info`/ rom function can take + #[repr(u32)] + pub enum GetSysInfoFlag { + ChipInfo = 0x0001, + Critical = 0x0002, + CpuInfo = 0x0004, + FlashDevInfo = 0x0008, + BootRandom = 0x0010, + // Ignore nonce for now since it can't/shouldn't be called anyway? + // Nonce = 0x0020, + BootInfo = 0x0040, + } + + impl GetSysInfoFlag { + const fn buffer_length(&self) -> usize { + match self { + GetSysInfoFlag::ChipInfo => 4, + GetSysInfoFlag::Critical | GetSysInfoFlag::CpuInfo | GetSysInfoFlag::FlashDevInfo => 2, + GetSysInfoFlag::BootRandom | GetSysInfoFlag::BootInfo => 5, + } + } + } + + pub struct ChipInfo { + package_sel: u32, + device_id: u32, + wafer_id: u32, + } + + impl From<[u32; 3]> for ChipInfo { + fn from(value: [u32; 3]) -> Self { + ChipInfo { + package_sel: value[0], + device_id: value[1], + wafer_id: value[2], + } + } + } + + pub struct OtpCriticalReg(u32); + + impl OtpCriticalReg { + pub fn secure_boot_enabled(&self) -> bool { + (self.0 & 0x1) == 1 + } + + pub fn secure_debug_disabled(&self) -> bool { + (self.0 & 0x2) >> 1 == 1 + } + + pub fn debug_disabled(&self) -> bool { + (self.0 & 0x4) >> 2 == 1 + } + + pub fn default_arch_sel(&self) -> bool { + (self.0 & 0x8) >> 3 == 1 + } + + pub fn glitch_detector_enabled(&self) -> bool { + (self.0 & 0x10) >> 4 == 1 + } + + pub fn glitch_detector_sens(&self) -> u8 { + ((self.0 & 0x60) >> 5) as _ + } + + pub fn arm_disabled(&self) -> bool { + (self.0 & 0x10000) >> 16 == 1 + } + + pub fn risc_disabled(&self) -> bool { + (self.0 & 0x20000) >> 17 == 1 + } + } + + impl From<[u32; 1]> for OtpCriticalReg { + fn from(value: [u32; 1]) -> OtpCriticalReg { + OtpCriticalReg(value[0]) + } + } + + #[repr(u32)] + pub enum CpuInfo { + Arm, + Risc + } + + impl From<[u32; 1]> for CpuInfo { + fn from(value: [u32; 1]) -> CpuInfo { + if value[0] == 0 { + CpuInfo::Arm + } + else { + CpuInfo::Risc + } + } + } + + pub struct FlashDevInfo(u32); + + #[repr(u32)] + pub enum FlashDevInfoSize { + None, + K8, + K16, + K32, + K64, + K128, + K256, + K512, + M1, + M2, + M4, + M8, + M16 + } + + impl From for FlashDevInfoSize { + fn from(value: u32) -> Self { + if value > 0xc { + panic!("FLASH_DEVINFO's cs0_size contained an unknown value greater than 0xc"); + } + + unsafe { core::mem::transmute::(value) } + } + } + + impl FlashDevInfo { + pub fn cs1_gpio(&self) -> u8 { + (self.0 & 0x1f) as _ + } + + pub fn d8h_erase_supported(&self) -> bool { + (self.0 & 0x80) == 1 + } + + pub fn cs0_size(&self) -> FlashDevInfoSize { + FlashDevInfoSize::from((self.0 & 0xf00) >> 8) + } + + pub fn cs1_size(&self) -> FlashDevInfoSize { + FlashDevInfoSize::from((self.0 & 0xf000) >> 12) + } + } + + impl From<[u32; 1]> for FlashDevInfo { + fn from(value: [u32; 1]) -> FlashDevInfo { + FlashDevInfo(value[0]) + } + } + + pub struct BootRandom(u128); + + impl From<[u32; 4]> for BootRandom { + fn from(value: [u32; 4]) -> BootRandom { + let mut result = 0; + for word in value { + result = (result << 32) | u128::from(word); + }; + BootRandom(result) + } + } + + pub struct BootInfo { + partition_index: i8, + boot_type: u8, + partition: i8, + tbyb_update_info: u8, + boot_diagnostic: u32, + boot_params: [u32; 2] + } + + #[repr(u16)] + pub enum BootDiagnosticFlags { + /// The region was searched for a block loop + RegionSearched = 0x0001, + /// A block loop was found but it was invalid + InvalidBlockLoop = 0x0002, + /// A valid block loop was found (Blocks from a loop wholly contained within the region, and + /// the blocks have the correct structure. Each block consists of items whose sizes sum to + /// the size of the block) + ValidBlockLoop = 0x0004, + /// A valid IMAGE_DEF was found in the region. A valid IMAGE_DEF must parse correctly and must + /// be executable + ValidImageDef = 0x0008, + /// Whether a partition table is present. This partition table must have a correct structure + /// formed if VALID_BLOCK_LOOP is set. If the partition table turns out to be invalid, then + /// INVALID_BLOCK_LOOP is set too (thus both VALID_BLOCK_LOOP and INVALID_BLOCK_LOOP will + /// both be set) + HasPartitionTable = 0x0010, + /// There was a choice of partition/slot and this one was considered. The first slot/partition + /// is chosen based on a number of factors. If the first choice fails verification, then the + /// other choice will be considered. + /// + /// * the version of the PARTITION_TABLE/IMAGE_DEF present in the slot/partition respectively. + /// * whether the slot/partition is the "update region" as per a FLASH_UPDATE reboot. + /// * whether an IMAGE_DEF is marked as "explicit buy" + Considered = 0x0020, + /// This slot/partition was chosen (or was the only choice) + Chosen = 0x0040, + /// if a signature is required for the PARTITION_TABLE (via OTP setting), then whether the + /// PARTITION_TABLE is signed with a key matching one of the four stored in OTP + PartitionTableMatchingKeyForVerify = 0x0080, + /// set if a hash value check could be performed. In the case a signature is required, this + /// value is identical to PARTITION_TABLE_MATCHING_KEY_FOR_VERIFY + PartitionTableHashForVerify = 0x0100, + /// whether the PARTITION_TABLE passed verification (signature/hash if present/required) + PartitionTableVerifiedOk = 0x0200, + /// if a signature is required for the IMAGE_DEF due to secure boot, then whether the + /// IMAGE_DEF is signed with a key matching one of the four stored in OTP + ImageDefMatchingKeyForVerify = 0x0400, + /// set if a hash value check could be performed. In the case a signature is required, this + /// value is identical to IMAGE_DEF_MATCHING_KEY_FOR_VERIFY + ImageDefHashForVerify = 0x0800, + /// whether the PARTITION_TABLE passed verification (signature/hash if present/required) and + /// any LOAD_MAP is valid + ImageDefVerifiedOk = 0x1000, + /// whether any code was copied into RAM due to a LOAD_MAP + LoadMapEntriesLoaded = 0x2000, + /// whether an IMAGE_DEF from this region was launched + ImageLaunched = 0x4000, + /// whether the IMAGE_DEF failed final checks before launching; these checks include + /// + /// * verification failed (if it hasn’t been verified earlier in the CONSIDERED phase). + /// * a problem occurred setting up any rolling window. + /// * the rollback version could not be set in OTP (if required in Secure mode) + /// * the image was marked as Non-secure + /// * the image was marked as "explicit buy", and this was a flash boot, but then region was + /// not the "flash update" region + /// * the image has the wrong architecture, but architecture auto-switch is disabled (or the + /// correct architecture is disabled) + ImageConditionFailure = 0x8000 + } + + impl From<[u32; 4]> for BootInfo { + fn from(value: [u32; 4]) -> Self { + let word0 = value[0]; + + BootInfo { + partition_index: word0 as _, + boot_type: (word0 >> 8) as _, + partition: (word0 >> 16) as _, + tbyb_update_info: (word0 >> 24) as _, + boot_diagnostic: value[1], + boot_params: [value[2], value[3]], + } + } + } + + impl BootInfo { + fn check_flag(diagnostics: u16, flag: BootDiagnosticFlags) -> bool { + (diagnostics & flag as u16) > 0 + } + + pub fn check_section_a_flag(&self, flag: BootDiagnosticFlags) -> bool { + Self::check_flag(self.boot_diagnostic as u16, flag) + } + + pub fn check_section_b_flag(&self, flag: BootDiagnosticFlags) -> bool { + Self::check_flag((self.boot_diagnostic >> 8) as u16, flag) + } + } + + #[macro_export] + /// Generates a function with the following signature: + /// + /// ```rs + /// pub fn $function_name() -> Result, BootRomApiErrorCode> + /// ``` + /// + /// Which safely calls [`get_sys_info`](super::get_sys_info()) using the flag provided via + /// the `flag` argument. `flag` is an expression that must resolve to a const variant of + /// [`GetSysInfoFlag`] + macro_rules! declare_get_sys_info_function { + ($function_name:ident, $ok_ret_type:ty, $flag:expr) => { + pub fn $function_name() -> Result, BootRomApiErrorCode> { + const FLAG: GetSysInfoFlag = $flag; + const BUFFER_LEN: usize = FLAG.buffer_length(); + let mut buffer = [0u32; FLAG.buffer_length()]; + let result = unsafe{super::get_sys_info( + buffer.as_mut_ptr(), buffer.len(), FLAG as u32 + )}; + + if result < 0 { + return Err(BootRomApiErrorCode::from(result)); + } + // The operation returned successfully but the flag wasn't supported + // for one reason or another + else if buffer[0] == 0 { + return Ok(None) + } + + Ok(Some(<$ok_ret_type>::from( + TryInto::<[u32; BUFFER_LEN-1]>::try_into(&buffer[1..]).unwrap() + ))) + } + } + } + + /// Get the unique identifier for the chip + declare_get_sys_info_function!(chip_info, ChipInfo, GetSysInfoFlag::ChipInfo); + + /// Get the value of the OTP critical register + declare_get_sys_info_function!(otp_critical_register, OtpCriticalReg, GetSysInfoFlag::Critical); + + /// Get the current running CPU's info + declare_get_sys_info_function!(cpu_info, CpuInfo, GetSysInfoFlag::CpuInfo); + + /// Get flash device info in the format of OTP FLASH_DEVINFO + declare_get_sys_info_function!(flash_dev_info, FlashDevInfo, GetSysInfoFlag::FlashDevInfo); + + /// Get a 128-bit random number generated on each boot + declare_get_sys_info_function!(boot_random, BootRandom, GetSysInfoFlag::BootRandom); + + // Get diagnostic boot info + declare_get_sys_info_function!(boot_info, BootInfo, GetSysInfoFlag::BootInfo); +} + macro_rules! declare_rom_function { ( $(#[$outer:meta])* From 136226a6cbc738028c33b653ffbe2118e4762eca Mon Sep 17 00:00:00 2001 From: Nahla Date: Sun, 17 Nov 2024 22:11:59 -0700 Subject: [PATCH 02/15] add nicer api for BootInfo and allow uknown states rather than panic --- rp235x-hal/src/rom_data.rs | 70 +++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index 113f139ca..99ad4c917 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -144,6 +144,8 @@ pub enum BootRomApiErrorCode { UnsupportedModification = -18, /// A required lock is not owned. See Section 5.4.4. LockRequired = -19, + /// An unknown error + Unknown = -1 } impl From for BootRomApiErrorCode { @@ -152,7 +154,7 @@ impl From for BootRomApiErrorCode { -4 => Self::NotPermitted, -5 => Self::InvalidArg, -19..=-10 => unsafe { core::mem::transmute(value) }, - _ => panic!("Attempted to convert an i32 to BootRomApiErrorCode with an invalid value"), + _ => Self::Unknown, } } } @@ -275,17 +277,18 @@ mod sys_info_api { M2, M4, M8, - M16 + M16, + Unknown } impl From for FlashDevInfoSize { fn from(value: u32) -> Self { if value > 0xc { - panic!("FLASH_DEVINFO's cs0_size contained an unknown value greater than 0xc"); + return Self::Unknown; } unsafe { core::mem::transmute::(value) } - } + } } impl FlashDevInfo { @@ -324,15 +327,65 @@ mod sys_info_api { } } + // based on https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_bootrom/include/pico/bootrom.h pub struct BootInfo { - partition_index: i8, - boot_type: u8, + diagnostic_partition: PartitionIndex, + boot_type: BootType, + chained: bool, partition: i8, + // could probably make a nicer api for tbyb, but documentation is eh so im holding off for now tbyb_update_info: u8, boot_diagnostic: u32, boot_params: [u32; 2] } + pub enum PartitionIndex { + Partition(u8), + None, + Slot0, + Slot1, + Image, + Unknown + } + + impl From for PartitionIndex { + fn from(value: i8) -> Self { + if value < -4 || value > 15 { + return Self::Unknown; + } + + match value { + -1 => Self::None, + -2 => Self::Slot0, + -3 => Self::Slot1, + -4 => Self::Image, + _ => Self::Partition(value as u8) + } + } + } + + pub enum BootType { + Normal, + BootSel, + RamImage, + FlashUpdate, + PcSp, + Unknown + } + + impl From for BootType { + fn from(value: u8) -> Self { + match value { + 0 => Self::Normal, + 2 => Self::BootSel, + 3 => Self::RamImage, + 4 => Self::FlashUpdate, + 8..=15 => Self::PcSp, + _ => Self::Unknown + } + } + } + #[repr(u16)] pub enum BootDiagnosticFlags { /// The region was searched for a block loop @@ -400,8 +453,9 @@ mod sys_info_api { let word0 = value[0]; BootInfo { - partition_index: word0 as _, - boot_type: (word0 >> 8) as _, + diagnostic_partition: PartitionIndex::from((word0 & 0xFF) as i8), + boot_type: BootType::from((word0 >> 8) as u8), + chained: (word0 >> 8) & 0x80 > 0, partition: (word0 >> 16) as _, tbyb_update_info: (word0 >> 24) as _, boot_diagnostic: value[1], From 0e929e799855ada4d6b77ead00fbe10d07d3d14f Mon Sep 17 00:00:00 2001 From: Nahla Date: Sun, 17 Nov 2024 22:18:50 -0700 Subject: [PATCH 03/15] Improve comment docs to reference enum's in the library via link rather than copy pasted constant names from the datasheet --- rp235x-hal/src/rom_data.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index 99ad4c917..676c730f8 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -116,8 +116,8 @@ pub enum BootRomApiErrorCode { /// The operation was disallowed by a security constraint NotPermitted = -4, /// One or more parameters passed to the function is outside the range of - /// supported values; BOOTROM_ERROR_INVALID_ADDRESS and - /// BOOTROM_ERROR_BAD_ALIGNMENT are more specific errors. + /// supported values; [`BootRomApiErrorCode::InvalidAddress`] and + /// [`BootRomApiErrorCode::BadAlignment`] are more specific errors. InvalidArg = -5, /// An address argument was out-of-bounds or was determined to be an address /// that the caller may not access @@ -400,9 +400,10 @@ mod sys_info_api { /// be executable ValidImageDef = 0x0008, /// Whether a partition table is present. This partition table must have a correct structure - /// formed if VALID_BLOCK_LOOP is set. If the partition table turns out to be invalid, then - /// INVALID_BLOCK_LOOP is set too (thus both VALID_BLOCK_LOOP and INVALID_BLOCK_LOOP will - /// both be set) + /// formed if [`BootDiagnosticFlags::ValidBlockLoop`] is set. If the partition table turns + /// out to be invalid, then [`BootDiagnosticFlags::InvalidBlockLoop`] is set too (thus both + /// [`BootDiagnosticFlags::ValidBlockLoop`] and [`BootDiagnosticFlags::InvalidBlockLoop`] + /// will both be set) HasPartitionTable = 0x0010, /// There was a choice of partition/slot and this one was considered. The first slot/partition /// is chosen based on a number of factors. If the first choice fails verification, then the @@ -418,7 +419,7 @@ mod sys_info_api { /// PARTITION_TABLE is signed with a key matching one of the four stored in OTP PartitionTableMatchingKeyForVerify = 0x0080, /// set if a hash value check could be performed. In the case a signature is required, this - /// value is identical to PARTITION_TABLE_MATCHING_KEY_FOR_VERIFY + /// value is identical to [`BootDiagnosticFlags::PartitionTableMatchingKeyForVerify`] PartitionTableHashForVerify = 0x0100, /// whether the PARTITION_TABLE passed verification (signature/hash if present/required) PartitionTableVerifiedOk = 0x0200, @@ -426,7 +427,7 @@ mod sys_info_api { /// IMAGE_DEF is signed with a key matching one of the four stored in OTP ImageDefMatchingKeyForVerify = 0x0400, /// set if a hash value check could be performed. In the case a signature is required, this - /// value is identical to IMAGE_DEF_MATCHING_KEY_FOR_VERIFY + /// value is identical to [`BootDiagnosticFlags::ImageDefMatchingKeyForVerify`] ImageDefHashForVerify = 0x0800, /// whether the PARTITION_TABLE passed verification (signature/hash if present/required) and /// any LOAD_MAP is valid From e469592af087fe4bcf37cbf8d98a700854b654f8 Mon Sep 17 00:00:00 2001 From: Nahla Date: Mon, 18 Nov 2024 09:19:39 -0700 Subject: [PATCH 04/15] Add clippy and fmt suggestions and fix bug found by clippy with d8h flag check --- rp235x-hal/src/rom_data.rs | 66 ++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index 676c730f8..33a153342 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -145,7 +145,7 @@ pub enum BootRomApiErrorCode { /// A required lock is not owned. See Section 5.4.4. LockRequired = -19, /// An unknown error - Unknown = -1 + Unknown = -1, } impl From for BootRomApiErrorCode { @@ -153,7 +153,7 @@ impl From for BootRomApiErrorCode { match value { -4 => Self::NotPermitted, -5 => Self::InvalidArg, - -19..=-10 => unsafe { core::mem::transmute(value) }, + -19..=-10 => unsafe { core::mem::transmute::(value) }, _ => Self::Unknown, } } @@ -180,7 +180,9 @@ mod sys_info_api { const fn buffer_length(&self) -> usize { match self { GetSysInfoFlag::ChipInfo => 4, - GetSysInfoFlag::Critical | GetSysInfoFlag::CpuInfo | GetSysInfoFlag::FlashDevInfo => 2, + GetSysInfoFlag::Critical + | GetSysInfoFlag::CpuInfo + | GetSysInfoFlag::FlashDevInfo => 2, GetSysInfoFlag::BootRandom | GetSysInfoFlag::BootInfo => 5, } } @@ -247,15 +249,14 @@ mod sys_info_api { #[repr(u32)] pub enum CpuInfo { Arm, - Risc + Risc, } impl From<[u32; 1]> for CpuInfo { fn from(value: [u32; 1]) -> CpuInfo { if value[0] == 0 { CpuInfo::Arm - } - else { + } else { CpuInfo::Risc } } @@ -278,7 +279,7 @@ mod sys_info_api { M4, M8, M16, - Unknown + Unknown, } impl From for FlashDevInfoSize { @@ -288,7 +289,7 @@ mod sys_info_api { } unsafe { core::mem::transmute::(value) } - } + } } impl FlashDevInfo { @@ -297,7 +298,7 @@ mod sys_info_api { } pub fn d8h_erase_supported(&self) -> bool { - (self.0 & 0x80) == 1 + (self.0 & 0x80) != 0 } pub fn cs0_size(&self) -> FlashDevInfoSize { @@ -322,7 +323,7 @@ mod sys_info_api { let mut result = 0; for word in value { result = (result << 32) | u128::from(word); - }; + } BootRandom(result) } } @@ -336,7 +337,7 @@ mod sys_info_api { // could probably make a nicer api for tbyb, but documentation is eh so im holding off for now tbyb_update_info: u8, boot_diagnostic: u32, - boot_params: [u32; 2] + boot_params: [u32; 2], } pub enum PartitionIndex { @@ -345,12 +346,12 @@ mod sys_info_api { Slot0, Slot1, Image, - Unknown + Unknown, } impl From for PartitionIndex { fn from(value: i8) -> Self { - if value < -4 || value > 15 { + if !(-4..=15).contains(&value) { return Self::Unknown; } @@ -359,7 +360,7 @@ mod sys_info_api { -2 => Self::Slot0, -3 => Self::Slot1, -4 => Self::Image, - _ => Self::Partition(value as u8) + _ => Self::Partition(value as u8), } } } @@ -370,7 +371,7 @@ mod sys_info_api { RamImage, FlashUpdate, PcSp, - Unknown + Unknown, } impl From for BootType { @@ -381,7 +382,7 @@ mod sys_info_api { 3 => Self::RamImage, 4 => Self::FlashUpdate, 8..=15 => Self::PcSp, - _ => Self::Unknown + _ => Self::Unknown, } } } @@ -408,7 +409,7 @@ mod sys_info_api { /// There was a choice of partition/slot and this one was considered. The first slot/partition /// is chosen based on a number of factors. If the first choice fails verification, then the /// other choice will be considered. - /// + /// /// * the version of the PARTITION_TABLE/IMAGE_DEF present in the slot/partition respectively. /// * whether the slot/partition is the "update region" as per a FLASH_UPDATE reboot. /// * whether an IMAGE_DEF is marked as "explicit buy" @@ -437,16 +438,16 @@ mod sys_info_api { /// whether an IMAGE_DEF from this region was launched ImageLaunched = 0x4000, /// whether the IMAGE_DEF failed final checks before launching; these checks include - /// + /// /// * verification failed (if it hasn’t been verified earlier in the CONSIDERED phase). /// * a problem occurred setting up any rolling window. /// * the rollback version could not be set in OTP (if required in Secure mode) /// * the image was marked as Non-secure /// * the image was marked as "explicit buy", and this was a flash boot, but then region was - /// not the "flash update" region + /// not the "flash update" region /// * the image has the wrong architecture, but architecture auto-switch is disabled (or the - /// correct architecture is disabled) - ImageConditionFailure = 0x8000 + /// correct architecture is disabled) + ImageConditionFailure = 0x8000, } impl From<[u32; 4]> for BootInfo { @@ -467,7 +468,7 @@ mod sys_info_api { impl BootInfo { fn check_flag(diagnostics: u16, flag: BootDiagnosticFlags) -> bool { - (diagnostics & flag as u16) > 0 + (diagnostics & flag as u16) != 0 } pub fn check_section_a_flag(&self, flag: BootDiagnosticFlags) -> bool { @@ -481,11 +482,11 @@ mod sys_info_api { #[macro_export] /// Generates a function with the following signature: - /// + /// /// ```rs /// pub fn $function_name() -> Result, BootRomApiErrorCode> /// ``` - /// + /// /// Which safely calls [`get_sys_info`](super::get_sys_info()) using the flag provided via /// the `flag` argument. `flag` is an expression that must resolve to a const variant of /// [`GetSysInfoFlag`] @@ -495,9 +496,8 @@ mod sys_info_api { const FLAG: GetSysInfoFlag = $flag; const BUFFER_LEN: usize = FLAG.buffer_length(); let mut buffer = [0u32; FLAG.buffer_length()]; - let result = unsafe{super::get_sys_info( - buffer.as_mut_ptr(), buffer.len(), FLAG as u32 - )}; + let result = + unsafe { super::get_sys_info(buffer.as_mut_ptr(), buffer.len(), FLAG as u32) }; if result < 0 { return Err(BootRomApiErrorCode::from(result)); @@ -505,21 +505,25 @@ mod sys_info_api { // The operation returned successfully but the flag wasn't supported // for one reason or another else if buffer[0] == 0 { - return Ok(None) + return Ok(None); } Ok(Some(<$ok_ret_type>::from( - TryInto::<[u32; BUFFER_LEN-1]>::try_into(&buffer[1..]).unwrap() + TryInto::<[u32; BUFFER_LEN - 1]>::try_into(&buffer[1..]).unwrap(), ))) } - } + }; } /// Get the unique identifier for the chip declare_get_sys_info_function!(chip_info, ChipInfo, GetSysInfoFlag::ChipInfo); /// Get the value of the OTP critical register - declare_get_sys_info_function!(otp_critical_register, OtpCriticalReg, GetSysInfoFlag::Critical); + declare_get_sys_info_function!( + otp_critical_register, + OtpCriticalReg, + GetSysInfoFlag::Critical + ); /// Get the current running CPU's info declare_get_sys_info_function!(cpu_info, CpuInfo, GetSysInfoFlag::CpuInfo); From f26a8d1cb8ae51924413a35b6fa9d4a394b8b7d4 Mon Sep 17 00:00:00 2001 From: Nahla Date: Mon, 18 Nov 2024 20:02:29 -0700 Subject: [PATCH 05/15] Add more documentation, remove transmute and make module public --- rp235x-hal/src/rom_data.rs | 141 ++++++++++++++++++++++++++++++------- 1 file changed, 116 insertions(+), 25 deletions(-) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index 33a153342..b42a1680c 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -112,6 +112,7 @@ pub fn rom_data_lookup(tag: RomFnTableCode, mask: u32) -> usize { /// bootrom API function return codes as defined by section 5.4.3 in the rp2350 data sheet /// See: https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf #[repr(i32)] +#[derive(Debug)] pub enum BootRomApiErrorCode { /// The operation was disallowed by a security constraint NotPermitted = -4, @@ -153,26 +154,42 @@ impl From for BootRomApiErrorCode { match value { -4 => Self::NotPermitted, -5 => Self::InvalidArg, - -19..=-10 => unsafe { core::mem::transmute::(value) }, + -10 => Self::InvalidAddress, + -11 => Self::BadAlignment, + -12 => Self::InvalidState, + -13 => Self::BufferTooSmall, + -14 => Self::PreconditionNotMet, + -15 => Self::ModifiedData, + -16 => Self::InvalidData, + -17 => Self::NotFound, + -18 => Self::UnsupportedModification, + -19 => Self::LockRequired, _ => Self::Unknown, } } } +/// This module defines a safe api to access the `get_sys_info` bootrom function #[allow(unused)] -mod sys_info_api { +pub mod sys_info_api { use super::BootRomApiErrorCode; /// Flags that the `get_sys_info`/ rom function can take #[repr(u32)] pub enum GetSysInfoFlag { + /// The flag used to get a chip's unique identifier ChipInfo = 0x0001, + /// The flag used to get the critical register's value Critical = 0x0002, + /// The flag used to get the current running CPU Architecture CpuInfo = 0x0004, + /// The flag used to get flash device info FlashDevInfo = 0x0008, + /// The flag used to get the random 128 bit integer generated on boot BootRandom = 0x0010, // Ignore nonce for now since it can't/shouldn't be called anyway? // Nonce = 0x0020, + /// The flag used to get boot diagnostic info BootInfo = 0x0040, } @@ -188,10 +205,14 @@ mod sys_info_api { } } + /// The unqiue identifier for each chip as reported by [`chip_info`] pub struct ChipInfo { - package_sel: u32, - device_id: u32, - wafer_id: u32, + /// The value of the `CHIP_INFO_PACKAGE_SEL` register + pub package_sel: u32, + /// The device's id + pub device_id: u32, + /// The wafer's id + pub wafer_id: u32, } impl From<[u32; 3]> for ChipInfo { @@ -204,37 +225,46 @@ mod sys_info_api { } } + /// The value held within the critical register as reported by [`otp_critical_register`] pub struct OtpCriticalReg(u32); impl OtpCriticalReg { + /// Check if secure boot is enabled pub fn secure_boot_enabled(&self) -> bool { (self.0 & 0x1) == 1 } + /// Check if secure debug is disabled pub fn secure_debug_disabled(&self) -> bool { (self.0 & 0x2) >> 1 == 1 } + /// Check if debug is disabled pub fn debug_disabled(&self) -> bool { (self.0 & 0x4) >> 2 == 1 } + /// Check the value of `DEFAULT_ARCHSEL` pub fn default_arch_sel(&self) -> bool { (self.0 & 0x8) >> 3 == 1 } + /// Check if the glitch detector is enabled pub fn glitch_detector_enabled(&self) -> bool { (self.0 & 0x10) >> 4 == 1 } + /// Value of `GLITCH_DETECTOR_SENS pub fn glitch_detector_sens(&self) -> u8 { ((self.0 & 0x60) >> 5) as _ } + /// Check if ARM is disabled pub fn arm_disabled(&self) -> bool { (self.0 & 0x10000) >> 16 == 1 } + /// Check if Risc-V is disabled pub fn risc_disabled(&self) -> bool { (self.0 & 0x20000) >> 17 == 1 } @@ -247,8 +277,11 @@ mod sys_info_api { } #[repr(u32)] + /// CPU architectures that might be running as reported by [`cpu_info`] pub enum CpuInfo { + /// Arm CPU Arm, + /// Risc-V CPU Risc, } @@ -262,23 +295,39 @@ mod sys_info_api { } } + /// Flash device information as reported by [`flash_dev_info`] pub struct FlashDevInfo(u32); + /// A struct to represent possible byte sizes that may be reported in [`FlashDevInfo`] #[repr(u32)] pub enum FlashDevInfoSize { + /// 0 bytes None, + /// 8 KiB K8, + /// 16 KiB K16, + /// 32 KiB K32, + /// 64 KiB K64, + /// 128 KiB K128, + /// 256 KiB K256, + /// 512 KiB K512, + /// 1 MiB M1, + /// 2 MiB M2, + /// 4 Mib M4, + /// 8 MiB M8, + /// 16 MiB M16, + /// Unknown size Unknown, } @@ -293,18 +342,23 @@ mod sys_info_api { } impl FlashDevInfo { + /// GPIO Number to be used for the secondary flash chip. See datasheet section 13.9 pub fn cs1_gpio(&self) -> u8 { (self.0 & 0x1f) as _ } + /// Check if all attached devices support a block erase command with a command prefix of + /// `D8h`` pub fn d8h_erase_supported(&self) -> bool { (self.0 & 0x80) != 0 } + /// Flash/PSRAM size on chip select 0 pub fn cs0_size(&self) -> FlashDevInfoSize { FlashDevInfoSize::from((self.0 & 0xf00) >> 8) } + /// Flash/PSRAM size on chip select 1 pub fn cs1_size(&self) -> FlashDevInfoSize { FlashDevInfoSize::from((self.0 & 0xf000) >> 12) } @@ -316,7 +370,8 @@ mod sys_info_api { } } - pub struct BootRandom(u128); + /// 128 bit random integer generated per boot as reported by [`boot_random`] + pub struct BootRandom(pub u128); impl From<[u32; 4]> for BootRandom { fn from(value: [u32; 4]) -> BootRandom { @@ -329,23 +384,38 @@ mod sys_info_api { } // based on https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_bootrom/include/pico/bootrom.h + /// Boot diagnostic info as described in 5.4 under the `get_sys_info` function pub struct BootInfo { - diagnostic_partition: PartitionIndex, - boot_type: BootType, - chained: bool, - partition: i8, + /// Information about which partition is being diagnosed + pub diagnostic_partition: PartitionIndex, + /// Type of boot that occurred + pub boot_type: BootType, + /// Whether it was a chained boot + pub chained: bool, + /// What partition the boot came from + pub partition: i8, // could probably make a nicer api for tbyb, but documentation is eh so im holding off for now - tbyb_update_info: u8, - boot_diagnostic: u32, - boot_params: [u32; 2], + /// Try Before You Buy info + pub tbyb_update_info: u8, + /// boot diagnostic flags for section A and section B + pub boot_diagnostic: u32, + /// Boot parameters 0 and 1 + pub boot_params: [u32; 2], } + /// Recen boot diagnostic partition pub enum PartitionIndex { + /// A partition along with its number Partition(u8), + /// None None, + /// Slot0 Slot0, + /// Slot1 Slot1, + /// Image Image, + /// Unknown Unknown, } @@ -365,12 +435,19 @@ mod sys_info_api { } } + /// The type of boot that occurred pub enum BootType { + /// Normal Normal, + /// bootsel BootSel, + /// Ram image RamImage, + /// Flash update FlashUpdate, + /// pc_sp PcSp, + /// Unknown Unknown, } @@ -388,6 +465,7 @@ mod sys_info_api { } #[repr(u16)] + /// Diagnostic flags reported by the upper and lower words in [`BootInfo::boot_diagnostic`] pub enum BootDiagnosticFlags { /// The region was searched for a block loop RegionSearched = 0x0001, @@ -471,10 +549,12 @@ mod sys_info_api { (diagnostics & flag as u16) != 0 } + /// Check if the diagnostic flag in section A (the lower word) is set pub fn check_section_a_flag(&self, flag: BootDiagnosticFlags) -> bool { Self::check_flag(self.boot_diagnostic as u16, flag) } + /// Check if the diagnostic flag in section B (the upper word) is set pub fn check_section_b_flag(&self, flag: BootDiagnosticFlags) -> bool { Self::check_flag((self.boot_diagnostic >> 8) as u16, flag) } @@ -491,7 +571,8 @@ mod sys_info_api { /// the `flag` argument. `flag` is an expression that must resolve to a const variant of /// [`GetSysInfoFlag`] macro_rules! declare_get_sys_info_function { - ($function_name:ident, $ok_ret_type:ty, $flag:expr) => { + ($(#[$meta:meta])* $function_name:ident, $ok_ret_type:ty, $flag:expr) => { + $(#[$meta])* pub fn $function_name() -> Result, BootRomApiErrorCode> { const FLAG: GetSysInfoFlag = $flag; const BUFFER_LEN: usize = FLAG.buffer_length(); @@ -515,27 +596,37 @@ mod sys_info_api { }; } - /// Get the unique identifier for the chip - declare_get_sys_info_function!(chip_info, ChipInfo, GetSysInfoFlag::ChipInfo); + declare_get_sys_info_function!( + /// Get the unique identifier for the chip + chip_info, ChipInfo, GetSysInfoFlag::ChipInfo + ); - /// Get the value of the OTP critical register declare_get_sys_info_function!( + /// Get the value of the OTP critical register otp_critical_register, OtpCriticalReg, GetSysInfoFlag::Critical ); - /// Get the current running CPU's info - declare_get_sys_info_function!(cpu_info, CpuInfo, GetSysInfoFlag::CpuInfo); + declare_get_sys_info_function!( + /// Get the current running CPU's info + cpu_info, CpuInfo, GetSysInfoFlag::CpuInfo + ); - /// Get flash device info in the format of OTP FLASH_DEVINFO - declare_get_sys_info_function!(flash_dev_info, FlashDevInfo, GetSysInfoFlag::FlashDevInfo); + declare_get_sys_info_function!( + /// Get flash device info in the format of OTP FLASH_DEVINFO + flash_dev_info, FlashDevInfo, GetSysInfoFlag::FlashDevInfo + ); - /// Get a 128-bit random number generated on each boot - declare_get_sys_info_function!(boot_random, BootRandom, GetSysInfoFlag::BootRandom); + declare_get_sys_info_function!( + /// Get a 128-bit random number generated on each boot + boot_random, BootRandom, GetSysInfoFlag::BootRandom + ); - // Get diagnostic boot info - declare_get_sys_info_function!(boot_info, BootInfo, GetSysInfoFlag::BootInfo); + declare_get_sys_info_function!( + /// Get diagnostic boot info + boot_info, BootInfo, GetSysInfoFlag::BootInfo + ); } macro_rules! declare_rom_function { From f54c46e46d4b1dba02fb3dfef45f391e9f4d188e Mon Sep 17 00:00:00 2001 From: Nahla Date: Mon, 18 Nov 2024 20:04:09 -0700 Subject: [PATCH 06/15] Use new safe API for rom funcs example --- rp235x-hal-examples/src/bin/rom_funcs.rs | 186 +++++++++++++++++------ 1 file changed, 137 insertions(+), 49 deletions(-) diff --git a/rp235x-hal-examples/src/bin/rom_funcs.rs b/rp235x-hal-examples/src/bin/rom_funcs.rs index c572cb59d..e3416bd73 100644 --- a/rp235x-hal-examples/src/bin/rom_funcs.rs +++ b/rp235x-hal-examples/src/bin/rom_funcs.rs @@ -13,6 +13,7 @@ // be linked) use panic_halt as _; +use rp235x_hal::rom_data::sys_info_api::{BootType, CpuInfo, FlashDevInfoSize, PartitionIndex}; // Alias for our HAL crate use rp235x_hal as hal; @@ -234,13 +235,27 @@ fn get_sys_info_chip_info(uart: &mut T) where T: core::fmt::Write, { - let mut buffer = [0u32; 16]; - let result = unsafe { hal::rom_data::get_sys_info(buffer.as_mut_ptr(), buffer.len(), 0x0001) }; - _ = writeln!(uart, "get_sys_info(CHIP_INFO/0x0001) -> {}", result); - _ = writeln!(uart, "\tSupported Flags: {:#06x}", buffer[0]); - _ = writeln!(uart, "\tRP2350 Package ID: {:#010x}", buffer[1]); - _ = writeln!(uart, "\tRP2350 Device ID : {:#010x}", buffer[2]); - _ = writeln!(uart, "\tRP2350 Wafer ID : {:#010x}", buffer[3]); + let result = hal::rom_data::sys_info_api::chip_info(); + let result = match result { + Ok(result) => { + match result { + Some(result) => result, + None => { + _ = writeln!(uart, "chip_info() not supported"); + return; + } + } + }, + Err(e) => { + _ = writeln!(uart, "Failed to get chip info : {:?}", e); + return; + } + }; + + _ = writeln!(uart, "get_sys_info(CHIP_INFO/0x0001)"); + _ = writeln!(uart, "\tRP2350 Package ID: {:#010x}", result.package_sel); + _ = writeln!(uart, "\tRP2350 Device ID : {:#010x}", result.device_id); + _ = writeln!(uart, "\tRP2350 Wafer ID : {:#010x}", result.wafer_id); } /// Run get_sys_info with 0x0004 @@ -248,17 +263,30 @@ fn get_sys_info_cpu_info(uart: &mut T) where T: core::fmt::Write, { - let mut buffer = [0u32; 16]; - let result = unsafe { hal::rom_data::get_sys_info(buffer.as_mut_ptr(), buffer.len(), 0x0004) }; - _ = writeln!(uart, "get_sys_info(CPU_INFO/0x0004) -> {}", result); - _ = writeln!(uart, "\tSupported Flags: {:#06x}", buffer[0]); + let result = hal::rom_data::sys_info_api::cpu_info(); + let result = match result { + Ok(result) => { + match result { + Some(result) => result, + None => { + _ = writeln!(uart, "cpu_info() not supported"); + return; + } + } + }, + Err(e) => { + _ = writeln!(uart, "Failed to get cpu info: {:?}", e); + return; + } + }; + + _ = writeln!(uart, "get_sys_info(CPU_INFO/0x0004)"); _ = writeln!( uart, "\tCPU Architecture: {}", - match buffer[1] { - 0 => "Arm", - 1 => "RISC-V", - _ => "Unknown", + match result { + CpuInfo::Arm => "Arm", + CpuInfo::Risc => "RISC-V", } ); } @@ -268,28 +296,44 @@ fn get_sys_info_flash_dev_info(uart: &mut T) where T: core::fmt::Write, { - let mut buffer = [0u32; 16]; - let result = unsafe { hal::rom_data::get_sys_info(buffer.as_mut_ptr(), buffer.len(), 0x0008) }; - _ = writeln!(uart, "get_sys_info(FLASH_DEV_INFO/0x0008) -> {}", result); + let result = hal::rom_data::sys_info_api::flash_dev_info(); + let result = match result { + Ok(result) => { + match result { + Some(result) => result, + None => { + _ = writeln!(uart, "flash_dev_info() not supported"); + return; + } + } + }, + Err(e) => { + _ = writeln!(uart, "Failed to get flash device info: {:?}", e); + return; + } + }; + + _ = writeln!(uart, "get_sys_info(FLASH_DEV_INFO/0x0008)"); let size_lookup = |value| match value { - 0 => "None", - 1 => "8K", - 2 => "16K", - 3 => "32K", - 4 => "64K", - 5 => "128K", - 6 => "256K", - 7 => "512K", - 8 => "1M", - 9 => "2M", - 10 => "4M", - 11 => "8M", - 12 => "16M", - _ => "Unknown", + FlashDevInfoSize::None => "None", + FlashDevInfoSize::K8 => "8K", + FlashDevInfoSize::K16 => "16K", + FlashDevInfoSize::K32 => "32K", + FlashDevInfoSize::K64 => "64K", + FlashDevInfoSize::K128 => "128K", + FlashDevInfoSize::K256 => "256K", + FlashDevInfoSize::K512 => "512K", + FlashDevInfoSize::M1 => "1M", + FlashDevInfoSize::M2 => "2M", + FlashDevInfoSize::M4 => "4M", + FlashDevInfoSize::M8 => "8M", + FlashDevInfoSize::M16 => "16M", + FlashDevInfoSize::Unknown => "Unknown", }; - _ = writeln!(uart, "\tSupported Flags: {:#06x}", buffer[0]); - _ = writeln!(uart, "\tCS0 Size: {}", size_lookup((buffer[1] >> 8) & 15)); - _ = writeln!(uart, "\tCS1 Size: {}", size_lookup((buffer[1] >> 12) & 15)); + _ = writeln!(uart, "\tCS1 GPIO: {}", result.cs1_gpio()); + _ = writeln!(uart, "\tD8H Erase Supported: {}", result.d8h_erase_supported()); + _ = writeln!(uart, "\tCS0 Size: {}", size_lookup(result.cs0_size())); + _ = writeln!(uart, "\tCS1 Size: {}", size_lookup(result.cs1_size())); } /// Run get_sys_info with 0x0010 @@ -297,15 +341,25 @@ fn get_sys_info_boot_random(uart: &mut T) where T: core::fmt::Write, { - let mut buffer = [0u32; 16]; - let result = unsafe { hal::rom_data::get_sys_info(buffer.as_mut_ptr(), buffer.len(), 0x0010) }; - _ = writeln!(uart, "get_sys_info(BOOT_RANDOM/0x0010) -> {}", result); - _ = writeln!(uart, "\tSupported Flags: {:#06x}", buffer[0]); - let a = buffer[1]; - let b = buffer[2]; - let c = buffer[3]; - let d = buffer[4]; - _ = writeln!(uart, "\tA random number: 0x{a:08x}{b:08x}{c:08x}{d:08x}"); + let result = hal::rom_data::sys_info_api::boot_random(); + let result = match result { + Ok(result) => { + match result { + Some(result) => result, + None => { + _ = writeln!(uart, "boot_random() not supported"); + return; + } + } + }, + Err(e) => { + _ = writeln!(uart, "Failed to get random boot integer: {:?}", e); + return; + } + }; + + _ = writeln!(uart, "get_sys_info(BOOT_RANDOM/0x0010)"); + _ = writeln!(uart, "\tA random number: 0x{:32x}", result.0); } /// Run get_sys_info with 0x0040; @@ -313,11 +367,45 @@ fn get_sys_info_start_block(uart: &mut T) where T: core::fmt::Write, { - let mut buffer = [0u32; 16]; - let result = unsafe { hal::rom_data::get_sys_info(buffer.as_mut_ptr(), buffer.len(), 0x0040) }; - _ = writeln!(uart, "get_sys_info(start_block/0x0040) -> {}", result); - _ = writeln!(uart, "\tSupported Flags: {:#06x}", buffer[0]); - _ = writeln!(uart, "\tBoot Info: {:08x?}", &buffer[1..result as usize]); + let result = hal::rom_data::sys_info_api::boot_info(); + let result = match result { + Ok(result) => { + match result { + Some(result) => result, + None => { + _ = writeln!(uart, "boot_info() not supported"); + return; + } + } + }, + Err(e) => { + _ = writeln!(uart, "Failed to get boot info: {:?}", e); + return; + } + }; + + _ = writeln!(uart, "get_sys_info(start_block/0x0040)"); + _ = writeln!(uart, "\tDiagnostic Partition: {}", match result.diagnostic_partition { + PartitionIndex::Partition(_) => "Numbered partition", + PartitionIndex::None => "None", + PartitionIndex::Slot0 => "Slot 0", + PartitionIndex::Slot1 => "Slot 1", + PartitionIndex::Image => "Image", + PartitionIndex::Unknown => "Unknown", + }); + _ = writeln!(uart, "\tBoot Type: {}", match result.boot_type { + BootType::Normal => "Normal", + BootType::BootSel => "bootsel", + BootType::RamImage => "RAM image", + BootType::FlashUpdate => "Flash update", + BootType::PcSp => "pc_sp", + BootType::Unknown => "Unknown", + }); + _ = writeln!(uart, "\tChained: {}", result.chained); + _ = writeln!(uart, "\tPartition: {}", result.partition); + _ = writeln!(uart, "\tTBYB Info: {:02x}", result.tbyb_update_info); + _ = writeln!(uart, "\tBoot Diagnostic: {:04x}", result.boot_diagnostic); + _ = writeln!(uart, "\tBoot Params: {:04x}, {:04x}", result.boot_params[0], result.boot_params[1]); } /// Run get_partition_table_info From 3818c5655cb01540076c262e729d8ab3a7e56a6f Mon Sep 17 00:00:00 2001 From: Nahla Date: Mon, 18 Nov 2024 20:05:18 -0700 Subject: [PATCH 07/15] Add clippy changes to example --- rp235x-hal-examples/src/bin/rom_funcs.rs | 112 ++++++++++++----------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/rp235x-hal-examples/src/bin/rom_funcs.rs b/rp235x-hal-examples/src/bin/rom_funcs.rs index e3416bd73..867343561 100644 --- a/rp235x-hal-examples/src/bin/rom_funcs.rs +++ b/rp235x-hal-examples/src/bin/rom_funcs.rs @@ -237,13 +237,11 @@ where { let result = hal::rom_data::sys_info_api::chip_info(); let result = match result { - Ok(result) => { - match result { - Some(result) => result, - None => { - _ = writeln!(uart, "chip_info() not supported"); - return; - } + Ok(result) => match result { + Some(result) => result, + None => { + _ = writeln!(uart, "chip_info() not supported"); + return; } }, Err(e) => { @@ -265,13 +263,11 @@ where { let result = hal::rom_data::sys_info_api::cpu_info(); let result = match result { - Ok(result) => { - match result { - Some(result) => result, - None => { - _ = writeln!(uart, "cpu_info() not supported"); - return; - } + Ok(result) => match result { + Some(result) => result, + None => { + _ = writeln!(uart, "cpu_info() not supported"); + return; } }, Err(e) => { @@ -298,13 +294,11 @@ where { let result = hal::rom_data::sys_info_api::flash_dev_info(); let result = match result { - Ok(result) => { - match result { - Some(result) => result, - None => { - _ = writeln!(uart, "flash_dev_info() not supported"); - return; - } + Ok(result) => match result { + Some(result) => result, + None => { + _ = writeln!(uart, "flash_dev_info() not supported"); + return; } }, Err(e) => { @@ -331,7 +325,11 @@ where FlashDevInfoSize::Unknown => "Unknown", }; _ = writeln!(uart, "\tCS1 GPIO: {}", result.cs1_gpio()); - _ = writeln!(uart, "\tD8H Erase Supported: {}", result.d8h_erase_supported()); + _ = writeln!( + uart, + "\tD8H Erase Supported: {}", + result.d8h_erase_supported() + ); _ = writeln!(uart, "\tCS0 Size: {}", size_lookup(result.cs0_size())); _ = writeln!(uart, "\tCS1 Size: {}", size_lookup(result.cs1_size())); } @@ -343,13 +341,11 @@ where { let result = hal::rom_data::sys_info_api::boot_random(); let result = match result { - Ok(result) => { - match result { - Some(result) => result, - None => { - _ = writeln!(uart, "boot_random() not supported"); - return; - } + Ok(result) => match result { + Some(result) => result, + None => { + _ = writeln!(uart, "boot_random() not supported"); + return; } }, Err(e) => { @@ -369,13 +365,11 @@ where { let result = hal::rom_data::sys_info_api::boot_info(); let result = match result { - Ok(result) => { - match result { - Some(result) => result, - None => { - _ = writeln!(uart, "boot_info() not supported"); - return; - } + Ok(result) => match result { + Some(result) => result, + None => { + _ = writeln!(uart, "boot_info() not supported"); + return; } }, Err(e) => { @@ -385,27 +379,39 @@ where }; _ = writeln!(uart, "get_sys_info(start_block/0x0040)"); - _ = writeln!(uart, "\tDiagnostic Partition: {}", match result.diagnostic_partition { - PartitionIndex::Partition(_) => "Numbered partition", - PartitionIndex::None => "None", - PartitionIndex::Slot0 => "Slot 0", - PartitionIndex::Slot1 => "Slot 1", - PartitionIndex::Image => "Image", - PartitionIndex::Unknown => "Unknown", - }); - _ = writeln!(uart, "\tBoot Type: {}", match result.boot_type { - BootType::Normal => "Normal", - BootType::BootSel => "bootsel", - BootType::RamImage => "RAM image", - BootType::FlashUpdate => "Flash update", - BootType::PcSp => "pc_sp", - BootType::Unknown => "Unknown", - }); + _ = writeln!( + uart, + "\tDiagnostic Partition: {}", + match result.diagnostic_partition { + PartitionIndex::Partition(_) => "Numbered partition", + PartitionIndex::None => "None", + PartitionIndex::Slot0 => "Slot 0", + PartitionIndex::Slot1 => "Slot 1", + PartitionIndex::Image => "Image", + PartitionIndex::Unknown => "Unknown", + } + ); + _ = writeln!( + uart, + "\tBoot Type: {}", + match result.boot_type { + BootType::Normal => "Normal", + BootType::BootSel => "bootsel", + BootType::RamImage => "RAM image", + BootType::FlashUpdate => "Flash update", + BootType::PcSp => "pc_sp", + BootType::Unknown => "Unknown", + } + ); _ = writeln!(uart, "\tChained: {}", result.chained); _ = writeln!(uart, "\tPartition: {}", result.partition); _ = writeln!(uart, "\tTBYB Info: {:02x}", result.tbyb_update_info); _ = writeln!(uart, "\tBoot Diagnostic: {:04x}", result.boot_diagnostic); - _ = writeln!(uart, "\tBoot Params: {:04x}, {:04x}", result.boot_params[0], result.boot_params[1]); + _ = writeln!( + uart, + "\tBoot Params: {:04x}, {:04x}", + result.boot_params[0], result.boot_params[1] + ); } /// Run get_partition_table_info From 2c7ccd50cb92a213c9591f365de63c8cee973583 Mon Sep 17 00:00:00 2001 From: Nahla Date: Sat, 23 Nov 2024 11:37:15 -0700 Subject: [PATCH 08/15] added comments to clarify buffer_length function --- rp235x-hal/src/rom_data.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index b42a1680c..7d85e4daf 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -194,6 +194,10 @@ pub mod sys_info_api { } impl GetSysInfoFlag { + /// Returns the length of the buffer needed to hold the data for the related operation returned + /// by [`super::get_sys_info()`]. This includes the initial segment to indicate which flags + /// were supported. The underlying enum represent a bitmask and these masks can be OR'd + /// together, however the safe API only uses one at a time so adding sizes is not a concern. const fn buffer_length(&self) -> usize { match self { GetSysInfoFlag::ChipInfo => 4, From cb0f04bd0cbb6fd80af3e19f27a3a94036d65216 Mon Sep 17 00:00:00 2001 From: Nahla Date: Sat, 23 Nov 2024 11:37:30 -0700 Subject: [PATCH 09/15] collapsed match per feedback to make more readable --- rp235x-hal-examples/src/bin/rom_funcs.rs | 65 +++++++++--------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/rp235x-hal-examples/src/bin/rom_funcs.rs b/rp235x-hal-examples/src/bin/rom_funcs.rs index 867343561..54376c1e5 100644 --- a/rp235x-hal-examples/src/bin/rom_funcs.rs +++ b/rp235x-hal-examples/src/bin/rom_funcs.rs @@ -235,14 +235,11 @@ fn get_sys_info_chip_info(uart: &mut T) where T: core::fmt::Write, { - let result = hal::rom_data::sys_info_api::chip_info(); - let result = match result { - Ok(result) => match result { - Some(result) => result, - None => { - _ = writeln!(uart, "chip_info() not supported"); - return; - } + let result = match hal::rom_data::sys_info_api::chip_info() { + Ok(Some(result)) => result, + Ok(None) => { + _ = writeln!(uart, "chip_info() not supported"); + return; }, Err(e) => { _ = writeln!(uart, "Failed to get chip info : {:?}", e); @@ -261,14 +258,11 @@ fn get_sys_info_cpu_info(uart: &mut T) where T: core::fmt::Write, { - let result = hal::rom_data::sys_info_api::cpu_info(); - let result = match result { - Ok(result) => match result { - Some(result) => result, - None => { - _ = writeln!(uart, "cpu_info() not supported"); - return; - } + let result = match hal::rom_data::sys_info_api::cpu_info() { + Ok(Some(result)) => result, + Ok(None) => { + _ = writeln!(uart, "cpu_info() not supported"); + return; }, Err(e) => { _ = writeln!(uart, "Failed to get cpu info: {:?}", e); @@ -292,14 +286,11 @@ fn get_sys_info_flash_dev_info(uart: &mut T) where T: core::fmt::Write, { - let result = hal::rom_data::sys_info_api::flash_dev_info(); - let result = match result { - Ok(result) => match result { - Some(result) => result, - None => { - _ = writeln!(uart, "flash_dev_info() not supported"); - return; - } + let result = match hal::rom_data::sys_info_api::flash_dev_info() { + Ok(Some(result)) => result, + Ok(None) => { + _ = writeln!(uart, "flash_dev_info() not supported"); + return; }, Err(e) => { _ = writeln!(uart, "Failed to get flash device info: {:?}", e); @@ -339,14 +330,11 @@ fn get_sys_info_boot_random(uart: &mut T) where T: core::fmt::Write, { - let result = hal::rom_data::sys_info_api::boot_random(); - let result = match result { - Ok(result) => match result { - Some(result) => result, - None => { - _ = writeln!(uart, "boot_random() not supported"); - return; - } + let result = match hal::rom_data::sys_info_api::boot_random() { + Ok(Some(result)) => result, + Ok(None) => { + _ = writeln!(uart, "boot_random() not supported"); + return; }, Err(e) => { _ = writeln!(uart, "Failed to get random boot integer: {:?}", e); @@ -363,14 +351,11 @@ fn get_sys_info_start_block(uart: &mut T) where T: core::fmt::Write, { - let result = hal::rom_data::sys_info_api::boot_info(); - let result = match result { - Ok(result) => match result { - Some(result) => result, - None => { - _ = writeln!(uart, "boot_info() not supported"); - return; - } + let result = match hal::rom_data::sys_info_api::boot_info() { + Ok(Some(result)) => result, + Ok(None) => { + _ = writeln!(uart, "boot_info() not supported"); + return; }, Err(e) => { _ = writeln!(uart, "Failed to get boot info: {:?}", e); From 359ee138e3dad2209913fd6d2d20b8f961381b4a Mon Sep 17 00:00:00 2001 From: Nahla Date: Sat, 23 Nov 2024 11:38:39 -0700 Subject: [PATCH 10/15] added api for get_sys_info_ns --- rp235x-hal/src/rom_data.rs | 75 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index 7d85e4daf..4527dd2b8 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -600,6 +600,43 @@ pub mod sys_info_api { }; } + #[macro_export] + #[cfg(all(target_arch = "arm", target_os = "none"))] + /// Generates a function with the following signature: + /// + /// ```rs + /// pub fn $function_name() -> Result, BootRomApiErrorCode> + /// ``` + /// + /// Which safely calls [`get_sys_info_ns`](super::get_sys_info_ns()) using the flag provided via + /// the `flag` argument. `flag` is an expression that must resolve to a const variant of + /// [`GetSysInfoFlag`] + macro_rules! declare_get_sys_info_ns_function { + ($(#[$meta:meta])* $function_name:ident, $ok_ret_type:ty, $flag:expr) => { + $(#[$meta])* + pub fn $function_name() -> Result, BootRomApiErrorCode> { + const FLAG: GetSysInfoFlag = $flag; + const BUFFER_LEN: usize = FLAG.buffer_length(); + let mut buffer = [0u32; FLAG.buffer_length()]; + let result = + unsafe { super::get_sys_info_ns(buffer.as_mut_ptr(), buffer.len(), FLAG as u32) }; + + if result < 0 { + return Err(BootRomApiErrorCode::from(result)); + } + // The operation returned successfully but the flag wasn't supported + // for one reason or another + else if buffer[0] == 0 { + return Ok(None); + } + + Ok(Some(<$ok_ret_type>::from( + TryInto::<[u32; BUFFER_LEN - 1]>::try_into(&buffer[1..]).unwrap(), + ))) + } + }; + } + declare_get_sys_info_function!( /// Get the unique identifier for the chip chip_info, ChipInfo, GetSysInfoFlag::ChipInfo @@ -631,6 +668,44 @@ pub mod sys_info_api { /// Get diagnostic boot info boot_info, BootInfo, GetSysInfoFlag::BootInfo ); + + #[cfg(all(target_arch = "arm", target_os = "none"))] + declare_get_sys_info_function!( + /// Get the unique identifier for the chip + chip_info_ns, ChipInfo, GetSysInfoFlag::ChipInfo + ); + + #[cfg(all(target_arch = "arm", target_os = "none"))] + declare_get_sys_info_function!( + /// Get the value of the OTP critical register + otp_critical_register_ns, + OtpCriticalReg, + GetSysInfoFlag::Critical + ); + + #[cfg(all(target_arch = "arm", target_os = "none"))] + declare_get_sys_info_function!( + /// Get the current running CPU's info + cpu_info_ns, CpuInfo, GetSysInfoFlag::CpuInfo + ); + + #[cfg(all(target_arch = "arm", target_os = "none"))] + declare_get_sys_info_function!( + /// Get flash device info in the format of OTP FLASH_DEVINFO + flash_dev_info_ns, FlashDevInfo, GetSysInfoFlag::FlashDevInfo + ); + + #[cfg(all(target_arch = "arm", target_os = "none"))] + declare_get_sys_info_function!( + /// Get a 128-bit random number generated on each boot + boot_random_ns, BootRandom, GetSysInfoFlag::BootRandom + ); + + #[cfg(all(target_arch = "arm", target_os = "none"))] + declare_get_sys_info_function!( + /// Get diagnostic boot info + boot_info_ns, BootInfo, GetSysInfoFlag::BootInfo + ); } macro_rules! declare_rom_function { From b955746ce2d4346c7ff23d01496399ef39fc6063 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 23 Nov 2024 18:59:25 +0000 Subject: [PATCH 11/15] Update rp235x-hal/src/rom_data.rs --- rp235x-hal/src/rom_data.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index 7d85e4daf..e0bc7cb83 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -587,9 +587,9 @@ pub mod sys_info_api { if result < 0 { return Err(BootRomApiErrorCode::from(result)); } - // The operation returned successfully but the flag wasn't supported - // for one reason or another else if buffer[0] == 0 { + // The operation returned successfully but the flag wasn't supported + // for one reason or another return Ok(None); } From 1365e403511d97ab848d4268957b232147fa8475 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 23 Nov 2024 18:59:58 +0000 Subject: [PATCH 12/15] Update rp235x-hal/src/rom_data.rs --- rp235x-hal/src/rom_data.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index e0bc7cb83..3cd7b55c9 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -586,8 +586,7 @@ pub mod sys_info_api { if result < 0 { return Err(BootRomApiErrorCode::from(result)); - } - else if buffer[0] == 0 { + } else if buffer[0] == 0 { // The operation returned successfully but the flag wasn't supported // for one reason or another return Ok(None); From 592c1f2f47314c6b251cca6d5ab1842f1225ac7f Mon Sep 17 00:00:00 2001 From: Nahla Date: Sat, 23 Nov 2024 12:35:48 -0700 Subject: [PATCH 13/15] cargo fmt --- rp235x-hal-examples/src/bin/rom_funcs.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rp235x-hal-examples/src/bin/rom_funcs.rs b/rp235x-hal-examples/src/bin/rom_funcs.rs index 54376c1e5..73a8d7ab9 100644 --- a/rp235x-hal-examples/src/bin/rom_funcs.rs +++ b/rp235x-hal-examples/src/bin/rom_funcs.rs @@ -240,7 +240,7 @@ where Ok(None) => { _ = writeln!(uart, "chip_info() not supported"); return; - }, + } Err(e) => { _ = writeln!(uart, "Failed to get chip info : {:?}", e); return; @@ -263,7 +263,7 @@ where Ok(None) => { _ = writeln!(uart, "cpu_info() not supported"); return; - }, + } Err(e) => { _ = writeln!(uart, "Failed to get cpu info: {:?}", e); return; @@ -291,7 +291,7 @@ where Ok(None) => { _ = writeln!(uart, "flash_dev_info() not supported"); return; - }, + } Err(e) => { _ = writeln!(uart, "Failed to get flash device info: {:?}", e); return; @@ -335,7 +335,7 @@ where Ok(None) => { _ = writeln!(uart, "boot_random() not supported"); return; - }, + } Err(e) => { _ = writeln!(uart, "Failed to get random boot integer: {:?}", e); return; @@ -356,7 +356,7 @@ where Ok(None) => { _ = writeln!(uart, "boot_info() not supported"); return; - }, + } Err(e) => { _ = writeln!(uart, "Failed to get boot info: {:?}", e); return; From 88b8873550f011116c6ab7416b9870b2760f8e1a Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 23 Nov 2024 20:37:18 +0000 Subject: [PATCH 14/15] Update rp235x-hal/src/rom_data.rs --- rp235x-hal/src/rom_data.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index dd1217b5c..84ee26829 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -622,10 +622,9 @@ pub mod sys_info_api { if result < 0 { return Err(BootRomApiErrorCode::from(result)); - } - // The operation returned successfully but the flag wasn't supported - // for one reason or another - else if buffer[0] == 0 { + } else if buffer[0] == 0 { + // The operation returned successfully but the flag wasn't supported + // for one reason or another return Ok(None); } From 13c62ca09b9eb5436a55f8b742e5e8ff0a173151 Mon Sep 17 00:00:00 2001 From: Nahla Date: Sat, 23 Nov 2024 14:12:35 -0700 Subject: [PATCH 15/15] call correct macro for ns functions --- rp235x-hal/src/rom_data.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rp235x-hal/src/rom_data.rs b/rp235x-hal/src/rom_data.rs index 84ee26829..dcb8d988a 100644 --- a/rp235x-hal/src/rom_data.rs +++ b/rp235x-hal/src/rom_data.rs @@ -668,13 +668,13 @@ pub mod sys_info_api { ); #[cfg(all(target_arch = "arm", target_os = "none"))] - declare_get_sys_info_function!( + declare_get_sys_info_ns_function!( /// Get the unique identifier for the chip chip_info_ns, ChipInfo, GetSysInfoFlag::ChipInfo ); #[cfg(all(target_arch = "arm", target_os = "none"))] - declare_get_sys_info_function!( + declare_get_sys_info_ns_function!( /// Get the value of the OTP critical register otp_critical_register_ns, OtpCriticalReg, @@ -682,25 +682,25 @@ pub mod sys_info_api { ); #[cfg(all(target_arch = "arm", target_os = "none"))] - declare_get_sys_info_function!( + declare_get_sys_info_ns_function!( /// Get the current running CPU's info cpu_info_ns, CpuInfo, GetSysInfoFlag::CpuInfo ); #[cfg(all(target_arch = "arm", target_os = "none"))] - declare_get_sys_info_function!( + declare_get_sys_info_ns_function!( /// Get flash device info in the format of OTP FLASH_DEVINFO flash_dev_info_ns, FlashDevInfo, GetSysInfoFlag::FlashDevInfo ); #[cfg(all(target_arch = "arm", target_os = "none"))] - declare_get_sys_info_function!( + declare_get_sys_info_ns_function!( /// Get a 128-bit random number generated on each boot boot_random_ns, BootRandom, GetSysInfoFlag::BootRandom ); #[cfg(all(target_arch = "arm", target_os = "none"))] - declare_get_sys_info_function!( + declare_get_sys_info_ns_function!( /// Get diagnostic boot info boot_info_ns, BootInfo, GetSysInfoFlag::BootInfo );