@@ -3,16 +3,43 @@ const FLASH_OFFSET: usize = 0x10000000;
3
3
const LAST_4K_BLOCK : usize = 0xff000 ;
4
4
const SERIALNUM_LEN : usize = 18 ;
5
5
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 > {
7
18
// Flash is mapped into memory, just read it from there
8
19
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 ;
15
26
}
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
+ } )
16
43
}
17
44
18
45
/// Get the firmware version in a format for USB Device Release
0 commit comments