Skip to content

Commit b41f5ba

Browse files
committed
fix: Use STM32 hardware CRC32 algorithm (CRC32/MPEG-2, uint32 fed byte-reversed)
1 parent c3e85a2 commit b41f5ba

4 files changed

Lines changed: 47 additions & 35 deletions

File tree

firmware/README.md

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,42 +13,42 @@ This project is split into two independent components:
1313
* Tombstone info located at the end, at `0x0800_07E0-0x0800_0800`
1414
* Responsible for:
1515

16-
* Checking a GPIO pin for 2 s after reset.
16+
* Checking a GPIO pin for 200 ms after reset.
1717
* If pressed → jump to the STM32 system ROM bootloader.
1818
* If not pressed → jump to the user application at `0x0800_0800`.
1919
* Contains a fixed **tombstone** block at the end of its flash region, with build metadata (magic, version, date).
2020

2121
* **UAPP (User-app) @ `userapp/`**
2222

23-
* Section starts at `0x0800_0800` (tombstone: `0x0800_0800`, code: `0x0800_0820`)
23+
* Section starts at `0x0800_0800` (tombstone: `0x0800_0800`, code: `0x0800_0A00`)
2424
* Normal user firmware, built with its own vector table and linker script.
2525
* At the very start, contains a **tombstone** block, to identify itself.
2626
* Uses the tombstone info (if needed) to check validity or report version.
2727

2828
**Flash Memory Layout**
2929

3030
```
31-
+-----------------------+ 0x0800_0000
32-
| Preloader Vector |
33-
| & Code |
34-
| (2 KB-32 bytes) |
35-
+-----------------------+ 0x0800_07E0
36-
| Tombstone info IAPL |
37-
| (32 bytes, fixed info)|
38-
+-----------------------+ 0x0800_0800
39-
| Tombstone info UAPP |
40-
| (32 bytes, fixed info)|
41-
+-----------------------+ 0x0800_0820
42-
| User App Vector |
43-
| & Code |
44-
| (up to 30KB-32 bytes) |
45-
+-----------------------+ end of flash
31+
+--------------------------+ 0x0800_0000
32+
| Preloader Vector |
33+
| & Code |
34+
| (2 KB-32 bytes) |
35+
+--------------------------+ 0x0800_07E0
36+
| Tombstone info IAPL |
37+
| (32 bytes) |
38+
+--------------------------+ 0x0800_0800
39+
| Tombstone info UAPP |
40+
| (32 bytes + padding) |
41+
+--------------------------+ 0x0800_0A00
42+
| User App Vector |
43+
| & Code |
44+
| (up to 30KB-0x200 bytes) |
45+
+--------------------------+ end of flash
4646
```
4747

4848
* **Preloader region**: `0x0800_0000 .. 0x0800_07E0`
4949
* **Tombstone IAPL**: `0x0800_07E0 .. 0x0800_0800`
5050
* **Tombstone UAPP**: `0x0800_0800 .. 0x0800_0820`
51-
* **User application**: `0x0800_0820 ..`
51+
* **User application**: `0x0800_0A00 ..`
5252

5353
**Build/Flash**
5454

@@ -68,9 +68,10 @@ Download from the latest release archive: [Release](https://github.com/xboxonere
6868

6969
### In-field update
7070

71-
1. Disconnect PCB from console!
72-
2. Connect PCB to PC
73-
3. Use custom stm32flash tool from this [repo](https://github.com/xboxoneresearch/libaspect2)
71+
1. Disconnect PCB from console and PC!
72+
2. Press and hold the button on the PCB.
73+
3. Connect PCB to PC, keep button pressed for a second.
74+
4. Use custom stm32flash tool from this repo: [repo](https://github.com/xboxoneresearch/libaspect2)
7475

7576
## Development
7677

firmware/common/bootloader.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,16 @@ uint32_t calculateCrc32(uint8_t *data, uint32_t len) {
1515
return 0xFFFFFFFF;
1616
}
1717

18-
/* Configure and reset CRC peripheral: use byte-wise input and reversed output */
19-
CRC->CR = CRC_CR_RESET | CRC_CR_REV_IN_0 | CRC_CR_REV_OUT;
18+
/* Configure and reset CRC peripheral: use default algorithm */
19+
CRC->CR = CRC_CR_RESET;
2020

2121
/* Feed data as bytes so peripheral processes one byte per write */
22-
uint8_t *p = (uint8_t *)data;
23-
for (uint32_t i = 0; i < len; i++) {
24-
*((volatile uint8_t *)&CRC->DR) = p[i];
22+
uint32_t *p = (uint32_t *)data;
23+
for (uint32_t i = 0; i < (len / sizeof(uint32_t)); i++) {
24+
*((volatile uint32_t *)&CRC->DR) = p[i];
2525
}
2626

27-
/* Final XOR and return */
28-
return (CRC->DR ^ 0xFFFFFFFF);
27+
return CRC->DR;
2928
}
3029

3130
void resetToSystemBootLoader()

firmware/scripts/fix_size_crc.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import argparse
1818
import enum
1919
import struct
20-
import zlib
2120
from typing import Tuple
2221

2322
# Constants mirroring firmware common/bootloader.h
@@ -41,8 +40,22 @@ def write_le_u32(buf: bytearray, offset: int, value: int):
4140
buf[offset:offset+4] = struct.pack('<I', value & 0xFFFFFFFF)
4241

4342

44-
def crc32_final(data: bytes) -> int:
45-
return zlib.crc32(data)
43+
def crc32_final(data: bytes, crc: int = 0xffffffff) -> int:
44+
"""
45+
CRC32/MPEG-2 with data fed in byte-reversed u32-chunks
46+
"""
47+
U32_SZ = 4
48+
assert len(data) % 4 == 0
49+
for position in range(0, len(data), U32_SZ):
50+
uint32 = data[position:position+U32_SZ]
51+
# Reverse bytes
52+
uint32 = uint32[::-1]
53+
54+
for val in uint32:
55+
crc ^= val << 24
56+
for _ in range(8):
57+
crc = crc << 1 if (crc & 0x80000000) == 0 else (crc << 1) ^ 0x104c11db7
58+
return crc
4659

4760

4861
def compute_and_patch(buf: bytearray, ptype: ProgramType) -> Tuple[int, int, int]:
@@ -60,7 +73,6 @@ def compute_and_patch(buf: bytearray, ptype: ProgramType) -> Tuple[int, int, int
6073
elif ptype is ProgramType.UAPP:
6174
if len(buf) < UAPP_ENTRY_OFFSET:
6275
raise SystemExit("UAPP binary smaller than expected entry offset; cannot compute tombstone")
63-
assert b"UAPP" == buf[UAPP_TOMBSTONE_OFF:UAPP_TOMBSTONE_OFF + 4]
6476
crc_region = bytes(buf[UAPP_ENTRY_OFFSET:])
6577
size = len(crc_region)
6678
crc = crc32_final(crc_region)

firmware/userapp/Core/Src/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ static void MX_CRC_Init(void)
189189
hcrc.Instance = CRC;
190190
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
191191
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
192-
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
193-
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
194-
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
192+
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
193+
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
194+
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS;
195195
if (HAL_CRC_Init(&hcrc) != HAL_OK)
196196
{
197197
Error_Handler();

0 commit comments

Comments
 (0)