diff --git a/libs/bao1x-api/src/offsets.rs b/libs/bao1x-api/src/offsets.rs index 829c0e049..c26db0326 100644 --- a/libs/bao1x-api/src/offsets.rs +++ b/libs/bao1x-api/src/offsets.rs @@ -1,99 +1,4 @@ -// These define the start region of the partition. In general, each partition has signature -// metadata in them, but the first word in the signature is a jump instruction that takes you -// to the actual boot code. -pub const BOOT0_START: usize = 0x6000_0000; -pub const BOOT1_START: usize = 0x6002_0000; -pub const LOADER_START: usize = 0x6006_0000; -pub const BAREMETAL_START: usize = LOADER_START; -// kernel needs to start on a page boundary, so eat into the loader area a bit to allow that to happen. -pub const KERNEL_START: usize = 0x6008_0000 - crate::signatures::SIGBLOCK_LEN; - -// total storage area available in RRAM. Above this are reserved vectors for security apparatus. -pub const RRAM_STORAGE_LEN: usize = 0x3D_A000; - -// loadable apps all "start" at this address for UF2 updates -// however these are remapped into external flash based on a defragmentation table -// and app ID. The app ID also has to get encoded into this offset, likely to be -// stuck in bits 24-27, to give up to 16 app slots of up to 8MiB in size. -pub const APP_START_UF2: usize = 0x7000_0000; - -// Define a trait with just the offset -pub trait OneWayEncoding: TryFrom { - const OFFSET: usize; -} - -macro_rules! encode_oneway { - ( - #[offset = $offset:literal] - $(#[$meta:meta])* - pub enum $name:ident { - $( - $variant:ident - ),* $(,)? - } - ) => { - $(#[$meta])* - #[repr(u32)] - #[derive(Debug, Clone, Copy, PartialEq)] - pub enum $name { - $( - $variant - ),* - } - - impl $name { - const ALL: &'static [Self] = &[ - $(Self::$variant),* - ]; - } - - impl TryFrom for $name { - type Error = (); - - fn try_from(value: u32) -> Result { - let index = (value % Self::ALL.len() as u32) as usize; - Ok(Self::ALL[index]) - } - } - - impl OneWayEncoding for $name { - const OFFSET: usize = $offset; - } - }; -} - -encode_oneway! { - #[offset = 80] - pub enum BootWaitCoding { - Disable, - Enable, - } -} - -encode_oneway! { - #[offset = 81] - pub enum BoardTypeCoding { - Baosec, - Dabao, - Oem, - } -} - -encode_oneway! { - #[offset = 82] - pub enum AltBootCoding { - PrimaryPartition, - AlternatePartition, - } -} - -pub const PUBKEY_SLOTS: usize = 4; -/// Offset in the one-way counter array for loader key revocations. Provisions for up to four -/// key slots, from [116..=120]. -pub const LOADER_REVOCATION_OFFSET: usize = 116; -/// Offset in the one-way counter array for boot1 key revocations. Provisions for up to four -/// key slots, from [120..=123]. -pub const BOOT1_REVOCATION_OFFSET: usize = LOADER_REVOCATION_OFFSET + PUBKEY_SLOTS; -/// Offset in the one-way counter array for boot0 key revocations. Provisions for up to four -/// key slots, from [124..=127]. -pub const BOOT0_REVOCATION_OFFSET: usize = BOOT1_REVOCATION_OFFSET + PUBKEY_SLOTS; +pub mod baosec; +pub mod common; +pub use common::*; +pub mod dabao; diff --git a/libs/bao1x-api/src/offsets/baosec.rs b/libs/bao1x-api/src/offsets/baosec.rs new file mode 100644 index 000000000..af6787183 --- /dev/null +++ b/libs/bao1x-api/src/offsets/baosec.rs @@ -0,0 +1,33 @@ +// we actually have 16MiB on the initial prototypes, but constraining to smaller for cost reduction +pub const SPI_FLASH_LEN: usize = 8192 * 1024; +pub const SPI_FLASH_ID_MASK: u32 = 0xff_ff_ff; +// density 18, memory type 20, mfg ID C2 ==> MX25L128833F +// density 38, memory type 25, mfg ID C2 ==> MX25U12832F +// mfg ID 0b ==> XT25Q64FWOIGT cost down option (8MiB) +pub const SPI_FLASH_IDS: [u32; 3] = [0x1820c2, 0x3825c2, 0x17_60_0b]; + +// details of the SPINOR device +pub const SPINOR_PAGE_LEN: u32 = 0x100; +pub const SPINOR_ERASE_SIZE: u32 = 0x1000; // this is the smallest sector size. +pub const SPINOR_BULK_ERASE_SIZE: u32 = 0x1_0000; // this is the bulk erase size. + +// 4MiB vs 8MiB memory price is a very nominal difference (~$0.20 off of $2.40 budgetary) +// So it's either all-or-nothing: either we have 8MiB, or we have none, in the final +// configuration. +pub const SWAP_RAM_LEN: usize = 8192 * 1024; +pub const SWAP_RAM_ID_MASK: u32 = 0xff_ff; +// KGD 5D, mfg ID 9D; remainder of bits are part of the EID +pub const SWAP_RAM_IDS: [u32; 2] = [0x5d9d, 0x559d]; + +// "Partition table" of external SPI FLASH +pub const SWAP_FLASH_ORIGIN: usize = 0x0000_0000; +pub const SWAP_FLASH_RESERVED_LEN: usize = 4096 * 1024; + +// PDDB takes up "the rest of the space" - about 4MiB envisioned. Should be +// "enough" for storing a few hundred, passwords, dozens of x.509 certs, dozens of private keys, etc. +pub const PDDB_ORIGIN: usize = SWAP_FLASH_ORIGIN + SWAP_FLASH_RESERVED_LEN; +pub const PDDB_LEN: usize = SPI_FLASH_LEN - PDDB_ORIGIN; + +// Location of on-chip application segment, as offset from RRAM start +pub const APP_RRAM_OFFSET: usize = 0; +pub const APP_RRAM_LEN: usize = 0; diff --git a/libs/bao1x-api/src/offsets/common.rs b/libs/bao1x-api/src/offsets/common.rs new file mode 100644 index 000000000..78111976d --- /dev/null +++ b/libs/bao1x-api/src/offsets/common.rs @@ -0,0 +1,98 @@ +// These define the start region of the partition. In general, each partition has signature +// metadata in them, but the first word in the signature is a jump instruction that takes you +// to the actual boot code. +pub const BOOT0_START: usize = 0x6000_0000; +pub const BOOT1_START: usize = 0x6002_0000; +pub const LOADER_START: usize = 0x6006_0000; +pub const BAREMETAL_START: usize = LOADER_START; +// kernel needs to start on a page boundary, so eat into the loader area a bit to allow that to happen. +pub const KERNEL_START: usize = 0x6008_0000 - crate::signatures::SIGBLOCK_LEN; + +// total storage area available in RRAM. Above this are reserved vectors for security apparatus. +pub const RRAM_STORAGE_LEN: usize = 0x3D_A000; + +// loadable swap "starts" at these address for UF2 updates. They are are interpreted as +// zero-offsets from their respective "partitions" after masking for the top address location. +pub const SWAP_START_UF2: usize = 0x7000_0000; +pub const SWAP_UF2_LEN: usize = 0x0800_0000; // 128 MiB + +// Define a trait with just the offset +pub trait OneWayEncoding: TryFrom { + const OFFSET: usize; +} + +macro_rules! encode_oneway { + ( + #[offset = $offset:literal] + $(#[$meta:meta])* + pub enum $name:ident { + $( + $variant:ident + ),* $(,)? + } + ) => { + $(#[$meta])* + #[repr(u32)] + #[derive(Debug, Clone, Copy, PartialEq)] + pub enum $name { + $( + $variant + ),* + } + + impl $name { + const ALL: &'static [Self] = &[ + $(Self::$variant),* + ]; + } + + impl TryFrom for $name { + type Error = (); + + fn try_from(value: u32) -> Result { + let index = (value % Self::ALL.len() as u32) as usize; + Ok(Self::ALL[index]) + } + } + + impl OneWayEncoding for $name { + const OFFSET: usize = $offset; + } + }; +} + +encode_oneway! { + #[offset = 80] + pub enum BootWaitCoding { + Disable, + Enable, + } +} + +encode_oneway! { + #[offset = 81] + pub enum BoardTypeCoding { + Baosec, + Dabao, + Oem, + } +} + +encode_oneway! { + #[offset = 82] + pub enum AltBootCoding { + PrimaryPartition, + AlternatePartition, + } +} + +pub const PUBKEY_SLOTS: usize = 4; +/// Offset in the one-way counter array for loader key revocations. Provisions for up to four +/// key slots, from [116..=120]. +pub const LOADER_REVOCATION_OFFSET: usize = 116; +/// Offset in the one-way counter array for boot1 key revocations. Provisions for up to four +/// key slots, from [120..=123]. +pub const BOOT1_REVOCATION_OFFSET: usize = LOADER_REVOCATION_OFFSET + PUBKEY_SLOTS; +/// Offset in the one-way counter array for boot0 key revocations. Provisions for up to four +/// key slots, from [124..=127]. +pub const BOOT0_REVOCATION_OFFSET: usize = BOOT1_REVOCATION_OFFSET + PUBKEY_SLOTS; diff --git a/libs/bao1x-api/src/offsets/dabao.rs b/libs/bao1x-api/src/offsets/dabao.rs new file mode 100644 index 000000000..1df794854 --- /dev/null +++ b/libs/bao1x-api/src/offsets/dabao.rs @@ -0,0 +1,24 @@ +// no external SPI +pub const SPI_FLASH_LEN: usize = 0; +pub const SPI_FLASH_ID_MASK: u32 = 0xff_ff_ff; +pub const SPI_FLASH_IDS: [u32; 0] = []; + +// no external RAM +pub const SWAP_RAM_LEN: usize = 0; +pub const SWAP_RAM_ID_MASK: u32 = 0xff_ff; +// KGD 5D, mfg ID 9D; remainder of bits are part of the EID +pub const SWAP_RAM_IDS: [u32; 0] = []; + +// "Partition table" of external SPI FLASH +pub const SWAP_FLASH_ORIGIN: usize = 0x0000_0000; +pub const SWAP_FLASH_RESERVED_LEN: usize = 0; +pub const APP_FLASH_ORIGIN: usize = 0; +pub const APP_FLASH_RESERVED_LEN: usize = 0; + +// No PDDB, because no FLASH +pub const PDDB_ORIGIN: usize = 0; +pub const PDDB_LEN: usize = 0; + +// Location of on-chip application segment, as offset from RRAM start +pub const APP_RRAM_OFFSET: usize = 0x30_0000; +pub const APP_RRAM_LEN: usize = 0xD_A000; diff --git a/libs/bao1x-api/src/signatures.rs b/libs/bao1x-api/src/signatures.rs index 01fbe0460..c3b187bab 100644 --- a/libs/bao1x-api/src/signatures.rs +++ b/libs/bao1x-api/src/signatures.rs @@ -29,6 +29,9 @@ pub enum FunctionCode { /// Kernel region Kernel = 0x1_00, UpdatedKernel = 0x1_01, + /// Swap region + Swap = 0x80_00, + UpdatedSwap = 0x80_01, /// Application region App = 0x10_0000, UpdatedApp = 0x10_0001, @@ -93,3 +96,35 @@ pub struct SealedFields { impl AsRef<[u8]> for SealedFields { fn as_ref(&self) -> &[u8] { bytemuck::bytes_of(self) } } + +#[derive(Debug, Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct SwapSourceHeader { + pub version: u32, + pub partial_nonce: [u8; 8], + pub mac_offset: u32, + pub aad_len: u32, + // aad is limited to 64 bytes! + pub aad: [u8; 64], +} +impl AsRef<[u8]> for SwapSourceHeader { + fn as_ref(&self) -> &[u8] { bytemuck::bytes_of(self) } +} +impl Default for SwapSourceHeader { + fn default() -> Self { + Self { version: 0, partial_nonce: [0; 8], mac_offset: 0, aad_len: 0, aad: [0; 64] } + } +} + +#[repr(C)] +#[derive(Debug, Clone, Copy, Pod, Zeroable, Default)] +pub struct SwapDescriptor { + pub ram_offset: u32, + pub ram_size: u32, + pub name: u32, + pub key: [u8; 32], + pub flash_offset: u32, +} +impl AsRef<[u8]> for SwapDescriptor { + fn as_ref(&self) -> &[u8] { bytemuck::bytes_of(self) } +}