Skip to content

Commit 5885a5d

Browse files
committed
bootloader: make screen messages more user friendly
Some consider "bootloader" text on the screen confusing, so the bootloader now invites users to follow instructions on the BitBoxApp screen, consistent with the regular mode once a firmware is booted. In the case where app flash is empty, it also displays a "let's get started" message, as well as rendering chunk writes progress with "INSTALLING" label. BitBox02 is shipped with empty app flash. It can also be erased manually via the bootloader protocol. The commit also introduces a separate bootloader changelog since we've never had it before and bootloader's release cycle is different from that of the firmware.
1 parent c247526 commit 5885a5d

File tree

3 files changed

+60
-9
lines changed

3 files changed

+60
-9
lines changed

CHANGELOG.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
# Changelog
22

3-
## [Unreleased]
3+
The changelog records significant changes to both the firmware and the
4+
bootloader. Since the bootloader has a separate release cycle and existing
5+
customers cannot upgrade their bootloader, its changes are recorded separately.
6+
7+
## Firmware
8+
9+
### [Unreleased]
410
- Display granular error codes when unlock fails unexpectedly
511

6-
## 9.6.0 [released 2021-05-20]
12+
### 9.6.0 [released 2021-05-20]
713
- Attempt to fix flaky SD behavior
814
- Add securechip_model to DeviceInfo: ATECCC608A or ATECC608B.
915
- Added reboot purpose for clearer UX: "Proceed to upgrade?" vs. "Go to startup settings?"
1016
- Allow creation of 128 bit seeds (12 BIP39 recovery words)
1117
- Increase maximum number of registered multisig accounts from 10 to 25.
1218

13-
## 9.5.0 [released 2021-03-10]
19+
### 9.5.0 [released 2021-03-10]
1420
- RestoreFrommnemonic: ported to Rust. Will now return UserAbortError on user abort instead of GenericError.
1521
- Anti-klepto support for ETH transaction signing and for BTC and ETH message signing.
1622
- Add Uniswap ERC-20 token.
1723
- Display warning before confirming raw ETH data.
1824

