CRC32 Verification
Relevant source files
The following files were used as context for generating this wiki page:
CRC32 verification is a critical integrity check mechanism within the OpenAwair ecosystem, primarily utilized during the Device Firmware Update (DFU) process. It ensures that firmware binaries transferred from a host machine to the Awair hardware (Glow C or Element) remain uncorrupted during transmission. The project implements a standard CRC32 algorithm using a precomputed lookup table to maintain performance and consistency across different project layers.
Sources: host/src/shared/crc32.ts, CLAUDE.md:73-82
Core Algorithm Implementation
The CRC32 implementation is located in the shared utility directory, making it accessible to both the firmware bootloader logic and the host-side loading tools. It uses a polynomial of 0xedb88320.
Lookup Table Generation
To optimize computation, a 256-entry CRC_TABLE is generated at runtime. Each entry is calculated by iterating through 8 bits of the index and applying a bitwise right shift combined with an XOR operation against the polynomial if the least significant bit is set.
Sources: host/src/shared/crc32.ts:1-12
Calculation Logic
The crc32 function processes a Uint8Array of data. It initializes a CRC accumulator at 0xffffffff, performs byte-wise XORing and table lookups, and finally returns the bitwise NOT of the result, constrained to an unsigned 32-bit integer.
export const crc32 = (data: Uint8Array): number => {
let crc = 0xffffffff;
for (const byte of data) {
const index = (crc ^ byte) & 0xff;
crc = (crc >>> 8) ^ CRC_TABLE[index];
}
return (crc ^ 0xffffffff) >>> 0;
};
Sources: host/src/shared/crc32.ts:14-22
Application in DFU and Bootloading
The primary application of CRC32 is within the DfuSession and Bootloader classes to validate firmware images before they are committed to flash memory or executed.
DFU Session Validation
During a DFU session, firmware is received in chunks. The DfuSession tracks the received data in a buffer. Once all bytes are received, the session performs a verification by comparing the calculated CRC32 of the buffer against an expectedCrc provided at the start of the session.
Metadata Persistence
The Bootloader class manages the persistence of CRC values in the device's FlashStore. When a firmware update is successfully verified, the CRC is stored as a string using a specific configuration key (e.g., firmwareCrcKey). This allows the bootloader to decide whether the current firmware is valid upon subsequent reboots.
| Component | Responsibility | Source |
|---|---|---|
FirmwareImage | Interface holding raw bytes and its pre-calculated CRC. | dfu.ts:10-13 |
createFirmwareImage | Utility to wrap bytes and generate initial CRC32. | dfu.ts:15-17 |
Bootloader.commitFirmware | Writes the verified CRC to flash storage. | bootloader.ts:39-43 |
DfuClient.upload | Host-side tool calculating CRC of the source image. | dfuClient.ts:21-36 |
Sources: host/src/firmware/bootloader/dfu.ts, host/src/firmware/bootloader/bootloader.ts, host/src/loader/ble/dfuClient.ts
Data Flow: Host to Device
The following diagram illustrates how CRC32 is used as a handshake mechanism between the host DfuClient and the device-side DfuSession.
Testing and Stability
The implementation includes unit tests to ensure stability and cross-platform consistency. A known data set [1, 2, 3, 4, 5] is expected to consistently produce the checksum 0x470b99f4. This guarantees that the TypeScript implementation on the host matches the expected behavior of the firmware logic.
Sources: host/test/crc32.test.ts:6-9, host/test/dfu.test.ts:15-26
Summary
CRC32 verification serves as the primary safeguard for firmware integrity in OpenAwair. By centralizing the algorithm in host/src/shared/crc32.ts, the project ensures that the host's calculation of "truth" matches the device's validation logic during DFU sessions, preventing the execution of malformed or incomplete firmware images.