1pub const ITEM_1BS_VECTOR_TABLE: u8 = 0x03;
13
14pub const ITEM_1BS_ROLLING_WINDOW_DELTA: u8 = 0x05;
16
17pub const ITEM_1BS_SIGNATURE: u8 = 0x09;
19
20pub const ITEM_1BS_SALT: u8 = 0x0c;
22
23pub const ITEM_1BS_IMAGE_TYPE: u8 = 0x42;
25
26pub const ITEM_1BS_ENTRY_POINT: u8 = 0x44;
28
29pub const ITEM_2BS_HASH_DEF: u8 = 0x47;
31
32pub const ITEM_1BS_VERSION: u8 = 0x48;
34
35pub const ITEM_1BS_HASH_VALUE: u8 = 0x4b;
37
38pub const ITEM_2BS_LOAD_MAP: u8 = 0x06;
42
43pub const ITEM_2BS_PARTITION_TABLE: u8 = 0x0a;
45
46pub const ITEM_2BS_IGNORED: u8 = 0xfe;
50
51pub const ITEM_2BS_LAST: u8 = 0xff;
55
56pub const IMAGE_TYPE_INVALID: u16 = 0x0000;
60
61pub const IMAGE_TYPE_EXE: u16 = 0x0001;
63
64pub const IMAGE_TYPE_DATA: u16 = 0x0002;
66
67pub const IMAGE_TYPE_EXE_TYPE_SECURITY_UNSPECIFIED: u16 = 0x0000;
69
70pub const IMAGE_TYPE_EXE_TYPE_SECURITY_NS: u16 = 0x0010;
72
73pub const IMAGE_TYPE_EXE_TYPE_SECURITY_S: u16 = 0x0020;
75
76pub const IMAGE_TYPE_EXE_CPU_ARM: u16 = 0x0000;
78
79pub const IMAGE_TYPE_EXE_CPU_RISCV: u16 = 0x0100;
81
82pub const IMAGE_TYPE_EXE_CHIP_RP2040: u16 = 0x0000;
84
85pub const IMAGE_TYPE_EXE_CHIP_RP2350: u16 = 0x1000;
87
88pub const IMAGE_TYPE_TBYB: u16 = 0x8000;
94
95const BLOCK_MARKER_START: u32 = 0xffffded3;
99
100const BLOCK_MARKER_END: u32 = 0xab123579;
104
105pub type ImageDef = Block<1>;
107
108#[derive(Debug)]
116#[repr(C)]
117pub struct Block<const N: usize> {
118 marker_start: u32,
119 items: [u32; N],
120 length: u32,
121 offset: *const u32,
122 marker_end: u32,
123}
124
125unsafe impl<const N: usize> Sync for Block<N> {}
126
127impl<const N: usize> Block<N> {
128 pub const fn new(items: [u32; N]) -> Block<N> {
133 Block {
134 marker_start: BLOCK_MARKER_START,
135 items,
136 length: item_last(N as u16),
137 offset: core::ptr::null(),
140 marker_end: BLOCK_MARKER_END,
141 }
142 }
143
144 pub const fn with_offset(self, offset: *const u32) -> Block<N> {
153 Block { offset, ..self }
154 }
155}
156
157impl Block<0> {
158 pub const fn empty() -> Block<0> {
160 Block::new([])
161 }
162
163 pub const fn extend(self, word: u32) -> Block<1> {
165 Block::new([word])
166 }
167}
168
169impl Block<1> {
170 pub const fn extend(self, word: u32) -> Block<2> {
172 Block::new([self.items[0], word])
173 }
174}
175
176impl Block<2> {
177 pub const fn extend(self, word: u32) -> Block<3> {
179 Block::new([self.items[0], self.items[1], word])
180 }
181}
182
183impl ImageDef {
184 pub const fn arch_exe(security: Security, architecture: Architecture) -> Self {
187 Self::new([item_image_type_exe(security, architecture)])
188 }
189
190 pub const fn exe(security: Security) -> Self {
195 if cfg!(all(target_arch = "riscv32", target_os = "none")) {
196 Self::arch_exe(security, Architecture::Riscv)
197 } else {
198 Self::arch_exe(security, Architecture::Arm)
199 }
200 }
201
202 pub const fn non_secure_exe() -> Self {
207 Self::exe(Security::NonSecure)
208 }
209
210 pub const fn secure_exe() -> Self {
215 Self::exe(Security::Secure)
216 }
217}
218
219pub const PARTITION_TABLE_MAX_ITEMS: usize = 128;
221
222#[derive(Debug, Clone, PartialEq, Eq, Default)]
224pub struct UnpartitionedSpace {
225 permissions_and_location: u32,
226 permissions_and_flags: u32,
227}
228
229impl UnpartitionedSpace {
230 pub const fn new() -> Self {
234 Self {
235 permissions_and_location: 0,
236 permissions_and_flags: 0,
237 }
238 }
239
240 pub const fn from_raw(permissions_and_location: u32, permissions_and_flags: u32) -> Self {
244 Self {
245 permissions_and_location,
246 permissions_and_flags,
247 }
248 }
249
250 pub const fn with_permission(self, permission: Permission) -> Self {
252 Self {
253 permissions_and_flags: self.permissions_and_flags | permission as u32,
254 permissions_and_location: self.permissions_and_location | permission as u32,
255 }
256 }
257
258 pub const fn with_flag(self, flag: UnpartitionedFlag) -> Self {
260 Self {
261 permissions_and_flags: self.permissions_and_flags | flag as u32,
262 ..self
263 }
264 }
265
266 pub fn get_first_last_sectors(&self) -> (u16, u16) {
270 (
271 (self.permissions_and_location & 0x0000_1FFF) as u16,
272 ((self.permissions_and_location >> 13) & 0x0000_1FFF) as u16,
273 )
274 }
275
276 pub fn get_first_last_bytes(&self) -> (u32, u32) {
280 let (first, last) = self.get_first_last_sectors();
281 (u32::from(first) * 4096, (u32::from(last) * 4096) + 4095)
282 }
283
284 pub fn has_permission(&self, permission: Permission) -> bool {
286 let mask = permission as u32;
287 (self.permissions_and_flags & mask) != 0
288 }
289
290 pub fn has_flag(&self, flag: UnpartitionedFlag) -> bool {
292 let mask = flag as u32;
293 (self.permissions_and_flags & mask) != 0
294 }
295}
296
297impl core::fmt::Display for UnpartitionedSpace {
298 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
299 let (first, last) = self.get_first_last_bytes();
300 write!(
301 f,
302 "{:#010x}..{:#010x} S:{}{} NS:{}{} B:{}{}",
303 first,
304 last,
305 if self.has_permission(Permission::SecureRead) {
306 'R'
307 } else {
308 '_'
309 },
310 if self.has_permission(Permission::SecureWrite) {
311 'W'
312 } else {
313 '_'
314 },
315 if self.has_permission(Permission::NonSecureRead) {
316 'R'
317 } else {
318 '_'
319 },
320 if self.has_permission(Permission::NonSecureWrite) {
321 'W'
322 } else {
323 '_'
324 },
325 if self.has_permission(Permission::BootRead) {
326 'R'
327 } else {
328 '_'
329 },
330 if self.has_permission(Permission::BootWrite) {
331 'W'
332 } else {
333 '_'
334 }
335 )
336 }
337}
338
339#[derive(Debug, Clone, PartialEq, Eq)]
341pub struct Partition {
342 permissions_and_location: u32,
343 permissions_and_flags: u32,
344 id: Option<u64>,
345 extra_families: [u32; 4],
346 extra_families_len: usize,
347 name: [u8; 128],
348}
349
350impl Partition {
351 const FLAGS_HAS_ID: u32 = 0b1;
352 const FLAGS_LINK_TYPE_A_PARTITION: u32 = 0b01 << 1;
353 const FLAGS_LINK_TYPE_OWNER: u32 = 0b10 << 1;
354 const FLAGS_LINK_MASK: u32 = 0b111111 << 1;
355 const FLAGS_HAS_NAME: u32 = 0b1 << 12;
356 const FLAGS_HAS_EXTRA_FAMILIES_SHIFT: u8 = 7;
357 const FLAGS_HAS_EXTRA_FAMILIES_MASK: u32 = 0b11 << Self::FLAGS_HAS_EXTRA_FAMILIES_SHIFT;
358
359 pub const fn new(first_sector: u16, last_sector: u16) -> Self {
363 assert!(first_sector < 0x2000);
365 assert!(last_sector < 0x2000);
366 assert!(first_sector <= last_sector);
367 Self {
368 permissions_and_location: ((last_sector as u32) << 13) | first_sector as u32,
369 permissions_and_flags: 0,
370 id: None,
371 extra_families: [0; 4],
372 extra_families_len: 0,
373 name: [0; 128],
374 }
375 }
376
377 pub const fn from_raw(permissions_and_location: u32, permissions_and_flags: u32) -> Self {
381 Self {
382 permissions_and_location,
383 permissions_and_flags,
384 id: None,
385 extra_families: [0; 4],
386 extra_families_len: 0,
387 name: [0; 128],
388 }
389 }
390
391 pub const fn with_permission(self, permission: Permission) -> Self {
393 Self {
394 permissions_and_location: self.permissions_and_location | permission as u32,
395 permissions_and_flags: self.permissions_and_flags | permission as u32,
396 ..self
397 }
398 }
399
400 pub const fn with_name(self, name: &str) -> Self {
402 let mut new_name = [0u8; 128];
403 let name = name.as_bytes();
404 let mut idx = 0;
405 new_name[0] = name.len() as u8;
406 while idx < name.len() {
407 new_name[idx + 1] = name[idx];
408 idx += 1;
409 }
410 Self {
411 name: new_name,
412 permissions_and_flags: self.permissions_and_flags | Self::FLAGS_HAS_NAME,
413 ..self
414 }
415 }
416
417 pub const fn with_extra_families(self, extra_families: &[u32]) -> Self {
421 assert!(extra_families.len() <= 4);
422 let mut new_extra_families = [0u32; 4];
423 let mut idx = 0;
424 while idx < extra_families.len() {
425 new_extra_families[idx] = extra_families[idx];
426 idx += 1;
427 }
428 Self {
429 extra_families: new_extra_families,
430 extra_families_len: extra_families.len(),
431 permissions_and_flags: (self.permissions_and_flags
432 & !Self::FLAGS_HAS_EXTRA_FAMILIES_MASK)
433 | ((extra_families.len() as u32) << Self::FLAGS_HAS_EXTRA_FAMILIES_SHIFT),
434 ..self
435 }
436 }
437
438 pub const fn with_id(self, id: u64) -> Self {
440 Self {
441 id: Some(id),
442 permissions_and_flags: self.permissions_and_flags | Self::FLAGS_HAS_ID,
443 ..self
444 }
445 }
446
447 pub const fn with_link(self, link: Link) -> Self {
449 let mut new_flags = self.permissions_and_flags & !Self::FLAGS_LINK_MASK;
450 match link {
451 Link::Nothing => {}
452 Link::ToA { partition_idx } => {
453 assert!(partition_idx < 16);
454 new_flags |= Self::FLAGS_LINK_TYPE_A_PARTITION;
455 new_flags |= (partition_idx as u32) << 3;
456 }
457 Link::ToOwner { partition_idx } => {
458 assert!(partition_idx < 16);
459 new_flags |= Self::FLAGS_LINK_TYPE_OWNER;
460 new_flags |= (partition_idx as u32) << 3;
461 }
462 }
463 Self {
464 permissions_and_flags: new_flags,
465 ..self
466 }
467 }
468
469 pub const fn with_flag(self, flag: PartitionFlag) -> Self {
471 Self {
472 permissions_and_flags: self.permissions_and_flags | flag as u32,
473 ..self
474 }
475 }
476
477 pub fn get_first_last_sectors(&self) -> (u16, u16) {
481 (
482 (self.permissions_and_location & 0x0000_1FFF) as u16,
483 ((self.permissions_and_location >> 13) & 0x0000_1FFF) as u16,
484 )
485 }
486
487 pub fn get_first_last_bytes(&self) -> (u32, u32) {
491 let (first, last) = self.get_first_last_sectors();
492 (u32::from(first) * 4096, (u32::from(last) * 4096) + 4095)
493 }
494
495 pub fn has_permission(&self, permission: Permission) -> bool {
497 let mask = permission as u32;
498 (self.permissions_and_flags & mask) != 0
499 }
500
501 pub fn get_extra_families(&self) -> &[u32] {
503 &self.extra_families[0..self.extra_families_len]
504 }
505
506 pub fn get_name(&self) -> Option<&str> {
510 let len = self.name[0] as usize;
511 if len == 0 {
512 None
513 } else {
514 core::str::from_utf8(&self.name[1..=len]).ok()
515 }
516 }
517
518 pub fn get_id(&self) -> Option<u64> {
520 self.id
521 }
522
523 pub fn get_link(&self) -> Link {
525 if (self.permissions_and_flags & Self::FLAGS_LINK_TYPE_A_PARTITION) != 0 {
526 let partition_idx = ((self.permissions_and_flags >> 3) & 0x0F) as u8;
527 Link::ToA { partition_idx }
528 } else if (self.permissions_and_flags & Self::FLAGS_LINK_TYPE_OWNER) != 0 {
529 let partition_idx = ((self.permissions_and_flags >> 3) & 0x0F) as u8;
530 Link::ToOwner { partition_idx }
531 } else {
532 Link::Nothing
533 }
534 }
535
536 pub fn has_flag(&self, flag: PartitionFlag) -> bool {
538 let mask = flag as u32;
539 (self.permissions_and_flags & mask) != 0
540 }
541}
542
543impl core::fmt::Display for Partition {
544 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
545 let (first, last) = self.get_first_last_bytes();
546 write!(
547 f,
548 "{:#010x}..{:#010x} S:{}{} NS:{}{} B:{}{}",
549 first,
550 last,
551 if self.has_permission(Permission::SecureRead) {
552 'R'
553 } else {
554 '_'
555 },
556 if self.has_permission(Permission::SecureWrite) {
557 'W'
558 } else {
559 '_'
560 },
561 if self.has_permission(Permission::NonSecureRead) {
562 'R'
563 } else {
564 '_'
565 },
566 if self.has_permission(Permission::NonSecureWrite) {
567 'W'
568 } else {
569 '_'
570 },
571 if self.has_permission(Permission::BootRead) {
572 'R'
573 } else {
574 '_'
575 },
576 if self.has_permission(Permission::BootWrite) {
577 'W'
578 } else {
579 '_'
580 }
581 )
582 }
583}
584
585#[derive(Clone)]
589pub struct PartitionTableBlock {
590 contents: [u32; PARTITION_TABLE_MAX_ITEMS],
592 num_items: usize,
594}
595
596impl PartitionTableBlock {
597 pub const fn new() -> PartitionTableBlock {
601 let mut contents = [0; PARTITION_TABLE_MAX_ITEMS];
602 contents[0] = BLOCK_MARKER_START;
603 contents[1] = item_last(0);
604 contents[2] = 0;
605 contents[3] = BLOCK_MARKER_END;
606 PartitionTableBlock {
607 contents,
608 num_items: 0,
609 }
610 }
611
612 pub const fn add_partition_item(
614 self,
615 unpartitioned: UnpartitionedSpace,
616 partitions: &[Partition],
617 ) -> Self {
618 let mut new_table = PartitionTableBlock::new();
619 let mut idx = 0;
620 while idx < self.num_items + 1 {
622 new_table.contents[idx] = self.contents[idx];
623 idx += 1;
624 }
625
626 let header_idx = idx;
628 new_table.contents[idx] = 0;
629 idx += 1;
630
631 new_table.contents[idx] = unpartitioned.permissions_and_flags;
637 idx += 1;
638
639 let mut partition_no = 0;
642 while partition_no < partitions.len() {
643 new_table.contents[idx] = partitions[partition_no].permissions_and_location;
645 idx += 1;
646
647 new_table.contents[idx] = partitions[partition_no].permissions_and_flags;
649 idx += 1;
650
651 if let Some(id) = partitions[partition_no].id {
653 new_table.contents[idx] = id as u32;
654 new_table.contents[idx + 1] = (id >> 32) as u32;
655 idx += 2;
656 }
657
658 let mut extra_families_idx = 0;
660 while extra_families_idx < partitions[partition_no].extra_families_len {
661 new_table.contents[idx] =
662 partitions[partition_no].extra_families[extra_families_idx];
663 idx += 1;
664 extra_families_idx += 1;
665 }
666
667 let mut name_idx = 0;
669 while name_idx < partitions[partition_no].name[0] as usize {
670 let name_chunk = [
671 partitions[partition_no].name[name_idx],
672 partitions[partition_no].name[name_idx + 1],
673 partitions[partition_no].name[name_idx + 2],
674 partitions[partition_no].name[name_idx + 3],
675 ];
676 new_table.contents[idx] = u32::from_le_bytes(name_chunk);
677 name_idx += 4;
678 idx += 1;
679 }
680
681 partition_no += 1;
682 }
683
684 let len = idx - header_idx;
685 new_table.contents[header_idx] =
686 item_generic_2bs(partitions.len() as u8, len as u16, ITEM_2BS_PARTITION_TABLE);
687
688 new_table.contents[idx] = item_last(idx as u16 - 1);
690 new_table.contents[idx + 1] = 0;
691 new_table.contents[idx + 2] = BLOCK_MARKER_END;
692
693 new_table.num_items = idx - 1;
695 new_table
696 }
697
698 pub const fn with_version(self, major: u16, minor: u16) -> Self {
700 let mut new_table = PartitionTableBlock::new();
701 let mut idx = 0;
702 while idx < self.num_items + 1 {
704 new_table.contents[idx] = self.contents[idx];
705 idx += 1;
706 }
707
708 new_table.contents[idx] = item_generic_2bs(0, 2, ITEM_1BS_VERSION);
710 idx += 1;
711 new_table.contents[idx] = ((major as u32) << 16) | minor as u32;
712 idx += 1;
713
714 new_table.contents[idx] = item_last(idx as u16 - 1);
716 new_table.contents[idx + 1] = 0;
717 new_table.contents[idx + 2] = BLOCK_MARKER_END;
718
719 new_table.num_items = idx - 1;
721 new_table
722 }
723
724 pub const fn with_sha256(self) -> Self {
729 let mut new_table = PartitionTableBlock::new();
730 let mut idx = 0;
731 while idx < self.num_items + 1 {
733 new_table.contents[idx] = self.contents[idx];
734 idx += 1;
735 }
736
737 new_table.contents[idx] = item_generic_2bs(1, 2, ITEM_2BS_HASH_DEF);
739 idx += 1;
740 new_table.contents[idx] = (idx + 1) as u32;
742 idx += 1;
743
744 let input = unsafe {
746 core::slice::from_raw_parts(new_table.contents.as_ptr() as *const u8, idx * 4)
747 };
748 let hash: [u8; 32] = sha2_const_stable::Sha256::new().update(input).finalize();
749
750 new_table.contents[idx] = item_generic_2bs(0, 9, ITEM_1BS_HASH_VALUE);
752 idx += 1;
753
754 let mut hash_idx = 0;
755 while hash_idx < hash.len() {
756 new_table.contents[idx] = u32::from_le_bytes([
757 hash[hash_idx],
758 hash[hash_idx + 1],
759 hash[hash_idx + 2],
760 hash[hash_idx + 3],
761 ]);
762 idx += 1;
763 hash_idx += 4;
764 }
765
766 new_table.contents[idx] = item_last(idx as u16 - 1);
768 new_table.contents[idx + 1] = 0;
769 new_table.contents[idx + 2] = BLOCK_MARKER_END;
770
771 new_table.num_items = idx - 1;
773 new_table
774 }
775}
776
777impl Default for PartitionTableBlock {
778 fn default() -> Self {
779 Self::new()
780 }
781}
782
783#[derive(Debug, Copy, Clone, PartialEq, Eq)]
785#[repr(u32)]
786#[allow(missing_docs)]
787pub enum PartitionFlag {
788 NotBootableArm = 1 << 9,
789 NotBootableRiscv = 1 << 10,
790 Uf2DownloadAbNonBootableOwnerAffinity = 1 << 11,
791 Uf2DownloadNoReboot = 1 << 13,
792 AcceptsDefaultFamilyRp2040 = 1 << 14,
793 AcceptsDefaultFamilyData = 1 << 16,
794 AcceptsDefaultFamilyRp2350ArmS = 1 << 17,
795 AcceptsDefaultFamilyRp2350Riscv = 1 << 18,
796 AcceptsDefaultFamilyRp2350ArmNs = 1 << 19,
797}
798
799#[derive(Debug, Copy, Clone, PartialEq, Eq)]
801#[repr(u32)]
802#[allow(missing_docs)]
803pub enum UnpartitionedFlag {
804 Uf2DownloadNoReboot = 1 << 13,
805 AcceptsDefaultFamilyRp2040 = 1 << 14,
806 AcceptsDefaultFamilyAbsolute = 1 << 15,
807 AcceptsDefaultFamilyData = 1 << 16,
808 AcceptsDefaultFamilyRp2350ArmS = 1 << 17,
809 AcceptsDefaultFamilyRp2350Riscv = 1 << 18,
810 AcceptsDefaultFamilyRp2350ArmNs = 1 << 19,
811}
812
813#[derive(Debug, Copy, Clone, PartialEq, Eq)]
815pub enum Link {
816 Nothing,
818 ToA {
820 partition_idx: u8,
822 },
823 ToOwner {
825 partition_idx: u8,
827 },
828}
829
830#[derive(Debug, Copy, Clone, PartialEq, Eq)]
832#[repr(u32)]
833pub enum Permission {
834 SecureRead = 1 << 26,
838 SecureWrite = 1 << 27,
842 NonSecureRead = 1 << 28,
846 NonSecureWrite = 1 << 29,
850 BootRead = 1 << 30,
854 BootWrite = 1 << 31,
858}
859
860impl Permission {
861 pub const fn is_in(self, mask: u32) -> bool {
863 (mask & (self as u32)) != 0
864 }
865}
866
867#[derive(Debug, Copy, Clone, PartialEq, Eq)]
869pub enum Architecture {
870 Arm,
872 Riscv,
874}
875
876#[derive(Debug, Copy, Clone)]
878pub enum Security {
879 Unspecified,
881 NonSecure,
883 Secure,
885}
886
887pub const fn item_generic_1bs(value: u16, length: u8, command: u8) -> u32 {
891 ((value as u32) << 16) | ((length as u32) << 8) | (command as u32)
892}
893
894pub const fn item_generic_2bs(value: u8, length: u16, command: u8) -> u32 {
898 ((value as u32) << 24) | ((length as u32) << 8) | (command as u32)
899}
900
901pub const fn item_ignored() -> u32 {
903 item_generic_2bs(0, 1, ITEM_2BS_IGNORED)
904}
905
906pub const fn item_image_type_invalid() -> u32 {
908 let value = IMAGE_TYPE_INVALID;
909 item_generic_1bs(value, 1, ITEM_1BS_IMAGE_TYPE)
910}
911
912pub const fn item_image_type_data() -> u32 {
914 let value = IMAGE_TYPE_DATA;
915 item_generic_1bs(value, 1, ITEM_1BS_IMAGE_TYPE)
916}
917
918pub const fn item_image_type_exe(security: Security, arch: Architecture) -> u32 {
920 let mut value = IMAGE_TYPE_EXE | IMAGE_TYPE_EXE_CHIP_RP2350;
921
922 match arch {
923 Architecture::Arm => {
924 value |= IMAGE_TYPE_EXE_CPU_ARM;
925 }
926 Architecture::Riscv => {
927 value |= IMAGE_TYPE_EXE_CPU_RISCV;
928 }
929 }
930
931 match security {
932 Security::Unspecified => value |= IMAGE_TYPE_EXE_TYPE_SECURITY_UNSPECIFIED,
933 Security::NonSecure => value |= IMAGE_TYPE_EXE_TYPE_SECURITY_NS,
934 Security::Secure => value |= IMAGE_TYPE_EXE_TYPE_SECURITY_S,
935 }
936
937 item_generic_1bs(value, 1, ITEM_1BS_IMAGE_TYPE)
938}
939
940pub const fn item_last(length: u16) -> u32 {
942 item_generic_2bs(0, length, ITEM_2BS_LAST)
943}
944
945pub const fn item_vector_table(table_ptr: u32) -> [u32; 2] {
949 [item_generic_1bs(0, 2, ITEM_1BS_VECTOR_TABLE), table_ptr]
950}
951
952pub const fn item_entry_point(entry_point: u32, initial_sp: u32) -> [u32; 3] {
954 [
955 item_generic_1bs(0, 3, ITEM_1BS_ENTRY_POINT),
956 entry_point,
957 initial_sp,
958 ]
959}
960
961pub const fn item_rolling_window(delta: u32) -> [u32; 2] {
966 [item_generic_1bs(0, 3, ITEM_1BS_ROLLING_WINDOW_DELTA), delta]
967}
968
969#[cfg(test)]
970mod test {
971 use super::*;
972
973 #[test]
1014 fn make_hashed_partition_table() {
1015 let table = PartitionTableBlock::new()
1016 .add_partition_item(
1017 UnpartitionedSpace::new()
1018 .with_permission(Permission::SecureRead)
1019 .with_permission(Permission::SecureWrite)
1020 .with_permission(Permission::NonSecureRead)
1021 .with_permission(Permission::NonSecureWrite)
1022 .with_permission(Permission::BootRead)
1023 .with_permission(Permission::BootWrite)
1024 .with_flag(UnpartitionedFlag::AcceptsDefaultFamilyAbsolute),
1025 &[
1026 Partition::new(2, 512)
1027 .with_id(0)
1028 .with_flag(PartitionFlag::AcceptsDefaultFamilyRp2350ArmS)
1029 .with_flag(PartitionFlag::AcceptsDefaultFamilyRp2350Riscv)
1030 .with_permission(Permission::SecureRead)
1031 .with_permission(Permission::SecureWrite)
1032 .with_permission(Permission::NonSecureRead)
1033 .with_permission(Permission::NonSecureWrite)
1034 .with_permission(Permission::BootRead)
1035 .with_permission(Permission::BootWrite)
1036 .with_name("A"),
1037 Partition::new(513, 1023)
1038 .with_id(1)
1039 .with_flag(PartitionFlag::AcceptsDefaultFamilyRp2350ArmS)
1040 .with_flag(PartitionFlag::AcceptsDefaultFamilyRp2350Riscv)
1041 .with_link(Link::ToA { partition_idx: 0 })
1042 .with_permission(Permission::SecureRead)
1043 .with_permission(Permission::SecureWrite)
1044 .with_permission(Permission::NonSecureRead)
1045 .with_permission(Permission::NonSecureWrite)
1046 .with_permission(Permission::BootRead)
1047 .with_permission(Permission::BootWrite)
1048 .with_name("B"),
1049 ],
1050 )
1051 .with_version(1, 0)
1052 .with_sha256();
1053 let expected = &[
1054 0xffffded3, 0x02000c0a, 0xfc008000, 0xfc400002, 0xfc061001, 0x00000000, 0x00000000, 0x00004101, 0xfc7fe201, 0xfc061003, 0x00000001, 0x00000000, 0x00004201, 0x00000248, 0x00010000, 0x01000247, 0x00000011, 0x0000094b, 0x1945cdad, 0x6b5f9773, 0xe2bf39bd, 0xb243e599, 0xab2f0e9a, 0x4d5d6d0b, 0xf973050f, 0x5ab6dadb, 0x000019ff, 0x00000000, 0xab123579, ];
1084 assert_eq!(
1085 &table.contents[..29],
1086 expected,
1087 "{:#010x?}\n != \n{:#010x?}",
1088 &table.contents[0..29],
1089 expected,
1090 );
1091 }
1092}