@@ -3,16 +3,43 @@ const FLASH_OFFSET: usize = 0x10000000;
33const LAST_4K_BLOCK : usize = 0xff000 ;
44const SERIALNUM_LEN : usize = 18 ;
55
6- pub fn get_serialnum ( ) -> Option < & ' static str > {
6+ #[ repr( packed) ]
7+ pub struct SerialnumStructRaw {
8+ sn_rev : u8 ,
9+ serialnum : [ u8 ; SERIALNUM_LEN ] ,
10+ crc32 : [ u8 ; 4 ] ,
11+ }
12+
13+ pub struct SerialnumStruct {
14+ pub serialnum : & ' static str ,
15+ }
16+
17+ pub fn get_serialnum ( ) -> Option < SerialnumStruct > {
718 // Flash is mapped into memory, just read it from there
819 let ptr: * const u8 = ( FLASH_OFFSET + LAST_4K_BLOCK ) as * const u8 ;
9- unsafe {
10- let slice : & [ u8 ] = core :: slice :: from_raw_parts ( ptr , SERIALNUM_LEN ) ;
11- if slice [ 0 ] == 0xFF || slice [ 0 ] == 0x00 {
12- return None ;
13- }
14- core :: str :: from_utf8 ( slice ) . ok ( )
20+ let sn_raw_ptr = ptr as * const SerialnumStructRaw ;
21+ let sn_raw = unsafe { sn_raw_ptr . as_ref ( ) ? } ;
22+
23+ // Only rev 1 supported
24+ if sn_raw . sn_rev != 1 {
25+ return None ;
1526 }
27+
28+ let crc: crc:: Crc < u32 > = crc:: Crc :: < u32 > :: new ( & crc:: CRC_32_ISO_HDLC ) ;
29+ let mut digest = crc. digest ( ) ;
30+ digest. update ( & [ sn_raw. sn_rev ] ) ;
31+ digest. update ( & sn_raw. serialnum ) ;
32+ let calc_checksum = digest. finalize ( ) ;
33+
34+ let actual_checksum = u32:: from_le_bytes ( sn_raw. crc32 ) ;
35+ // Checksum invalid, serial fall back to default serial number
36+ if calc_checksum != actual_checksum {
37+ return None ;
38+ }
39+
40+ Some ( SerialnumStruct {
41+ serialnum : core:: str:: from_utf8 ( & sn_raw. serialnum ) . ok ( ) ?,
42+ } )
1643}
1744
1845/// Get the firmware version in a format for USB Device Release
0 commit comments