Skip to content

Commit

Permalink
Add Firmware ID to binary (#4)
Browse files Browse the repository at this point in the history
* add fwid module

* sanity check firmware size using FWID
  • Loading branch information
shadow578 authored May 20, 2024
1 parent 31c1016 commit 3d001b3
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 8 deletions.
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ monitor_speed = 115200
# use a python script to retrieve version info from git
extra_scripts =
pre:scripts/version.py
post:scripts/check_fwid.py

# configure code checking
check_tool = cppcheck
Expand Down
60 changes: 60 additions & 0 deletions scripts/check_fwid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import sys
from os import path
import re

Import("env")

def check_fwid(source, target, env):
"""Check the Firmware ID of the binary."""
firmware_bin = target[0].get_abspath()

def read_fwid(bin_path: str) -> dict:
"""Read and Parse the Firmware ID from the binary."""

# firmware id is matched with the following regex:
# - first group: 32-bit hex number, APP_BASE_ADDRESS
# - second group: firmware version string
fwid_regex = r"OpenHC32Boot A:0x([0-9A-F]+) V:(.+)"

# read binary as a string, search for a string match
with open(bin_path, "rb") as f:
content = f.read().decode("ascii", errors="replace")

match = re.search(fwid_regex, content)
if match is None:
return None

return {
"fwid": match.group(0),
"app_base_address": int(match.group(1), 16),
"bootloader_version": match.group(2)
}

# read the firmware id from the binary
fwid = read_fwid(firmware_bin)
if fwid is None:
sys.stderr.write(f"Failed to read FWID from '{firmware_bin}'\n")
sys.exit(1)

# print firmware id information
print(f"Read Firmware ID '{fwid['fwid']}' from '{firmware_bin}'")

# ensure file_size(firmware.bin) <= APP_BASE_ADDRESS
firmware_bin_size = path.getsize(firmware_bin)

if firmware_bin_size > fwid["app_base_address"]:
sys.stderr.write(f"Error: Firmware size ({hex(firmware_bin_size)}) is too large for APP_BASE_ADDRESS={hex(fwid['app_base_address'])}\n")

# calculate minimum required APP_BASE_ADDRESS
min_app_base_address = 0
while min_app_base_address < firmware_bin_size:
min_app_base_address += 0x2000

sys.stderr.write(f"Error: Set APP_BASE_ADDRESS to {hex(min_app_base_address)}\n")

sys.exit(1)

env.AddPostAction(
path.join(env.get("BUILD_DIR"), env.get("PROGNAME") + ".bin"),
env.VerboseAction(check_fwid, "Checking FWID")
)
14 changes: 6 additions & 8 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ int main()

screen.init();

// print firmware identification message as early as possible
fwid::print();
beep::beep(100);

#if ENABLE_BOOTLOADER_PROTECTION == 1
// initialize protection of the bootloader region
mpu::init(true, true, false);
Expand All @@ -70,10 +74,6 @@ int main()
flash::write_protect::enable();
#endif

// print hello message
logging::log("OpenHC32Boot " BOOTLOADER_VERSION "\n");
beep::beep(100);

#if PRINT_CHIPID == 1
chipid::print();
#endif
Expand Down Expand Up @@ -116,10 +116,8 @@ int main()
}
}

// log application jump address
logging::log("jumping to app @ ");
logging::log(APP_BASE_ADDRESS, 16);
logging::log("\n");
// log application jump
logging::log("jumping to app\n");

// run pre-checks on the application
if (!leap::pre_check(APP_BASE_ADDRESS))
Expand Down
1 change: 1 addition & 0 deletions src/modules.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
#include "modules/assert.h"
#include "modules/compat.h"
#include "modules/flash_wp.h"
#include "modules/fwid.h"
23 changes: 23 additions & 0 deletions src/modules/fwid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "fwid.h"
#include "log.h"
#include "../config.h"
#include "../util.h"

#if APP_BASE_ADDRESS == 0x2000
#define APP_BASE_ADDRESS_STR "0x2000"
#elif APP_BASE_ADDRESS == 0x4000
#define APP_BASE_ADDRESS_STR "0x4000"
#elif APP_BASE_ADDRESS == 0x6000
#define APP_BASE_ADDRESS_STR "0x6000"
#elif APP_BASE_ADDRESS == 0x8000
#define APP_BASE_ADDRESS_STR "0x8000"
#else
#error "Invalid APP_BASE_ADDRESS for FWID"
#endif

void fwid::print()
{
// "OpenHC32Boot A:[APP_BASE_ADDRESS] V:[VERSION] ", eg.: "OpenHC32Boot A:0x4000 V:1.0.0 "
// Note: the 'check_fwid.py' script depends on this format, so it must be updated if this is changed
logging::log("OpenHC32Boot A:" APP_BASE_ADDRESS_STR " V:" BOOTLOADER_VERSION "\n");
}
9 changes: 9 additions & 0 deletions src/modules/fwid.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

namespace fwid
{
/**
* @brief print firmware ID information
*/
void print();
} // namespace fwid

0 comments on commit 3d001b3

Please sign in to comment.