A command-line interface for working with a custom firmware header placed at the beginning of a binary image.
Project description
fwtool
fwtool is a command-line utility for creating, updating, inspecting, and verifying
a custom firmware metadata header prepended to a binary image.
It is intended for firmware packaging workflows where a raw application binary is post-processed into a single flashable image:
- a fixed-size header is placed at the beginning
- the firmware payload follows immediately after
- the header contains version, payload size, and CRC information
This is useful for bootloaders or firmware update logic that need to validate and identify an application image before booting or programming it.
What it does
fwtool supports four main operations:
- Attach a new header to a raw firmware binary
- Edit an existing header in a packaged binary
- Print the parsed contents of an existing header
- Verify that an existing header matches the payload
Header format
The tool generates a 256-byte header with the following layout:
| Offset | Size | Field | Description |
|---|---|---|---|
0x00..0x03 |
4 | magic | ASCII string XLAB |
0x04..0x07 |
4 | version | Little-endian bytes: [0x00, patch, minor, major] |
0x08..0x0B |
4 | size | Payload size in bytes, little-endian uint32 |
0x0C..0x0F |
4 | crc32 | CRC-32/MPEG-2 of payload, little-endian uint32 |
0x10..0xFF |
240 | padding | Filled with 0xFF |
Notes
- The CRC is calculated over the payload only, not over the header.
- The size stored in the header is the payload size only.
- The version is stored as:
- byte 0:
0x00 - byte 1: patch
- byte 2: minor
- byte 3: major
- byte 0:
For example, version 1.2.3 is stored as:
00 03 02 01
Typical use case
A common workflow looks like this:
- Link the firmware application so that it expects to execute after the reserved header space.
- Build the raw application binary.
- Use
fwtoolto prepend the metadata header. - Program the resulting combined binary into flash.
For example:
Flash address 0x08004000:
[256-byte metadata header]
[firmware payload]
Installation
Requirements
- Python 3.9+
crccheck
Install dependency manually
pip install crccheck
Run directly
If you have the script as fwtool.py, you can run it with:
python fwtool.py ...
Install as a CLI tool
If the project includes a pyproject.toml, install it in editable mode:
pip install -e .
Then run it as:
fwtool ...
Usage
fwtool binary [version] [output] [options]
Positional arguments
-
binary
Path to input binary file -
version
Firmware version string such as:11.21.2.3
-
output
Output path for attach/edit operations
Options
-
--mode {attach,edit}
Select how the tool treats the input file:attach: input is a raw binary without a headeredit: input already contains a header and it will be replaced
-
--in-place
Modify the input file directly instead of writing to a separate output file -
--print-header
Parse and print the header from an existing packaged binary -
--verify-header
Verify header magic, payload size, and payload CRC against the payload -
--json
Print machine-readable JSON output for--print-headeror--verify-header -
--quiet
Suppress output for--verify-headerand use exit code only
Examples
1. Attach a new header to a raw binary
fwtool firmware.bin 1.2.3 packaged.bin --mode attach
This creates:
packaged.bin = [256-byte header][firmware.bin payload]
2. Replace the header of an existing packaged binary
fwtool packaged.bin 1.2.4 updated.bin --mode edit
This keeps the payload but replaces the header with updated metadata.
3. Replace the header in place
fwtool packaged.bin 1.2.4 --mode edit --in-place
This modifies packaged.bin directly.
4. Attach a header in place
fwtool firmware.bin 1.2.3 --mode attach --in-place
This replaces the raw input file with a packaged binary containing the header.
5. Print header contents
fwtool packaged.bin --print-header
Example output:
magic: b'XLAB'
version: 1.2.3
size: 123456 bytes
crc32: 0x1a2b3c4d
6. Print header contents as JSON
fwtool packaged.bin --print-header --json
Example output:
{
\"magic_ascii\": \"XLAB\",
\"magic_hex\": \"584c4142\",
\"version\": {
\"major\": 1,
\"minor\": 2,
\"patch\": 3,
\"string\": \"1.2.3\"
},
\"size\": 123456,
\"crc\": {
\"int\": 439041101,
\"hex\": \"0x1a2b3c4d\"
}
}
7. Verify a packaged binary
fwtool packaged.bin --verify-header
Example output:
magic: OK
version: 1.2.3
size: OK (header=123456, actual=123456)
crc32: OK (header=0x1a2b3c4d, actual=0x1a2b3c4d)
verification: OK
8. Verify quietly using only the exit code
fwtool packaged.bin --verify-header --quiet
echo $?
Exit code meanings:
0: verification passed1: verification failed
9. Verify with JSON output
fwtool packaged.bin --verify-header --json
Example output:
{
\"ok\": true,
\"magic_ok\": true,
\"size_ok\": true,
\"crc_ok\": true,
\"header\": {
\"magic_ascii\": \"XLAB\",
\"magic_hex\": \"584c4142\",
\"version\": {
\"major\": 1,
\"minor\": 2,
\"patch\": 3,
\"string\": \"1.2.3\"
},
\"size\": 123456,
\"crc\": {
\"int\": 439041101,
\"hex\": \"0x1a2b3c4d\"
}
},
\"payload\": {
\"size\": 123456,
\"crc\": {
\"int\": 439041101,
\"hex\": \"0x1a2b3c4d\"
}
}
}
Version handling
Accepted version formats:
1→1.0.01.2→1.2.01.2.3→1.2.3
Rules:
- missing components are filled with zero
- extra components are ignored
- each component must be in the range
0..255
Verification behavior
When --verify-header is used, the tool checks:
- the magic field is
XLAB - the payload size matches the size stored in the header
- the payload CRC matches the CRC stored in the header
The header itself is not included in the size or CRC calculation.
Exit codes
General operations
0on success- non-zero on failure
--verify-header
0if verification succeeds1if verification fails
Common workflow example
Build a raw firmware image:
arm-none-eabi-objcopy -O binary app.elf app.bin
Attach metadata header:
fwtool app.bin 1.2.3 app_packed.bin --mode attach
Program the combined image to flash:
st-flash write app_packed.bin 0x08004000
Notes for embedded use
If your firmware image is packaged with a prepended header, the application must typically be linked to execute after the reserved header region.
Example:
- metadata region starts at
0x08004000 - header size is
0x100 - application is linked to start at
0x08004100
Then the combined image can be programmed at 0x08004000, and the application
payload will land at the correct runtime address.
Development
Run tests
If you have a pytest test suite:
pytest -q
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fwtool-1.0.0.tar.gz.
File metadata
- Download URL: fwtool-1.0.0.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b523afe69cfb3f4e5dfe18054d939eb17edfcdcb5c701dba39f41696feb4889
|
|
| MD5 |
9aca18ba9e68aeea04265e77bd7102df
|
|
| BLAKE2b-256 |
fc451b4cdd0c26c98e0788ce73804748e4995a8714e2ad535bd9996fda024c6c
|
File details
Details for the file fwtool-1.0.0-py3-none-any.whl.
File metadata
- Download URL: fwtool-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
209fedc07ade59808a79cc4151fa9144e7ad5e1f9d5c0a0f9cb50672fda2058f
|
|
| MD5 |
300f8a7384acb37757882330aeeb32cc
|
|
| BLAKE2b-256 |
4189da5df75e2574aa4bb46c1c4495fcf167adaa55b378f5b9707b9bac85a874
|