Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Firmware ID to binary #4

Merged
merged 2 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -120,10 +120,8 @@ int main()
sd::close_update_file(file, FIRMWARE_UPDATE_FILE);
}

// 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