1use core::fmt;
8use core::mem::size_of;
9
10const NUM_STORAGE_PERMISSIONS: usize = 8;
13
14pub enum InitialTbfParseError {
17 UnableToParse,
22
23 InvalidHeader(u32),
28}
29
30impl From<core::array::TryFromSliceError> for InitialTbfParseError {
31 fn from(_error: core::array::TryFromSliceError) -> Self {
35 InitialTbfParseError::UnableToParse
36 }
37}
38
39pub enum TbfParseError {
41 NotEnoughFlash,
43
44 UnsupportedVersion(u16),
46
47 ChecksumMismatch(u32, u32),
51
52 BadTlvEntry(usize),
56
57 BadProcessName,
60
61 InternalError,
67
68 TooManyEntries(usize),
73}
74
75impl From<core::array::TryFromSliceError> for TbfParseError {
76 fn from(_error: core::array::TryFromSliceError) -> Self {
80 TbfParseError::InternalError
81 }
82}
83
84impl fmt::Debug for TbfParseError {
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 match self {
87 TbfParseError::NotEnoughFlash => write!(f, "Buffer too short to parse TBF header"),
88 TbfParseError::UnsupportedVersion(version) => {
89 write!(f, "TBF version {} unsupported", version)
90 }
91 TbfParseError::ChecksumMismatch(app, calc) => write!(
92 f,
93 "Checksum verification failed: app:{:#x}, calc:{:#x}",
94 app, calc
95 ),
96 TbfParseError::BadTlvEntry(tipe) => write!(f, "TLV entry type {} is invalid", tipe),
97 TbfParseError::BadProcessName => write!(f, "Process name not UTF-8"),
98 TbfParseError::InternalError => write!(f, "Internal kernel error. This is a bug."),
99 TbfParseError::TooManyEntries(tipe) => {
100 write!(
101 f,
102 "There are too many variable entries of {} for Tock to parse",
103 tipe
104 )
105 }
106 }
107 }
108}
109
110#[derive(Clone, Copy, Debug)]
114pub struct TbfHeaderV2Base {
115 pub(crate) version: u16,
116 pub(crate) header_size: u16,
117 pub(crate) total_size: u32,
118 pub(crate) flags: u32,
119 pub(crate) checksum: u32,
120}
121
122#[derive(Clone, Copy, Debug)]
124pub enum TbfHeaderTypes {
125 TbfHeaderMain = 1,
126 TbfHeaderWriteableFlashRegions = 2,
127 TbfHeaderPackageName = 3,
128 TbfHeaderFixedAddresses = 5,
129 TbfHeaderPermissions = 6,
130 TbfHeaderStoragePermissions = 7,
131 TbfHeaderKernelVersion = 8,
132 TbfHeaderProgram = 9,
133 TbfHeaderShortId = 10,
134 TbfFooterCredentials = 128,
135
136 Unknown,
140}
141
142#[derive(Clone, Copy, Debug)]
144pub struct TbfTlv {
145 pub(crate) tipe: TbfHeaderTypes,
146 pub(crate) length: u16,
147}
148
149#[derive(Clone, Copy, Debug)]
157pub struct TbfHeaderV2Main {
158 init_fn_offset: u32,
159 protected_trailer_size: u32,
160 minimum_ram_size: u32,
161}
162
163#[derive(Clone, Copy, Debug)]
173pub struct TbfHeaderV2Program {
174 init_fn_offset: u32,
175 protected_trailer_size: u32,
176 minimum_ram_size: u32,
177 binary_end_offset: u32,
178 version: u32,
179}
180
181#[derive(Clone, Copy, Debug, Default)]
186pub struct TbfHeaderV2WriteableFlashRegion {
187 writeable_flash_region_offset: u32,
188 writeable_flash_region_size: u32,
189}
190
191#[derive(Clone, Copy, Debug, Default)]
204pub struct TbfHeaderV2FixedAddresses {
205 start_process_ram: u32,
209 start_process_flash: u32,
213}
214
215#[derive(Clone, Copy, Debug, Default)]
216struct TbfHeaderDriverPermission {
217 driver_number: u32,
218 offset: u32,
219 allowed_commands: u64,
220}
221
222#[derive(Clone, Copy, Debug)]
224pub struct TbfHeaderV2Permissions<const L: usize> {
225 length: u16,
226 perms: [TbfHeaderDriverPermission; L],
227}
228
229#[derive(Clone, Copy, Debug)]
231pub struct TbfHeaderV2StoragePermissions<const L: usize> {
232 write_id: Option<core::num::NonZeroU32>,
233 read_length: u16,
234 read_ids: [u32; L],
235 modify_length: u16,
236 modify_ids: [u32; L],
237}
238
239#[derive(Clone, Copy, Debug)]
240pub struct TbfHeaderV2KernelVersion {
241 major: u16,
242 minor: u16,
243}
244
245#[derive(Clone, Copy, Debug)]
249pub struct TbfHeaderV2ShortId {
250 short_id: Option<core::num::NonZeroU32>,
251}
252
253#[derive(Clone, Copy, Debug, Eq, PartialEq)]
254pub enum TbfFooterV2CredentialsType {
255 Reserved = 0,
256 Rsa3072Key = 1,
257 Rsa4096Key = 2,
258 SHA256 = 3,
259 SHA384 = 4,
260 SHA512 = 5,
261 EcdsaNistP256 = 6,
262}
263
264#[derive(Clone, Copy, Debug)]
265pub struct TbfFooterV2Credentials {
266 format: TbfFooterV2CredentialsType,
267 data: &'static [u8],
268}
269
270impl TbfFooterV2Credentials {
271 pub fn format(&self) -> TbfFooterV2CredentialsType {
272 self.format
273 }
274
275 pub fn data(&self) -> &'static [u8] {
276 self.data
277 }
278}
279
280impl core::convert::TryFrom<&[u8]> for TbfHeaderV2Base {
283 type Error = TbfParseError;
284
285 fn try_from(b: &[u8]) -> Result<TbfHeaderV2Base, Self::Error> {
286 if b.len() < 16 {
287 return Err(TbfParseError::InternalError);
288 }
289 Ok(TbfHeaderV2Base {
290 version: u16::from_le_bytes(
291 b.get(0..2)
292 .ok_or(TbfParseError::InternalError)?
293 .try_into()?,
294 ),
295 header_size: u16::from_le_bytes(
296 b.get(2..4)
297 .ok_or(TbfParseError::InternalError)?
298 .try_into()?,
299 ),
300 total_size: u32::from_le_bytes(
301 b.get(4..8)
302 .ok_or(TbfParseError::InternalError)?
303 .try_into()?,
304 ),
305 flags: u32::from_le_bytes(
306 b.get(8..12)
307 .ok_or(TbfParseError::InternalError)?
308 .try_into()?,
309 ),
310 checksum: u32::from_le_bytes(
311 b.get(12..16)
312 .ok_or(TbfParseError::InternalError)?
313 .try_into()?,
314 ),
315 })
316 }
317}
318
319impl core::convert::TryFrom<u16> for TbfHeaderTypes {
320 type Error = TbfParseError;
321
322 fn try_from(h: u16) -> Result<TbfHeaderTypes, Self::Error> {
323 match h {
324 1 => Ok(TbfHeaderTypes::TbfHeaderMain),
325 2 => Ok(TbfHeaderTypes::TbfHeaderWriteableFlashRegions),
326 3 => Ok(TbfHeaderTypes::TbfHeaderPackageName),
327 5 => Ok(TbfHeaderTypes::TbfHeaderFixedAddresses),
328 6 => Ok(TbfHeaderTypes::TbfHeaderPermissions),
329 7 => Ok(TbfHeaderTypes::TbfHeaderStoragePermissions),
330 8 => Ok(TbfHeaderTypes::TbfHeaderKernelVersion),
331 9 => Ok(TbfHeaderTypes::TbfHeaderProgram),
332 10 => Ok(TbfHeaderTypes::TbfHeaderShortId),
333 128 => Ok(TbfHeaderTypes::TbfFooterCredentials),
334 _ => Ok(TbfHeaderTypes::Unknown),
335 }
336 }
337}
338
339impl core::convert::TryFrom<&[u8]> for TbfTlv {
340 type Error = TbfParseError;
341
342 fn try_from(b: &[u8]) -> Result<TbfTlv, Self::Error> {
343 Ok(TbfTlv {
344 tipe: u16::from_le_bytes(
345 b.get(0..2)
346 .ok_or(TbfParseError::InternalError)?
347 .try_into()?,
348 )
349 .try_into()?,
350 length: u16::from_le_bytes(
351 b.get(2..4)
352 .ok_or(TbfParseError::InternalError)?
353 .try_into()?,
354 ),
355 })
356 }
357}
358
359impl core::convert::TryFrom<&[u8]> for TbfHeaderV2Main {
360 type Error = TbfParseError;
361
362 fn try_from(b: &[u8]) -> Result<TbfHeaderV2Main, Self::Error> {
363 if b.len() < 12 {
365 return Err(TbfParseError::InternalError);
366 }
367 Ok(TbfHeaderV2Main {
368 init_fn_offset: u32::from_le_bytes(
369 b.get(0..4)
370 .ok_or(TbfParseError::InternalError)?
371 .try_into()?,
372 ),
373 protected_trailer_size: u32::from_le_bytes(
374 b.get(4..8)
375 .ok_or(TbfParseError::InternalError)?
376 .try_into()?,
377 ),
378 minimum_ram_size: u32::from_le_bytes(
379 b.get(8..12)
380 .ok_or(TbfParseError::InternalError)?
381 .try_into()?,
382 ),
383 })
384 }
385}
386
387impl core::convert::TryFrom<&[u8]> for TbfHeaderV2Program {
388 type Error = TbfParseError;
389 fn try_from(b: &[u8]) -> Result<TbfHeaderV2Program, Self::Error> {
390 if b.len() < 20 {
392 return Err(TbfParseError::InternalError);
393 }
394 Ok(TbfHeaderV2Program {
395 init_fn_offset: u32::from_le_bytes(
396 b.get(0..4)
397 .ok_or(TbfParseError::InternalError)?
398 .try_into()?,
399 ),
400 protected_trailer_size: u32::from_le_bytes(
401 b.get(4..8)
402 .ok_or(TbfParseError::InternalError)?
403 .try_into()?,
404 ),
405 minimum_ram_size: u32::from_le_bytes(
406 b.get(8..12)
407 .ok_or(TbfParseError::InternalError)?
408 .try_into()?,
409 ),
410 binary_end_offset: u32::from_le_bytes(
411 b.get(12..16)
412 .ok_or(TbfParseError::InternalError)?
413 .try_into()?,
414 ),
415 version: u32::from_le_bytes(
416 b.get(16..20)
417 .ok_or(TbfParseError::InternalError)?
418 .try_into()?,
419 ),
420 })
421 }
422}
423
424impl core::convert::TryFrom<&[u8]> for TbfHeaderV2WriteableFlashRegion {
425 type Error = TbfParseError;
426
427 fn try_from(b: &[u8]) -> Result<TbfHeaderV2WriteableFlashRegion, Self::Error> {
428 Ok(TbfHeaderV2WriteableFlashRegion {
429 writeable_flash_region_offset: u32::from_le_bytes(
430 b.get(0..4)
431 .ok_or(TbfParseError::InternalError)?
432 .try_into()?,
433 ),
434 writeable_flash_region_size: u32::from_le_bytes(
435 b.get(4..8)
436 .ok_or(TbfParseError::InternalError)?
437 .try_into()?,
438 ),
439 })
440 }
441}
442
443impl core::convert::TryFrom<&[u8]> for TbfHeaderV2FixedAddresses {
444 type Error = TbfParseError;
445
446 fn try_from(b: &[u8]) -> Result<TbfHeaderV2FixedAddresses, Self::Error> {
447 Ok(TbfHeaderV2FixedAddresses {
448 start_process_ram: u32::from_le_bytes(
449 b.get(0..4)
450 .ok_or(TbfParseError::InternalError)?
451 .try_into()?,
452 ),
453 start_process_flash: u32::from_le_bytes(
454 b.get(4..8)
455 .ok_or(TbfParseError::InternalError)?
456 .try_into()?,
457 ),
458 })
459 }
460}
461
462impl core::convert::TryFrom<&[u8]> for TbfHeaderDriverPermission {
463 type Error = TbfParseError;
464
465 fn try_from(b: &[u8]) -> Result<TbfHeaderDriverPermission, Self::Error> {
466 if b.len() < 16 {
468 return Err(TbfParseError::InternalError);
469 }
470 Ok(TbfHeaderDriverPermission {
471 driver_number: u32::from_le_bytes(
472 b.get(0..4)
473 .ok_or(TbfParseError::InternalError)?
474 .try_into()?,
475 ),
476 offset: u32::from_le_bytes(
477 b.get(4..8)
478 .ok_or(TbfParseError::InternalError)?
479 .try_into()?,
480 ),
481 allowed_commands: u64::from_le_bytes(
482 b.get(8..16)
483 .ok_or(TbfParseError::InternalError)?
484 .try_into()?,
485 ),
486 })
487 }
488}
489
490impl<const L: usize> core::convert::TryFrom<&[u8]> for TbfHeaderV2StoragePermissions<L> {
491 type Error = TbfParseError;
492
493 fn try_from(b: &[u8]) -> Result<TbfHeaderV2StoragePermissions<L>, Self::Error> {
494 let mut read_end = 6;
495
496 let write_id = core::num::NonZeroU32::new(u32::from_le_bytes(
497 b.get(0..4)
498 .ok_or(TbfParseError::NotEnoughFlash)?
499 .try_into()?,
500 ));
501
502 let read_length = u16::from_le_bytes(
503 b.get(4..6)
504 .ok_or(TbfParseError::NotEnoughFlash)?
505 .try_into()?,
506 );
507
508 let mut read_ids: [u32; L] = [0; L];
509 for i in 0..read_length as usize {
510 let start = 6 + (i * size_of::<u32>());
511 read_end = start + size_of::<u32>();
512 if let Some(read_id) = read_ids.get_mut(i) {
513 *read_id = u32::from_le_bytes(
514 b.get(start..read_end)
515 .ok_or(TbfParseError::NotEnoughFlash)?
516 .try_into()?,
517 );
518 } else {
519 return Err(TbfParseError::BadTlvEntry(
520 TbfHeaderTypes::TbfHeaderStoragePermissions as usize,
521 ));
522 }
523 }
524
525 let modify_length = u16::from_le_bytes(
526 b.get(read_end..(read_end + 2))
527 .ok_or(TbfParseError::NotEnoughFlash)?
528 .try_into()?,
529 );
530
531 let mut modify_ids: [u32; L] = [0; L];
532 for i in 0..modify_length as usize {
533 let start = read_end + 2 + (i * size_of::<u32>());
534 let modify_end = start + size_of::<u32>();
535 if let Some(modify_id) = modify_ids.get_mut(i) {
536 *modify_id = u32::from_le_bytes(
537 b.get(start..modify_end)
538 .ok_or(TbfParseError::NotEnoughFlash)?
539 .try_into()?,
540 );
541 } else {
542 return Err(TbfParseError::BadTlvEntry(
543 TbfHeaderTypes::TbfHeaderStoragePermissions as usize,
544 ));
545 }
546 }
547
548 Ok(TbfHeaderV2StoragePermissions {
549 write_id,
550 read_length,
551 read_ids,
552 modify_length,
553 modify_ids,
554 })
555 }
556}
557
558impl core::convert::TryFrom<&[u8]> for TbfHeaderV2KernelVersion {
559 type Error = TbfParseError;
560
561 fn try_from(b: &[u8]) -> Result<TbfHeaderV2KernelVersion, Self::Error> {
562 Ok(TbfHeaderV2KernelVersion {
563 major: u16::from_le_bytes(
564 b.get(0..2)
565 .ok_or(TbfParseError::InternalError)?
566 .try_into()?,
567 ),
568 minor: u16::from_le_bytes(
569 b.get(2..4)
570 .ok_or(TbfParseError::InternalError)?
571 .try_into()?,
572 ),
573 })
574 }
575}
576
577impl core::convert::TryFrom<&[u8]> for TbfHeaderV2ShortId {
578 type Error = TbfParseError;
579
580 fn try_from(b: &[u8]) -> Result<TbfHeaderV2ShortId, Self::Error> {
581 Ok(TbfHeaderV2ShortId {
582 short_id: core::num::NonZeroU32::new(u32::from_le_bytes(
583 b.get(0..4)
584 .ok_or(TbfParseError::InternalError)?
585 .try_into()?,
586 )),
587 })
588 }
589}
590
591impl core::convert::TryFrom<&'static [u8]> for TbfFooterV2Credentials {
592 type Error = TbfParseError;
593
594 fn try_from(b: &'static [u8]) -> Result<TbfFooterV2Credentials, Self::Error> {
595 let format = u32::from_le_bytes(
596 b.get(0..4)
597 .ok_or(TbfParseError::InternalError)?
598 .try_into()?,
599 );
600 let ftype = match format {
601 0 => TbfFooterV2CredentialsType::Reserved,
602 1 => TbfFooterV2CredentialsType::Rsa3072Key,
603 2 => TbfFooterV2CredentialsType::Rsa4096Key,
604 3 => TbfFooterV2CredentialsType::SHA256,
605 4 => TbfFooterV2CredentialsType::SHA384,
606 5 => TbfFooterV2CredentialsType::SHA512,
607 6 => TbfFooterV2CredentialsType::EcdsaNistP256,
608 _ => {
609 return Err(TbfParseError::BadTlvEntry(
610 TbfHeaderTypes::TbfFooterCredentials as usize,
611 ));
612 }
613 };
614 let length = match ftype {
615 TbfFooterV2CredentialsType::Reserved => 0,
616 TbfFooterV2CredentialsType::Rsa3072Key => 768,
617 TbfFooterV2CredentialsType::Rsa4096Key => 1024,
618 TbfFooterV2CredentialsType::SHA256 => 32,
619 TbfFooterV2CredentialsType::SHA384 => 48,
620 TbfFooterV2CredentialsType::SHA512 => 64,
621 TbfFooterV2CredentialsType::EcdsaNistP256 => 64,
622 };
623 let data = &b
624 .get(4..(length + 4))
625 .ok_or(TbfParseError::NotEnoughFlash)?;
626 Ok(TbfFooterV2Credentials {
627 format: ftype,
628 data,
629 })
630 }
631}
632
633pub enum CommandPermissions {
637 NoPermsAtAll,
639 NoPermsThisDriver,
642 Mask(u64),
645}
646
647#[derive(Clone, Copy, Debug)]
653pub struct TbfHeaderV2 {
654 pub(crate) base: TbfHeaderV2Base,
655 pub(crate) main: Option<TbfHeaderV2Main>,
656 pub(crate) program: Option<TbfHeaderV2Program>,
657 pub(crate) package_name: Option<&'static str>,
658 pub(crate) writeable_regions: Option<&'static [u8]>,
659 pub(crate) fixed_addresses: Option<&'static [u8]>,
660 pub(crate) permissions: Option<&'static [u8]>,
661 pub(crate) storage_permissions: Option<&'static [u8]>,
662 pub(crate) kernel_version: Option<TbfHeaderV2KernelVersion>,
663 pub(crate) short_id: Option<TbfHeaderV2ShortId>,
664}
665
666#[derive(Debug)]
673pub enum TbfHeader {
674 TbfHeaderV2(TbfHeaderV2),
675 Padding(TbfHeaderV2Base),
676}
677
678impl TbfHeader {
679 pub fn length(&self) -> u16 {
681 match *self {
682 TbfHeader::TbfHeaderV2(hd) => hd.base.header_size,
683 TbfHeader::Padding(base) => base.header_size,
684 }
685 }
686
687 pub fn is_app(&self) -> bool {
689 match *self {
690 TbfHeader::TbfHeaderV2(_) => true,
691 TbfHeader::Padding(_) => false,
692 }
693 }
694
695 pub fn enabled(&self) -> bool {
698 match *self {
699 TbfHeader::TbfHeaderV2(hd) => {
700 hd.base.flags & 0x00000001 == 1
702 }
703 TbfHeader::Padding(_) => false,
704 }
705 }
706
707 pub fn get_minimum_app_ram_size(&self) -> u32 {
711 match *self {
712 TbfHeader::TbfHeaderV2(hd) => {
713 if hd.program.is_some() {
714 hd.program.map_or(0, |p| p.minimum_ram_size)
715 } else if hd.main.is_some() {
716 hd.main.map_or(0, |m| m.minimum_ram_size)
717 } else {
718 0
719 }
720 }
721 _ => 0,
722 }
723 }
724
725 pub fn get_protected_size(&self) -> u32 {
728 match *self {
729 TbfHeader::TbfHeaderV2(hd) => {
730 if hd.program.is_some() {
731 hd.program.map_or(0, |p| {
732 (hd.base.header_size as u32) + p.protected_trailer_size
733 })
734 } else if hd.main.is_some() {
735 hd.main.map_or(0, |m| {
736 (hd.base.header_size as u32) + m.protected_trailer_size
737 })
738 } else {
739 0
740 }
741 }
742 _ => 0,
743 }
744 }
745
746 pub fn get_app_start_offset(&self) -> u32 {
750 self.get_protected_size()
753 }
754
755 pub fn get_init_function_offset(&self) -> u32 {
758 match *self {
759 TbfHeader::TbfHeaderV2(hd) => {
760 if hd.program.is_some() {
761 hd.program
762 .map_or(0, |p| p.init_fn_offset + (hd.base.header_size as u32))
763 } else if hd.main.is_some() {
764 hd.main
765 .map_or(0, |m| m.init_fn_offset + (hd.base.header_size as u32))
766 } else {
767 0
768 }
769 }
770 _ => 0,
771 }
772 }
773
774 pub fn get_package_name(&self) -> Option<&'static str> {
776 match *self {
777 TbfHeader::TbfHeaderV2(hd) => hd.package_name,
778 _ => None,
779 }
780 }
781
782 pub fn number_writeable_flash_regions(&self) -> usize {
784 match *self {
785 TbfHeader::TbfHeaderV2(hd) => hd.writeable_regions.map_or(0, |wr_slice| {
786 let wfr_len = size_of::<TbfHeaderV2WriteableFlashRegion>();
787 wr_slice.len() / wfr_len
788 }),
789 _ => 0,
790 }
791 }
792
793 pub fn get_writeable_flash_region(&self, index: usize) -> (usize, usize) {
795 match *self {
796 TbfHeader::TbfHeaderV2(hd) => hd.writeable_regions.map_or((0, 0), |wr_slice| {
797 fn get_region(
798 wr_slice: &'static [u8],
799 index: usize,
800 ) -> Result<TbfHeaderV2WriteableFlashRegion, ()> {
801 let wfr_len = size_of::<TbfHeaderV2WriteableFlashRegion>();
802
803 let wfr = wr_slice
804 .get(index * wfr_len..(index + 1) * wfr_len)
805 .ok_or(())?
806 .try_into()
807 .or(Err(()))?;
808 Ok(wfr)
809 }
810
811 match get_region(wr_slice, index) {
812 Ok(wr) => (
813 wr.writeable_flash_region_offset as usize,
814 wr.writeable_flash_region_size as usize,
815 ),
816 Err(()) => (0, 0),
817 }
818 }),
819 _ => (0, 0),
820 }
821 }
822
823 pub fn get_fixed_address_ram(&self) -> Option<u32> {
826 let hd = match self {
827 TbfHeader::TbfHeaderV2(hd) => hd,
828 _ => return None,
829 };
830 let fixed_addresses: TbfHeaderV2FixedAddresses = hd.fixed_addresses?.try_into().ok()?;
831 match fixed_addresses.start_process_ram {
832 0xFFFFFFFF => None,
833 start => Some(start),
834 }
835 }
836
837 pub fn get_fixed_address_flash(&self) -> Option<u32> {
840 let hd = match self {
841 TbfHeader::TbfHeaderV2(hd) => hd,
842 _ => return None,
843 };
844 let fixed_addresses: TbfHeaderV2FixedAddresses = hd.fixed_addresses?.try_into().ok()?;
845 match fixed_addresses.start_process_flash {
846 0xFFFFFFFF => None,
847 start => Some(start),
848 }
849 }
850
851 pub fn get_command_permissions(&self, driver_num: usize, offset: usize) -> CommandPermissions {
864 match self {
865 TbfHeader::TbfHeaderV2(hd) => match hd.permissions {
866 Some(permissions_tlv_slice) => {
867 fn get_command_permissions_result(
869 permissions_tlv_slice: &'static [u8],
870 driver_num: usize,
871 offset: usize,
872 ) -> Result<CommandPermissions, ()> {
873 let mut found_driver_num: bool = false;
874 let perm_len = size_of::<TbfHeaderDriverPermission>();
875
876 let number_perms = u16::from_le_bytes(
878 permissions_tlv_slice
879 .get(0..2)
880 .ok_or(())?
881 .try_into()
882 .or(Err(()))?,
883 );
884 let permissions_slice = permissions_tlv_slice.get(2..).ok_or(())?;
886
887 for i in 0..number_perms as usize {
889 let perm: TbfHeaderDriverPermission = permissions_slice
890 .get((i * perm_len)..((i + 1) * perm_len))
891 .ok_or(())?
892 .try_into()
893 .or(Err(()))?;
894
895 if perm.driver_number == driver_num as u32 {
896 found_driver_num = true;
897 if perm.offset == offset as u32 {
898 return Ok(CommandPermissions::Mask(perm.allowed_commands));
899 }
900 }
901 }
902
903 if found_driver_num {
904 Ok(CommandPermissions::Mask(0))
908 } else {
909 Ok(CommandPermissions::NoPermsThisDriver)
910 }
911 }
912
913 get_command_permissions_result(permissions_tlv_slice, driver_num, offset)
914 .unwrap_or(CommandPermissions::NoPermsAtAll)
915 }
916 _ => CommandPermissions::NoPermsAtAll,
917 },
918 _ => CommandPermissions::NoPermsAtAll,
919 }
920 }
921
922 pub fn get_storage_write_id(&self) -> Option<core::num::NonZeroU32> {
927 match self {
928 TbfHeader::TbfHeaderV2(hd) => match hd.storage_permissions {
929 Some(storage_permissions_tlv_slice) => {
930 let write_id = core::num::NonZeroU32::new(u32::from_le_bytes(
931 storage_permissions_tlv_slice.get(0..4)?.try_into().ok()?,
932 ));
933
934 write_id
935 }
936 _ => None,
937 },
938 _ => None,
939 }
940 }
941
942 pub fn get_storage_read_ids(&self) -> Option<(usize, [u32; NUM_STORAGE_PERMISSIONS])> {
945 match self {
946 TbfHeader::TbfHeaderV2(hd) => match hd.storage_permissions {
947 Some(storage_permissions_tlv_slice) => {
948 let storage_permissions: TbfHeaderV2StoragePermissions<
949 NUM_STORAGE_PERMISSIONS,
950 > = storage_permissions_tlv_slice.try_into().ok()?;
951
952 Some((
953 storage_permissions.read_length.into(),
954 storage_permissions.read_ids,
955 ))
956 }
957 _ => None,
958 },
959 _ => None,
960 }
961 }
962
963 pub fn get_storage_modify_ids(&self) -> Option<(usize, [u32; NUM_STORAGE_PERMISSIONS])> {
966 match self {
967 TbfHeader::TbfHeaderV2(hd) => match hd.storage_permissions {
968 Some(storage_permissions_tlv_slice) => {
969 let storage_permissions: TbfHeaderV2StoragePermissions<
970 NUM_STORAGE_PERMISSIONS,
971 > = storage_permissions_tlv_slice.try_into().ok()?;
972
973 Some((
974 storage_permissions.modify_length.into(),
975 storage_permissions.modify_ids,
976 ))
977 }
978 _ => None,
979 },
980 _ => None,
981 }
982 }
983
984 pub fn get_kernel_version(&self) -> Option<(u16, u16)> {
987 match self {
988 TbfHeader::TbfHeaderV2(hd) => match hd.kernel_version {
989 Some(kernel_version) => Some((kernel_version.major, kernel_version.minor)),
990 _ => None,
991 },
992 _ => None,
993 }
994 }
995
996 pub fn get_binary_end(&self) -> u32 {
1000 match self {
1001 TbfHeader::TbfHeaderV2(hd) => hd
1002 .program
1003 .map_or(hd.base.total_size, |p| p.binary_end_offset),
1004 _ => 0,
1005 }
1006 }
1007
1008 pub fn get_binary_version(&self) -> u32 {
1011 match self {
1012 TbfHeader::TbfHeaderV2(hd) => hd.program.map_or(0, |p| p.version),
1013 _ => 0,
1014 }
1015 }
1016
1017 pub fn get_fixed_short_id(&self) -> Option<core::num::NonZeroU32> {
1020 match self {
1021 TbfHeader::TbfHeaderV2(hd) => hd.short_id.map_or(None, |si| si.short_id),
1022 _ => None,
1023 }
1024 }
1025}