Skip to content

Commit a1713eb

Browse files
committed
Use CRC32B to verify serial number
The previously used check for 0x00 or 0xFF was too primitive and resulted in lots of false positives if other firmware was flashed. Signed-off-by: Daniel Schaefer <[email protected]>
1 parent 769bf30 commit a1713eb

File tree

8 files changed

+105
-17
lines changed

8 files changed

+105
-17
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

b1display/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ fn main() -> ! {
114114
let mut serial = SerialPort::new(&usb_bus);
115115

116116
let serialnum = if let Some(serialnum) = get_serialnum() {
117-
serialnum
117+
serialnum.serialnum
118118
} else {
119119
DEFAULT_SERIAL
120120
};

c1minimal/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ fn main() -> ! {
103103
let mut serial = SerialPort::new(&usb_bus);
104104

105105
let serialnum = if let Some(serialnum) = get_serialnum() {
106-
serialnum
106+
serialnum.serialnum
107107
} else {
108108
DEFAULT_SERIAL
109109
};

fl16-inputmodules/Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ name = "fl16-inputmodules"
44
version = "0.1.5"
55

66
[dependencies]
7+
crc = "3.0"
78
cortex-m = "0.7"
89
cortex-m-rt = "0.7.3"
910
embedded-hal = { version = "0.2.7", features = ["unproven"] }
@@ -15,7 +16,7 @@ defmt-rtt = "0.4"
1516
rp2040-panic-usb-boot = "0.5.0"
1617

1718
# Not using an external BSP, we've got the Framework Laptop 16 BSPs locally in this crate
18-
rp2040-hal = { version="0.8", features=["rt", "critical-section-impl"] }
19+
rp2040-hal = { version = "0.8", features = ["rt", "critical-section-impl"] }
1920
rp2040-boot2 = "0.3"
2021

2122
# USB Serial
@@ -43,6 +44,6 @@ ws2812-pio = { version = "0.6.0", optional = true }
4344

4445
[features]
4546
default = []
46-
ledmatrix = [ "is31fl3741" ]
47-
b1display = [ "st7306", "embedded-graphics", "tinybmp" ]
48-
c1minimal = ["smart-leds", "ws2812-pio" ]
47+
ledmatrix = ["is31fl3741"]
48+
b1display = ["st7306", "embedded-graphics", "tinybmp"]
49+
c1minimal = ["smart-leds", "ws2812-pio"]

fl16-inputmodules/src/serialnum.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,43 @@ const FLASH_OFFSET: usize = 0x10000000;
33
const LAST_4K_BLOCK: usize = 0xff000;
44
const 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

flash_layout.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Flash Layout
2+
3+
The flash is 1MB large and consists of 256 4K blocks.
4+
The last block is used to store the serial number.
5+
6+
###### LED Matrix
7+
8+
| Start | End | Size | Name |
9+
|----------|----------|---------------|--------------------|
10+
| 0x000000 | Dynamic | Roughly 40K | Firmware |
11+
| TBD | 0x0FF000 | TBD | Persistent Storage |
12+
| 0x0FF000 | 0x100000 | 0x1000 (4K) | Serial Number |
13+
14+
###### QMK Keyboards
15+
16+
| Start | End | Size | Name |
17+
|----------|----------|---------------|--------------------|
18+
| 0x000000 | Dynamic | Roughly 60K | Firmware |
19+
| 0xef000 | 0x0FF000 | 0x10000 (16K) | Persistent Storage |
20+
| 0x0FF000 | 0x100000 | 0x01000 (4K) | Serial Number |
21+
22+
## Serial Number
23+
24+
- 1 byte serial number revision (== 1)
25+
- 18 bytes serial number
26+
- 1 byte hardware revision
27+
- 4 byte CRC checksum over serial number (CRC32B, same as Python's `zlib.crc32()`)
28+
29+
Hardware Revisions:
30+
31+
- B1 Display
32+
- 1 First Prototype, very early prototype
33+
- LED Matrix
34+
- 1 First Prototype (ATC)
35+
- 2 Second Prototype (BizLink)
36+
- 3 Third Prototype, 27k Resistor
37+
- Keyboard, Numpad, Macropad
38+
- 1 First Prototype

ledmatrix/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ fn main() -> ! {
184184
let mut serial = SerialPort::new(&usb_bus);
185185

186186
let serialnum = if let Some(serialnum) = get_serialnum() {
187-
serialnum
187+
serialnum.serialnum
188188
} else {
189189
DEFAULT_SERIAL
190190
};

scripts/serial.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
#!/usr/bin/env python3
22
import zlib
33

4-
ledmatrix_1 = b'FRAKDEAM1100000000' # POC 1
5-
ledmatrix_2 = b'FRAKDEBZ4100000000' # EVT 1, config 1
6-
ledmatrix_3 = b'FRAKDEBZ4200000000' # EVT 1, config 2 (27k resistor)
4+
ledmatrix_1 = b'FRAKDEAM1100000000' # POC 1
5+
ledmatrix_2 = b'FRAKDEBZ4100000000' # EVT 1, config 1
6+
ledmatrix_3 = b'FRAKDEBZ4200000000' # EVT 1, config 2 (27k resistor)
7+
ansi_keyboard = b'FRAKDWEN4100000000' # EVT 1, config 1 (US ANSI)
8+
rgb_keyboard = b'FRAKDKEN4100000000' # EVT 1, config 1 (US ANSI)
9+
iso_keyboard = b'FRAKDWEN4200000000' # EVT 1, config 2 (UK ISO)
10+
jis_keyboard = b'FRAKDWEN4J00000000' # EVT 1, config J (JIS)
11+
numpad = b'FRAKDMEN4100000000' # EVT 1, config 1
12+
macropad = b'FRAKDNEN4100000000' # EVT 1, config 1
713

814
# This section is for modifying
915
selected = ledmatrix_2

0 commit comments

Comments
 (0)