unsafe fn parse_and_validate_tbf_header(address: *const u8) -> Option<TbfHeader> {
    let version = *(address as *const u16);

    match version {
        1 => {
            let tbf_header = &*(address as *const TbfHeaderV1);

            let checksum =
                tbf_header.version             ^ tbf_header.total_size      ^ tbf_header.entry_offset ^
                tbf_header.rel_data_offset     ^ tbf_header.rel_data_size   ^ tbf_header.text_offset ^
                tbf_header.text_size           ^ tbf_header.got_offset      ^ tbf_header.got_size ^
                tbf_header.data_offset         ^ tbf_header.data_size       ^ tbf_header.bss_mem_offset ^
                tbf_header.bss_size            ^ tbf_header.min_stack_len   ^ tbf_header.min_app_heap_len ^
                tbf_header.min_kernel_heap_len ^ tbf_header.pkg_name_offset ^ tbf_header.pkg_name_size;

            if checksum != tbf_header.checksum {
                None
            } else {
                Some(TbfHeader::TbfHeaderV1(tbf_header))
            }
        }

        2 => {
            let tbf_header_base = &*(address as *const TbfHeaderV2Base);

            // Some sanity checking. Make sure the header isn't longer than the
            // total app. Make sure the total app fits inside a reasonable size
            // of flash.
            if tbf_header_base.header_size as u32 >= tbf_header_base.total_size ||
               tbf_header_base.total_size > 0x010000000 {
                return None;
            }

            // Calculate checksum. The checksum is the XOR of each 4 byte word
            // in the header.
            let mut chunks = tbf_header_base.header_size as usize / 4;
            let mut leftover_bytes = 0;
            if chunks * 4 != tbf_header_base.header_size as usize {
                chunks += 1;
                leftover_bytes = tbf_header_base.header_size as usize - (chunks * 4);
            }
            let mut checksum: u32 = 0;
            let header = slice::from_raw_parts(address as *const u32, chunks);
            for (i, chunk) in header.iter().enumerate() {
                if i == 3 {
                    // Skip the checksum field.
                } else if i == chunks - 1 && leftover_bytes != 0 {
                    // In this case, we don't want to use the entire word.
                    checksum ^= *chunk & (0xFFFFFFFF >> (4 - leftover_bytes));
                } else {
                    checksum ^= *chunk;
                }
            }

            if checksum != tbf_header_base.checksum {
                return None;
            }

            // Skip the base of the header.
            let mut offset = mem::size_of::<TbfHeaderV2Base>() as isize;
            let mut remaining_length = tbf_header_base.header_size as usize - offset as usize;

            // Check if this is a real app or just padding. Padding apps are
            // identified by not having any options.
            if remaining_length == 0 {
                // Just padding.
                if checksum == tbf_header_base.checksum {
                    Some(TbfHeader::Padding(tbf_header_base))
                } else {
                    None
                }

            } else {
                // This is an actual app.

                // Places to save fields that we parse out of the header
                // options.
                let mut main_pointer: Option<&TbfHeaderV2Main> = None;
                let mut wfr_pointer: Option<&'static [TbfHeaderV2WriteableFlashRegion]> = None;
                let mut app_name_str = "";

                // Loop through the header looking for known options.
                while remaining_length > mem::size_of::<TbfHeaderTlv>() {
                    let tbf_tlv_header = &*(address.offset(offset) as *const TbfHeaderTlv);

                    remaining_length -= mem::size_of::<TbfHeaderTlv>();
                    offset += mem::size_of::<TbfHeaderTlv>() as isize;

                    // Only parse known TLV blocks. There is no type 0.
                    if (tbf_tlv_header.tipe as u16) < TbfHeaderTypes::Unused as u16 && (tbf_tlv_header.tipe as u16) > 0 {
                        // This lets us skip unknown header types.

                        match tbf_tlv_header.tipe {
                            TbfHeaderTypes::TbfHeaderMain => /* Main */ {
                                if remaining_length >= mem::size_of::<TbfHeaderV2Main>() &&
                                   tbf_tlv_header.length as usize == mem::size_of::<TbfHeaderV2Main>() {
                                    let tbf_main = &*(address.offset(offset) as *const TbfHeaderV2Main);
                                    main_pointer = Some(tbf_main);
                                }
                            }
                            TbfHeaderTypes::TbfHeaderWriteableFlashRegions => /* Writeable Flash Regions */ {
                                // Length must be a multiple of the size of a region definition.
                                if tbf_tlv_header.length as usize % mem::size_of::<TbfHeaderV2WriteableFlashRegion>() == 0 {
                                    let number_regions = tbf_tlv_header.length as usize / mem::size_of::<TbfHeaderV2WriteableFlashRegion>();
                                    let region_start = &*(address.offset(offset) as *const TbfHeaderV2WriteableFlashRegion);
                                    let regions = slice::from_raw_parts(region_start, number_regions);
                                    wfr_pointer = Some(regions);
                                }
                            }
                            TbfHeaderTypes::TbfHeaderPackageName => /* Package Name */ {
                                if remaining_length >= tbf_tlv_header.length as usize {
                                    let package_name_byte_array =
                                        slice::from_raw_parts(address.offset(offset), tbf_tlv_header.length as usize);
                                    let _ = str::from_utf8(package_name_byte_array).map(|name_str| { app_name_str = name_str; });
                                }
                            }
                            TbfHeaderTypes::Unused => {}
                        }
                    }

                    // All TLV blocks are padded to 4 bytes, so we need to skip
                    // more if the length is not a multiple of 4.
                    remaining_length -= align4!(tbf_tlv_header.length) as usize;
                    offset += align4!(tbf_tlv_header.length) as isize;
                }

                let tbf_header = TbfHeaderV2 {
                    base: tbf_header_base,
                    main: main_pointer,
                    package_name: Some(app_name_str),
                    writeable_regions: wfr_pointer,
                };

                Some(TbfHeader::TbfHeaderV2(tbf_header))
            }
        }

        _ => None
    }
}
/// Converts a pointer to memory to a TbfHeader struct
///
/// This function takes a pointer to arbitrary memory and optionally returns a
/// TBF header struct. This function will validate the header checksum, but does
/// not perform sanity or security checking on the structure.
Converts a pointer to memory to a TbfHeader struct
This function takes a pointer to arbitrary memory and optionally returns a
TBF header struct. This function will validate the header checksum, but does
not perform sanity or security checking on the structure.
Converts a pointer to memory to a TbfHeader struct This function takes a pointer to arbitrary memory and optionally returns a TBF header struct . This function will validate the header checksum but does not perform sanity or security checking on the structure .
unsafe fn parse_and_validate_tbf_header(address: *const u8) -> Option<TbfHeader> {
    let version = *(address as *const u16);
    match version {
        1 => {
            let tbf_header = &*(address as *const TbfHeaderV1);
            let checksum =
                tbf_header.version             ^ tbf_header.total_size      ^ tbf_header.entry_offset ^
                tbf_header.rel_data_offset     ^ tbf_header.rel_data_size   ^ tbf_header.text_offset ^
                tbf_header.text_size           ^ tbf_header.got_offset      ^ tbf_header.got_size ^
                tbf_header.data_offset         ^ tbf_header.data_size       ^ tbf_header.bss_mem_offset ^
                tbf_header.bss_size            ^ tbf_header.min_stack_len   ^ tbf_header.min_app_heap_len ^
                tbf_header.min_kernel_heap_len ^ tbf_header.pkg_name_offset ^ tbf_header.pkg_name_size;
            if checksum != tbf_header.checksum {
                None
            } else {
                Some(TbfHeader::TbfHeaderV1(tbf_header))
            }
        }
        2 => {
            let tbf_header_base = &*(address as *const TbfHeaderV2Base);
            // Some sanity checking. Make sure the header isn't longer than the
            // total app. Make sure the total app fits inside a reasonable size
            // of flash.
            if tbf_header_base.header_size as u32 >= tbf_header_base.total_size ||
               tbf_header_base.total_size > 0x010000000 {
                return None;
            }
            // Calculate checksum. The checksum is the XOR of each 4 byte word
            // in the header.
            let mut chunks = tbf_header_base.header_size as usize / 4;
            let mut leftover_bytes = 0;
            if chunks * 4 != tbf_header_base.header_size as usize {
                chunks += 1;
                leftover_bytes = tbf_header_base.header_size as usize - (chunks * 4);
            }
            let mut checksum: u32 = 0;
            let header = slice::from_raw_parts(address as *const u32, chunks);
            for (i, chunk) in header.iter().enumerate() {
                if i == 3 {
                    // Skip the checksum field.
                } else if i == chunks - 1 && leftover_bytes != 0 {
                    // In this case, we don't want to use the entire word.
                    checksum ^= *chunk & (0xFFFFFFFF >> (4 - leftover_bytes));
                } else {
                    checksum ^= *chunk;
                }
            }
            if checksum != tbf_header_base.checksum {
                return None;
            }
            // Skip the base of the header.
            let mut offset = mem::size_of::<TbfHeaderV2Base>() as isize;
            let mut remaining_length = tbf_header_base.header_size as usize - offset as usize;
            // Check if this is a real app or just padding. Padding apps are
            // identified by not having any options.
            if remaining_length == 0 {
                // Just padding.
                if checksum == tbf_header_base.checksum {
                    Some(TbfHeader::Padding(tbf_header_base))
                } else {
                    None
                }
            } else {
                // This is an actual app.
                // Places to save fields that we parse out of the header
                // options.
                let mut main_pointer: Option<&TbfHeaderV2Main> = None;
                let mut wfr_pointer: Option<&'static [TbfHeaderV2WriteableFlashRegion]> = None;
                let mut app_name_str = "";
                // Loop through the header looking for known options.
                while remaining_length > mem::size_of::<TbfHeaderTlv>() {
                    let tbf_tlv_header = &*(address.offset(offset) as *const TbfHeaderTlv);
                    remaining_length -= mem::size_of::<TbfHeaderTlv>();
                    offset += mem::size_of::<TbfHeaderTlv>() as isize;
                    // Only parse known TLV blocks. There is no type 0.
                    if (tbf_tlv_header.tipe as u16) < TbfHeaderTypes::Unused as u16 && (tbf_tlv_header.tipe as u16) > 0 {
                        // This lets us skip unknown header types.
                        match tbf_tlv_header.tipe {
                            TbfHeaderTypes::TbfHeaderMain => /* Main */ {
                                if remaining_length >= mem::size_of::<TbfHeaderV2Main>() &&
                                   tbf_tlv_header.length as usize == mem::size_of::<TbfHeaderV2Main>() {
                                    let tbf_main = &*(address.offset(offset) as *const TbfHeaderV2Main);
                                    main_pointer = Some(tbf_main);
                                }
                            }
                            TbfHeaderTypes::TbfHeaderWriteableFlashRegions => /* Writeable Flash Regions */ {
                                // Length must be a multiple of the size of a region definition.
                                if tbf_tlv_header.length as usize % mem::size_of::<TbfHeaderV2WriteableFlashRegion>() == 0 {
                                    let number_regions = tbf_tlv_header.length as usize / mem::size_of::<TbfHeaderV2WriteableFlashRegion>();
                                    let region_start = &*(address.offset(offset) as *const TbfHeaderV2WriteableFlashRegion);
                                    let regions = slice::from_raw_parts(region_start, number_regions);
                                    wfr_pointer = Some(regions);
                                }
                            }
                            TbfHeaderTypes::TbfHeaderPackageName => /* Package Name */ {
                                if remaining_length >= tbf_tlv_header.length as usize {
                                    let package_name_byte_array =
                                        slice::from_raw_parts(address.offset(offset), tbf_tlv_header.length as usize);
                                    let _ = str::from_utf8(package_name_byte_array).map(|name_str| { app_name_str = name_str; });
                                }
                            }
                            TbfHeaderTypes::Unused => {}
                        }
                    }
                    // All TLV blocks are padded to 4 bytes, so we need to skip
                    // more if the length is not a multiple of 4.
                    remaining_length -= align4!(tbf_tlv_header.length) as usize;
                    offset += align4!(tbf_tlv_header.length) as isize;
                }
                let tbf_header = TbfHeaderV2 {
                    base: tbf_header_base,
                    main: main_pointer,
                    package_name: Some(app_name_str),
                    writeable_regions: wfr_pointer,
                };
                Some(TbfHeader::TbfHeaderV2(tbf_header))
            }
        }
        _ => None
    }
}
unsafe fn parse_and_validate_tbf_header ( address : * const u8 ) -> Option < TbfHeader > { let version = * ( address as * const u16 ) ; match version { 1 => { let tbf_header = & * ( address as * const TbfHeaderV1 ) ; let checksum = tbf_header . version ^ tbf_header . total_size ^ tbf_header . entry_offset ^ tbf_header . rel_data_offset ^ tbf_header . rel_data_size ^ tbf_header . text_offset ^ tbf_header . text_size ^ tbf_header . got_offset ^ tbf_header . got_size ^ tbf_header . data_offset ^ tbf_header . data_size ^ tbf_header . bss_mem_offset ^ tbf_header . bss_size ^ tbf_header . min_stack_len ^ tbf_header . min_app_heap_len ^ tbf_header . min_kernel_heap_len ^ tbf_header . pkg_name_offset ^ tbf_header . pkg_name_size ; if checksum != tbf_header . checksum { None } else { Some ( TbfHeader :: TbfHeaderV1 ( tbf_header ) ) } } 2 => { let tbf_header_base = & * ( address as * const TbfHeaderV2Base ) ; // Some sanity checking. Make sure the header isn't longer than the // total app. Make sure the total app fits inside a reasonable size // of flash. if tbf_header_base . header_size as u32 >= tbf_header_base . total_size || tbf_header_base . total_size > 0x010000000 { return None ; } // Calculate checksum. The checksum is the XOR of each 4 byte word // in the header. let mut chunks = tbf_header_base . header_size as usize / 4 ; let mut leftover_bytes = 0 ; if chunks * 4 != tbf_header_base . header_size as usize { chunks += 1 ; leftover_bytes = tbf_header_base . header_size as usize - ( chunks * 4 ) ; } let mut checksum : u32 = 0 ; let header = slice :: from_raw_parts ( address as * const u32 , chunks ) ; for ( i , chunk ) in header . iter ( ) . enumerate ( ) { if i == 3 { // Skip the checksum field. } else if i == chunks - 1 && leftover_bytes != 0 { // In this case, we don't want to use the entire word. checksum ^= * chunk & ( 0xFFFFFFFF >> ( 4 - leftover_bytes ) ) ; } else { checksum ^= * chunk ; } } if checksum != tbf_header_base . checksum { return None ; } // Skip the base of the header. let mut offset = mem :: size_of :: < TbfHeaderV2Base > ( ) as isize ; let mut remaining_length = tbf_header_base . header_size as usize - offset as usize ; // Check if this is a real app or just padding. Padding apps are // identified by not having any options. if remaining_length == 0 { // Just padding. if checksum == tbf_header_base . checksum { Some ( TbfHeader :: Padding ( tbf_header_base ) ) } else { None } } else { // This is an actual app. // Places to save fields that we parse out of the header // options. let mut main_pointer : Option < & TbfHeaderV2Main > = None ; let mut wfr_pointer : Option < & ' static [ TbfHeaderV2WriteableFlashRegion ] > = None ; let mut app_name_str = " " ; // Loop through the header looking for known options. while remaining_length > mem :: size_of :: < TbfHeaderTlv > ( ) { let tbf_tlv_header = & * ( address . offset ( offset ) as * const TbfHeaderTlv ) ; remaining_length -= mem :: size_of :: < TbfHeaderTlv > ( ) ; offset += mem :: size_of :: < TbfHeaderTlv > ( ) as isize ; // Only parse known TLV blocks. There is no type 0. if ( tbf_tlv_header . tipe as u16 ) < TbfHeaderTypes :: Unused as u16 && ( tbf_tlv_header . tipe as u16 ) > 0 { // This lets us skip unknown header types. match tbf_tlv_header . tipe { TbfHeaderTypes :: TbfHeaderMain => /* Main */ { if remaining_length >= mem :: size_of :: < TbfHeaderV2Main > ( ) && tbf_tlv_header . length as usize == mem :: size_of :: < TbfHeaderV2Main > ( ) { let tbf_main = & * ( address . offset ( offset ) as * const TbfHeaderV2Main ) ; main_pointer = Some ( tbf_main ) ; } } TbfHeaderTypes :: TbfHeaderWriteableFlashRegions => /* Writeable Flash Regions */ { // Length must be a multiple of the size of a region definition. if tbf_tlv_header . length as usize % mem :: size_of :: < TbfHeaderV2WriteableFlashRegion > ( ) == 0 { let number_regions = tbf_tlv_header . length as usize / mem :: size_of :: < TbfHeaderV2WriteableFlashRegion > ( ) ; let region_start = & * ( address . offset ( offset ) as * const TbfHeaderV2WriteableFlashRegion ) ; let regions = slice :: from_raw_parts ( region_start , number_regions ) ; wfr_pointer = Some ( regions ) ; } } TbfHeaderTypes :: TbfHeaderPackageName => /* Package Name */ { if remaining_length >= tbf_tlv_header . length as usize { let package_name_byte_array = slice :: from_raw_parts ( address . offset ( offset ) , tbf_tlv_header . length as usize ) ; let _ = str :: from_utf8 ( package_name_byte_array ) . map ( | name_str | { app_name_str = name_str ; } ) ; } } TbfHeaderTypes :: Unused => { } } } // All TLV blocks are padded to 4 bytes, so we need to skip // more if the length is not a multiple of 4. remaining_length -= align4 ! ( tbf_tlv_header length ) as usize ; offset += align4 ! ( tbf_tlv_header length ) as isize ; } let tbf_header = TbfHeaderV2 { base : tbf_header_base , main : main_pointer , package_name : Some ( app_name_str ) , writeable_regions : wfr_pointer , } ; Some ( TbfHeader :: TbfHeaderV2 ( tbf_header ) ) } } _ => None } }
Converts a pointer to memory to a TbfHeader struct
This function takes a pointer to arbitrary memory and optionally returns a
TBF header struct.
Converts a pointer to memory to a TbfHeader struct This function takes a pointer to arbitrary memory and optionally returns a TBF header struct .
address
*const u8
address
*const u8