bootloader+loader: rework build, make clear what is bootloader and what is loader in docu

This commit is contained in:
Pavol Rusnak 2017-03-20 15:58:47 +01:00
parent cc525e97ce
commit cbaca604f3
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
6 changed files with 28 additions and 23 deletions

View File

@ -29,9 +29,13 @@ build_firmware_debug: vendor res build_cross ## build firmware with frozen modul
$(MAKE) -f Makefile.firmware $(TREZORHAL_PORT_OPTS) DEBUG=1
build_bootloader: vendor ## build bootloader
mkdir -p $(BOOTLOADER_BUILD_DIR)/genhdr
touch $(BOOTLOADER_BUILD_DIR)/genhdr/qstrdefs.generated.h
$(MAKE) -f Makefile.bootloader $(TREZORHAL_PORT_OPTS)
build_loader: vendor ## build loader
mkdir -p $(LOADER_BUILD_DIR)/genhdr
touch $(LOADER_BUILD_DIR)/genhdr/qstrdefs.generated.h
$(MAKE) -f Makefile.loader $(TREZORHAL_PORT_OPTS)
build_unix: vendor ## build unix port

View File

@ -1,46 +1,47 @@
# TREZOR Core Bootloader
Bootloader is split into two stages. See [Memory Layout](memory.md) for info about in which sectors each stage is stored.
TREZOR initialization in split into two stages. See [Memory Layout](memory.md) for info about in which sectors each stage is stored.
First stage is stored in write-protected area, which means it is non-upgradable. Only second stage bootloader update is allowed.
First stage (bootloader) is stored in write-protected area, which means it is non-upgradable.
Only second stage (loader) update is allowed.
## First Stage Bootloader
## First Stage - Bootloader
First stage checks the integrity and signatures of the second stage and runs it if everything is OK.
If first stage bootloader finds a valid second stage bootloader image on the SD card (in raw format, no filesystem),
If first stage bootloader finds a valid second stage loader image on the SD card (in raw format, no filesystem),
it will replace the internal second stage, allowing a second stage update via SD card.
## Second Stage Bootloader
## Second Stage - Loader
Second stage checks the integrity and signatures of the firmware and runs it if everything is OK.
If second stage bootloader detects a pressed finger on the display or there is no firmware loaded in the device,
If second stage loader detects a pressed finger on the display or there is no firmware loaded in the device,
it will start in a firmware update mode, allowing a firmware update via USB.
## Common notes
* Hash function used below is SHA-256 and signature system is Ed25519 (allows combining signatures by multiple keys into one).
* All multibyte integer values are little endian.
* There is a tool called [firmwarectl](../tools/firmwarectl) which checks validity of the bootloader/firmware images including their headers.
* There is a tool called [firmwarectl](../tools/firmwarectl) which checks validity of the loader/firmware images including their headers.
## Bootloader Format
## Loader Format
TREZOR Core (second stage) bootloader consists of 2 parts:
TREZOR Core (second stage) loader consists of 2 parts:
1. bootloader header
2. bootloader code
1. loader header
2. loader code
### Bootloader Header
### Loader Header
Total length of bootloader header is always 256 bytes.
Total length of loader header is always 256 bytes.
| offset | length | name | description |
|-------:|-------:|------|-------------|
| 0x0000 | 4 | magic | firmware magic `TRZB` |
| 0x0004 | 4 | hdrlen | length of the bootloader header |
| 0x0000 | 4 | magic | firmware magic `TRZL` |
| 0x0004 | 4 | hdrlen | length of the loader header |
| 0x0008 | 4 | expiry | valid until timestamp (0=infinity) |
| 0x000C | 4 | codelen | length of the bootloader code (without the header) |
| 0x000C | 4 | codelen | length of the loader code (without the header) |
| 0x0010 | 1 | vmajor | version (major) |
| 0x0011 | 1 | vminor | version (minor) |
| 0x0012 | 1 | vpatch | version (patch) |
@ -100,7 +101,7 @@ Total length of firmware header is always 256 bytes.
## Various ideas
* Bootloader should be able to read vendor+firmware header and send info about FW to client in features message.
* Bootloader should not try to run firmware if there is not any.
* Loader should be able to read vendor + firmware header and send info about FW to client in features message.
* Loader should not try to run firmware if there is not any.
* Storage wiping rule: Don't erase storage when old FW and new FW are signed using the same key set. Otherwise erase.
* Bootloader should send error to client when firmware update fails and allow client to try one more time. This prevents storage area erasure by accident.
* Loader should send error to client when firmware update fails and allow client to try one more time. This prevents storage area erasure by accident.

View File

@ -4,11 +4,11 @@
| sector | range | size | function
|-----------|-------------------------|--------:|----------------------
| Sector 0 | 0x08000000 - 0x08003FFF | 16 KiB | bootloader 1st stage (write-protected)
| Sector 1 | 0x08004000 - 0x08007FFF | 16 KiB | bootloader 1st stage (write-protected)
| Sector 0 | 0x08000000 - 0x08003FFF | 16 KiB | bootloader (1st stage) (write-protected)
| Sector 1 | 0x08004000 - 0x08007FFF | 16 KiB | bootloader (1st stage) (write-protected)
| Sector 2 | 0x08008000 - 0x0800BFFF | 16 KiB | storage area
| Sector 3 | 0x0800C000 - 0x0800FFFF | 16 KiB | storage area
| Sector 4 | 0x08010000 - 0x0801FFFF | 64 KiB | bootloader 2nd stage
| Sector 4 | 0x08010000 - 0x0801FFFF | 64 KiB | loader (2nd stage)
| Sector 5 | 0x08020000 - 0x0803FFFF | 128 KiB | firmware
| Sector 6 | 0x08040000 - 0x0805FFFF | 128 KiB | firmware
| Sector 7 | 0x08060000 - 0x0807FFFF | 128 KiB | firmware

View File

@ -11,7 +11,7 @@ bool parse_header(const uint8_t *data, uint32_t *codelen, uint8_t *sigidx, uint8
{
uint32_t magic;
memcpy(&magic, data, 4);
if (magic != 0x425A5254) return false; // TRZB
if (magic != 0x4C5A5254) return false; // TRZL
uint32_t hdrlen;
memcpy(&hdrlen, data + 4, 4);