19-
## 9.4.0 [released 2021-01-20]
25+
### 9.4.0 [released 2021-01-20]
2026
- ETHPubRequest api call now fails if a an invalid contract address is provided also if `display` is
2127
false.
2228
- Fix a memory leak (freeing a malloc'd string - no a functional or security issue)
@@ -26,10 +32,15 @@
2632
- Fix a rare touch issue resulting from failed calibration.
2733
- Protection against the nonce covert channel attack when singing Bitcoin/Litecoin transactions (antiklepto protocol).
2834

29-
## 9.3.1 [tagged 2020-12-01]
35+
### 9.3.1 [tagged 2020-12-01]
3036
- Fix a bug where the device could freeze and become unresponsive.
3137

32-
## 9.3.0 [tagged 2020-11-23]
38+
### 9.3.0 [tagged 2020-11-23]
3339
- Enter multisig account name on the device if the name in BTCRegisterScriptConfigRequest is empty.
3440
- Allow new keypaths: m/48'/coin'/account' for multisig, to enable compatibility with the Nunchuk wallet.
3541
- Multisig script type and derivation keypath are now also verified during account regisration.
42+
43+
## Bootloader
44+
45+
### v1.0.4
46+
- Make bootloader mode more user-friendly and prompt for action on empty firmware

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ endif()
9292
set(FIRMWARE_VERSION "v9.6.1")
9393
set(FIRMWARE_BTC_ONLY_VERSION "v9.6.1")
9494
set(FIRMWARE_BITBOXBASE_VERSION "v9.6.1")
95-
set(BOOTLOADER_VERSION "v1.0.3")
95+
set(BOOTLOADER_VERSION "v1.0.4")
9696

9797
find_package(PythonInterp 3.6 REQUIRED)
9898

src/bootloader/bootloader.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,26 @@ typedef union {
160160

161161
static uint8_t _loading_ready = 0;
162162
static uint8_t _firmware_num_chunks = 0;
163+
// Indicates whether the whole app flash contains only 0xFF.
164+
// This controls bootloader text messages on the screen.
165+
// The value is computed at bootloader enter.
166+
static uint8_t _is_app_flash_empty = 0;
167+
168+
// A "bare" firmware hash where all app flash sections are empty.
169+
// Bare meaning the hash is computed in the same way as _firmware_hash except
170+
// the firmware version is omitted.
171+
// If FLASH_APP_LEN is changed, recompute with either a shell command:
172+
// printf '%884736s' | tr ' ' '\377' | openssl sha256 -binary | openssl sha256 -hex
173+
// or python:
174+
// hashlib.sha256(hashlib.sha256(b'\xff' * 884736).digest()).hexdigest()
175+
static const uint8_t _empty_bare_flash_hash[SHA256_DIGEST_LENGTH] = {
176+
0xbf, 0x71, 0x80, 0xc1, 0x23, 0xdf, 0xb5, 0x96, 0x1d, 0x93, 0xcd, 0x5f, 0xd9, 0x8a, 0xa4, 0x35,
177+
0x00, 0xb8, 0xaf, 0x3a, 0x79, 0xf8, 0xc6, 0x56, 0x4a, 0x9b, 0x02, 0xe1, 0x8a, 0xb8, 0x21, 0xae,
178+
};
179+
#if FLASH_APP_LEN != 884736
180+
#error "FLASH_APP_LEN changed; recompute _empty_bare_flash_hash"
181+
#endif
182+
163183
// clang-format off
164184
#if PRODUCT_BITBOX_BTCONLY == 1
165185
static const uint8_t _root_pubkeys[BOOT_NUM_ROOT_SIGNING_KEYS][BOOT_PUBKEY_LEN] = { // order is important
@@ -336,7 +356,10 @@ static void _render_default_screen(void)
336356
{
337357
UG_ClearBuffer();
338358
_load_logo();
339-
UG_PutString(1, SCREEN_HEIGHT - 9, "BOOTLOADER", false);
359+
if (_is_app_flash_empty) {
360+
UG_PutString(0, SCREEN_HEIGHT - 9 * 2, "Let's get started!", false);
361+
}
362+
UG_PutString(0, SCREEN_HEIGHT - 9, "See the BitBoxApp", false);
340363
UG_SendBuffer();
341364
}
342365

@@ -352,7 +375,11 @@ static void _render_progress(float progress)
352375
} else {
353376
_load_arrow(0, SCREEN_HEIGHT - 16, 10);
354377
}
355-
UG_PutString(SCREEN_WIDTH / 2 - 3, SCREEN_HEIGHT - 9 * 2, "UPGRADING", false);
378+
const char* msg = "UPGRADING";
379+
if (_is_app_flash_empty) {
380+
msg = "INSTALLING";
381+
}
382+
UG_PutString(SCREEN_WIDTH / 2 - 3, SCREEN_HEIGHT - 9 * 2, msg, false);
356383
UG_SendBuffer();
357384
}
358385

@@ -407,6 +434,18 @@ static void _render_hash(const char* title, const uint8_t* hash)
407434
_render_default_screen();
408435
}
409436

437+
// Sets _is_app_flash_empty by computing a "bare" hash, identical to _firmware_hash
438+
// except omitting the firmware version.
439+
static void _compute_is_app_flash_empty(void)
440+
{
441+
uint8_t hash[SHA256_DIGEST_LENGTH];
442+
sha_sync_sha256_start(&HASH_ALGORITHM_0, &_pukcc_sha256_context, false);
443+
sha_sync_sha256_update(&HASH_ALGORITHM_0, (const uint8_t*)FLASH_APP_START, FLASH_APP_LEN);
444+
sha_sync_sha256_finish(&HASH_ALGORITHM_0, hash);
445+
pukcc_sha256_compute(hash, SHA256_DIGEST_LENGTH, hash);
446+
_is_app_flash_empty = MEMEQ(hash, _empty_bare_flash_hash, sizeof(_empty_bare_flash_hash));
447+
}
448+
410449
static size_t _report_status(uint8_t status, uint8_t* output)
411450
{
412451
output[1] = status;
@@ -1003,6 +1042,7 @@ void bootloader_jump(void)
10031042
}
10041043

10051044
// App not entered. Start USB API to receive boot commands
1045+
_compute_is_app_flash_empty();
10061046
_render_default_screen();
10071047
#if PLATFORM_BITBOX02 == 1
10081048
if (usb_start(_api_setup) != ERR_NONE) {

0 commit comments

Comments
 (0)