mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-11 16:00:57 +00:00
docs(legacy): ImHex patterns for v2 trezor.bin, v1+v2 combined trezor.bin and bootloader binary images
[no changelog]
This commit is contained in:
parent
e4bc37f10b
commit
09ebe29369
@ -125,3 +125,10 @@ This table shows the result for bootloader 1.8.0+ and 1.9.1+:
|
||||
|
||||
The other three possibilities with signed firmware and `PRODUCTION!=0` for bootloader/firmware don't exist.
|
||||
|
||||
## Parsing existing T1 binary images with ImHex
|
||||
|
||||
There is multi-platform hex editor [ImHex](https://github.com/WerWolv/ImHex) ([another link](https://imhex.werwolv.net/))
|
||||
that allows for parsing firmware images we distribute such as those from https://github.com/trezor/data/tree/master/firmware
|
||||
|
||||
See `legacy/imhex/` directory in repo and `README.md` there how to use it to parse headers from existing images.
|
||||
|
||||
|
37
legacy/imhex/README.md
Normal file
37
legacy/imhex/README.md
Normal file
@ -0,0 +1,37 @@
|
||||
# ImHex patterns for T1 firmware images
|
||||
|
||||
ImHex is multiplatform hex editor, with ability to parse binary files
|
||||
based on patterns.
|
||||
|
||||
Here are patterns for decoding binary images, there are 3 types:
|
||||
|
||||
1. firmware with both headers (TRZR and TRZF) which we distribute - `t1_firmware_v1+v2.hexpat`
|
||||
2. firmware built from git (TRZF header) - `t1_firmware_trezor_bin_v2.hexpat`
|
||||
3. bootloader - `t1_bootloader_bin.hexpat`
|
||||
|
||||
## Using ImHex with these patterns
|
||||
|
||||
Download ImHex from https://github.com/WerWolv/ImHex or https://imhex.werwolv.net/
|
||||
|
||||
### First download base library
|
||||
|
||||
You must download standard libraries via menu
|
||||
`Help->Content Store->Libraries`
|
||||
|
||||
### Opening T1 firmware images
|
||||
|
||||
In this directory, run `imhex /path/to/some_firmware.bin` (so that patterns can be
|
||||
found in current directory with includes).
|
||||
|
||||
Open pattern via `File->Load Pattern->Browse...` or add the patterns to existing
|
||||
pattern directories so that you can load without using browse. Pattern dirs are
|
||||
XDG-BASED, so your dir depending on installation will be something like
|
||||
|
||||
* `/usr/share/imhex/patterns`
|
||||
* `.local/share/imhex/patterns`
|
||||
|
||||
or see [where the directories are for other OSes](https://hackersonlineclub.com/imhex-hex-editor-for-reverse-engineers-and-programmers/).
|
||||
|
||||
## Sample screenshot
|
||||
|
||||
![ImHex screenshot](imhex_screenshot.png)
|
BIN
legacy/imhex/imhex_screenshot.png
Normal file
BIN
legacy/imhex/imhex_screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
9
legacy/imhex/t1_bootloader_bin.hexpat
Normal file
9
legacy/imhex/t1_bootloader_bin.hexpat
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma base_address 0x8000000
|
||||
|
||||
#include "t1_firmware.pat"
|
||||
|
||||
u32 VTOR = base();
|
||||
|
||||
VectorTable vector_table @ VTOR;
|
||||
|
||||
|
91
legacy/imhex/t1_firmware.pat
Normal file
91
legacy/imhex/t1_firmware.pat
Normal file
@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
#pragma endian little
|
||||
|
||||
// You must download standard libraries via menu
|
||||
// Help->Content Store->Libraries
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
#define FW_MAGIC_OLD "TRZR"
|
||||
#define FW_MAGIC_NEW "TRZF"
|
||||
|
||||
struct ImageHeader_v1 {
|
||||
char magic_old[4];
|
||||
u32 code_length;
|
||||
u8 key_indexes[3];
|
||||
u8 flags;
|
||||
u8 __reserved1[52];
|
||||
u8 sig1[64];
|
||||
u8 sig2[64];
|
||||
u8 sig3[64];
|
||||
};
|
||||
|
||||
struct ImageHeader_v2 {
|
||||
char magic_new[4];
|
||||
u32 hdrlen_or_reset_handler_thumb;
|
||||
u32 expiry;
|
||||
u32 codelen;
|
||||
u32 version;
|
||||
u32 fix_version;
|
||||
u8 __reserved1[8];
|
||||
u8 hashes[512];
|
||||
u8 sig1[64];
|
||||
u8 sig2[64];
|
||||
u8 sig3[64];
|
||||
u8 sigindex1;
|
||||
u8 sigindex2;
|
||||
u8 sigindex3;
|
||||
u8 __reserved2[220];
|
||||
u8 __sigmask;
|
||||
u8 __sig[64];
|
||||
};
|
||||
|
||||
fn base() {
|
||||
return std::mem::base_address();
|
||||
};
|
||||
|
||||
//#define VTOR (base()+0x500)
|
||||
//0x8010400
|
||||
|
||||
bitfield ARMAddress {
|
||||
ThumbMode : 1;
|
||||
Address : 31 [[transform("address_transform")]];
|
||||
} [[right_to_left]];
|
||||
|
||||
fn address_transform(u32 value) {
|
||||
return value << 1;
|
||||
};
|
||||
|
||||
fn address_mask(u32 value) {
|
||||
return value & 0xFFFFFFFE;
|
||||
};
|
||||
|
||||
using Address = u32;
|
||||
|
||||
struct Exceptions {
|
||||
Address reset [[name("Reset Handler"), transform("address_mask")]];
|
||||
// size is just estimate so that it highlights some bytes
|
||||
u8 reset_function[256] @ reset;
|
||||
Address nmi [[name("Non-maskable Interrupt Handler")]];
|
||||
Address hard_fault [[name("HardFault Handler")]];
|
||||
Address mem_manage [[name("Memory Protection Error Handler")]];
|
||||
Address bus_fault [[name("Bus Fault Handler")]];
|
||||
Address usage_fault [[name("UsageFault (Instruction Execution fault) Handler")]];
|
||||
Address reserved_1[4] [[hidden]];
|
||||
Address sv_call [[name("Synchronous Supervisor Call (SVC Instruction) Handler")]];
|
||||
Address debug_monitor [[name("Synchronous Debug Event Handler")]];
|
||||
Address reserved_2[1] [[hidden]];
|
||||
Address pend_sv [[name("Asynchronous Supervisor Call Handler")]];
|
||||
Address sys_tick [[name("System Timer Tick Handler")]];
|
||||
};
|
||||
|
||||
struct VectorTable {
|
||||
Address initial_sp [[name("Initial Stack Pointer Value")]];
|
||||
Exceptions exceptions [[inline, name("Exceptions")]];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
15
legacy/imhex/t1_firmware_trezor_bin_v2.hexpat
Normal file
15
legacy/imhex/t1_firmware_trezor_bin_v2.hexpat
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma base_address 0x8010000
|
||||
|
||||
#include "t1_firmware.pat"
|
||||
|
||||
u32 V2_HEADER_BASE = base();
|
||||
u32 VTOR = V2_HEADER_BASE + 0x400;
|
||||
|
||||
#define FW_MAGIC_NEW "TRZF"
|
||||
|
||||
ImageHeader_v2 header_v2 @ V2_HEADER_BASE;
|
||||
VectorTable vector_table @ VTOR;
|
||||
|
||||
std::assert(header_v2.magic_new == FW_MAGIC_NEW, "Wrong NEW magic, expected TRFZ at start");
|
||||
|
||||
|
30
legacy/imhex/t1_firmware_v1+v2.hexpat
Normal file
30
legacy/imhex/t1_firmware_v1+v2.hexpat
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma base_address 0x800FF00
|
||||
|
||||
#include "t1_firmware.pat"
|
||||
|
||||
u32 V1_HEADER_BASE = base();
|
||||
u32 V2_HEADER_BASE = base() + 0x100;
|
||||
u32 VTOR = V2_HEADER_BASE + 0x400;
|
||||
|
||||
#define FW_MAGIC_OLD "TRZR"
|
||||
#define FW_MAGIC_NEW "TRZF"
|
||||
|
||||
ImageHeader_v1 header_v1 @ V1_HEADER_BASE;
|
||||
ImageHeader_v2 header_v2 @ V2_HEADER_BASE;
|
||||
VectorTable vector_table @ VTOR;
|
||||
|
||||
// this could be out of bounds, just warn if VTOR and old pre-1.8.0 bootloader
|
||||
// reset handlers are not the same
|
||||
u32 reset_start_v1 = (header_v2.hdrlen_or_reset_handler_thumb & 0xFFFFFFFE);
|
||||
if (reset_start_v1 != (vector_table.exceptions.reset)) {
|
||||
std::print("v1 reset handler differs from VTOR");
|
||||
};
|
||||
|
||||
// another possible declaration of exception handler with masking
|
||||
// u8 reset_start_vtor[256] @ (vector_table.exceptions.reset & 0xFFFFFFFE);
|
||||
// declaration via ptr, needs mask out Thumb bit
|
||||
// u8 *reset_start_v1_ptr : u32 @ (V2_HEADER_BASE + 0x4);
|
||||
|
||||
std::assert(header_v1.magic_old == FW_MAGIC_OLD, "Wrong OLD magic");
|
||||
std::assert(header_v2.magic_new == FW_MAGIC_NEW, "Wrong NEW magic");
|
||||
|
Loading…
Reference in New Issue
Block a user