mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 22:38:08 +00:00
feat(core): compress embedded bootloader
[no changelog]
This commit is contained in:
parent
1c69644fe0
commit
bf2697a619
@ -793,16 +793,14 @@ if TREZOR_MODEL not in ('1',):
|
|||||||
' $SOURCE $TARGET', ))
|
' $SOURCE $TARGET', ))
|
||||||
|
|
||||||
if TREZOR_MODEL not in ('DISC1', ):
|
if TREZOR_MODEL not in ('DISC1', ):
|
||||||
obj_program.extend(
|
tools.embed_binary(
|
||||||
env.Command(
|
obj_program,
|
||||||
target='embed/firmware/bootloaders/bootloader.o',
|
env,
|
||||||
source=f'embed/firmware/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin',
|
'bootloader',
|
||||||
action='$OBJCOPY -I binary -O elf32-littlearm -B arm'
|
'embed/firmware/bootloaders/bootloader.o',
|
||||||
' --rename-section .data=.bootloader'
|
f'embed/firmware/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin',
|
||||||
f' --redefine-sym _binary_embed_firmware_bootloaders_bootloader_{BOOTLOADER_SUFFIX}_bin_start=_binary_embed_firmware_bootloader_bin_start'
|
)
|
||||||
f' --redefine-sym _binary_embed_firmware_bootloaders_bootloader_{BOOTLOADER_SUFFIX}_bin_end=_binary_embed_firmware_bootloader_bin_end'
|
|
||||||
f' --redefine-sym _binary_embed_firmware_bootloaders_bootloader_{BOOTLOADER_SUFFIX}_bin_size=_binary_embed_firmware_bootloader_bin_size'
|
|
||||||
' $SOURCE $TARGET', ))
|
|
||||||
|
|
||||||
env.Depends(obj_program, qstr_generated)
|
env.Depends(obj_program, qstr_generated)
|
||||||
|
|
||||||
|
@ -24,11 +24,15 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
#include "memzero.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
|
#include "uzlib.h"
|
||||||
|
|
||||||
// symbols from bootloader.bin => bootloader.o
|
// symbols from bootloader.bin => bootloader.o
|
||||||
extern const void _binary_embed_firmware_bootloader_bin_start;
|
extern const void
|
||||||
extern const void _binary_embed_firmware_bootloader_bin_size;
|
_binary_embed_firmware_bootloaders_bootloader_bin_deflated_start;
|
||||||
|
extern const void
|
||||||
|
_binary_embed_firmware_bootloaders_bootloader_bin_deflated_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
static secbool known_bootloader(const uint8_t *hash, int len) {
|
static secbool known_bootloader(const uint8_t *hash, int len) {
|
||||||
@ -111,11 +115,31 @@ static secbool latest_bootloader(const uint8_t *hash, int len) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define UZLIB_WINDOW_SIZE (1 << 10)
|
||||||
|
|
||||||
|
#if PRODUCTION || BOOTLOADER_QA
|
||||||
|
static void uzlib_prepare(struct uzlib_uncomp *decomp, uint8_t *window,
|
||||||
|
const void *src, uint32_t srcsize, void *dest,
|
||||||
|
uint32_t destsize) {
|
||||||
|
memzero(decomp, sizeof(struct uzlib_uncomp));
|
||||||
|
if (window) {
|
||||||
|
memzero(window, UZLIB_WINDOW_SIZE);
|
||||||
|
}
|
||||||
|
memzero(dest, destsize);
|
||||||
|
decomp->source = (const uint8_t *)src;
|
||||||
|
decomp->source_limit = decomp->source + srcsize;
|
||||||
|
decomp->dest = (uint8_t *)dest;
|
||||||
|
decomp->dest_limit = decomp->dest + destsize;
|
||||||
|
uzlib_uncompress_init(decomp, window, window ? UZLIB_WINDOW_SIZE : 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void check_and_replace_bootloader(void) {
|
void check_and_replace_bootloader(void) {
|
||||||
#if PRODUCTION || BOOTLOADER_QA
|
#if PRODUCTION || BOOTLOADER_QA
|
||||||
|
|
||||||
// compute current bootloader hash
|
// compute current bootloader hash
|
||||||
uint8_t hash[BLAKE2S_DIGEST_LENGTH];
|
uint8_t hash[BLAKE2S_DIGEST_LENGTH];
|
||||||
const uint32_t bl_len = 128 * 1024;
|
const uint32_t bl_len = flash_area_get_size(&BOOTLOADER_AREA);
|
||||||
const void *bl_data = flash_area_get_address(&BOOTLOADER_AREA, 0, bl_len);
|
const void *bl_data = flash_area_get_address(&BOOTLOADER_AREA, 0, bl_len);
|
||||||
blake2s(bl_data, bl_len, hash, BLAKE2S_DIGEST_LENGTH);
|
blake2s(bl_data, bl_len, hash, BLAKE2S_DIGEST_LENGTH);
|
||||||
|
|
||||||
@ -130,14 +154,25 @@ void check_and_replace_bootloader(void) {
|
|||||||
|
|
||||||
// replace bootloader with the latest one
|
// replace bootloader with the latest one
|
||||||
const uint32_t *data =
|
const uint32_t *data =
|
||||||
(const uint32_t *)&_binary_embed_firmware_bootloader_bin_start;
|
(const uint32_t
|
||||||
|
*)&_binary_embed_firmware_bootloaders_bootloader_bin_deflated_start;
|
||||||
const uint32_t len =
|
const uint32_t len =
|
||||||
(const uint32_t)&_binary_embed_firmware_bootloader_bin_size;
|
(const uint32_t)&_binary_embed_firmware_bootloaders_bootloader_bin_deflated_size;
|
||||||
|
|
||||||
|
struct uzlib_uncomp decomp = {0};
|
||||||
|
uint8_t decomp_window[UZLIB_WINDOW_SIZE] = {0};
|
||||||
|
uint32_t decomp_out[IMAGE_HEADER_SIZE / sizeof(uint32_t)] = {0};
|
||||||
|
|
||||||
|
uzlib_prepare(&decomp, decomp_window, data, len, decomp_out,
|
||||||
|
sizeof(decomp_out));
|
||||||
|
|
||||||
|
ensure((uzlib_uncompress(&decomp) == TINF_OK) ? sectrue : secfalse,
|
||||||
|
"Bootloader header decompression failed");
|
||||||
|
|
||||||
const image_header *new_bld_hdr = read_image_header(
|
const image_header *new_bld_hdr = read_image_header(
|
||||||
(uint8_t *)data, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE);
|
(uint8_t *)decomp_out, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE);
|
||||||
|
|
||||||
ensure(new_bld_hdr == (const image_header *)data ? sectrue : secfalse,
|
ensure(new_bld_hdr == (const image_header *)decomp_out ? sectrue : secfalse,
|
||||||
"Invalid embedded bootloader");
|
"Invalid embedded bootloader");
|
||||||
|
|
||||||
ensure(check_image_model(new_bld_hdr), "Incompatible embedded bootloader");
|
ensure(check_image_model(new_bld_hdr), "Incompatible embedded bootloader");
|
||||||
@ -177,16 +212,32 @@ void check_and_replace_bootloader(void) {
|
|||||||
|
|
||||||
ensure(flash_area_erase(&BOOTLOADER_AREA, NULL), NULL);
|
ensure(flash_area_erase(&BOOTLOADER_AREA, NULL), NULL);
|
||||||
ensure(flash_unlock_write(), NULL);
|
ensure(flash_unlock_write(), NULL);
|
||||||
for (int i = 0; i < len / sizeof(uint32_t); i++) {
|
|
||||||
ensure(
|
uint32_t offset = 0;
|
||||||
flash_area_write_word(&BOOTLOADER_AREA, i * sizeof(uint32_t), data[i]),
|
|
||||||
NULL);
|
do {
|
||||||
|
uint32_t *p = decomp_out;
|
||||||
|
uint32_t last_whole_word_addr = (((uint32_t)decomp.dest) & ~3);
|
||||||
|
while ((uint32_t)p < last_whole_word_addr) {
|
||||||
|
ensure(flash_area_write_word(&BOOTLOADER_AREA, offset, *p++), NULL);
|
||||||
|
offset += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
for (int i = len / sizeof(uint32_t); i < 128 * 1024 / sizeof(uint32_t); i++) {
|
if ((uint8_t *)p < decomp.dest) {
|
||||||
ensure(flash_area_write_word(&BOOTLOADER_AREA, i * sizeof(uint32_t),
|
// last few bytes in case of unaligned data
|
||||||
0x00000000),
|
uint32_t d = 0;
|
||||||
NULL);
|
memcpy(&d, p, (uint32_t)decomp.dest - (uint32_t)p);
|
||||||
|
ensure(flash_area_write_word(&BOOTLOADER_AREA, offset, d), NULL);
|
||||||
|
offset += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
decomp.dest = (uint8_t *)decomp_out;
|
||||||
|
} while (uzlib_uncompress(&decomp) >= 0);
|
||||||
|
|
||||||
|
// fill the rest of the bootloader area with 0x00
|
||||||
|
while (offset < bl_len) {
|
||||||
|
ensure(flash_area_write_word(&BOOTLOADER_AREA, offset, 0x00000000), NULL);
|
||||||
|
offset += sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
|
||||||
ensure(flash_lock_write(), NULL);
|
ensure(flash_lock_write(), NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import zlib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from boards import (
|
from boards import (
|
||||||
@ -120,3 +121,51 @@ def get_defs_for_cmake(defs: list[str | tuple[str, str]]) -> list[str]:
|
|||||||
else:
|
else:
|
||||||
result.append(d)
|
result.append(d)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _compress(data: bytes) -> bytes:
|
||||||
|
z = zlib.compressobj(level=9, wbits=-10)
|
||||||
|
return z.compress(data) + z.flush()
|
||||||
|
|
||||||
|
|
||||||
|
def embed_binary(obj_program, env, section, target_, file):
|
||||||
|
_in = f"embedded_{section}.bin.deflated"
|
||||||
|
|
||||||
|
def redefine_sym(name):
|
||||||
|
src = (
|
||||||
|
"_binary_build_firmware_"
|
||||||
|
+ _in.replace("/", "_").replace(".", "_")
|
||||||
|
+ "_"
|
||||||
|
+ name
|
||||||
|
)
|
||||||
|
dest = (
|
||||||
|
"_binary_"
|
||||||
|
+ target_.replace("/", "_").replace(".o", "_bin_deflated")
|
||||||
|
+ "_"
|
||||||
|
+ name
|
||||||
|
)
|
||||||
|
return f" --redefine-sym {src}={dest}"
|
||||||
|
|
||||||
|
def compress_action(target, source, env):
|
||||||
|
srcf = Path(str(source[0]))
|
||||||
|
dstf = Path(str(target[0]))
|
||||||
|
compressed = _compress(srcf.read_bytes())
|
||||||
|
dstf.write_bytes(compressed)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
compress = env.Command(target=_in, source=file, action=compress_action)
|
||||||
|
|
||||||
|
obj_program.extend(
|
||||||
|
env.Command(
|
||||||
|
target=target_,
|
||||||
|
source=_in,
|
||||||
|
action="$OBJCOPY -I binary -O elf32-littlearm -B arm"
|
||||||
|
f" --rename-section .data=.{section}"
|
||||||
|
+ redefine_sym("start")
|
||||||
|
+ redefine_sym("end")
|
||||||
|
+ redefine_sym("size")
|
||||||
|
+ " $SOURCE $TARGET",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
env.Depends(obj_program, compress)
|
||||||
|
Loading…
Reference in New Issue
Block a user