Improved flash image validation (#1916)

This commit is contained in:
Mark Thompson 2024-02-18 12:02:42 -06:00 committed by GitHub
parent a1f7010e08
commit cd80da58d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 4 deletions

View File

@ -28,27 +28,49 @@ namespace ui {
static const char16_t* firmware_folder = u"/FIRMWARE"; static const char16_t* firmware_folder = u"/FIRMWARE";
// Firmware image validation
static const char* hackrf_magic = "HACKRFFW";
#define FIRMWARE_INFO_AREA_OFFSET 0x400
#define FIRST_CHECKSUM_NIGHTLY 240125
Thread* FlashUtilityView::thread{nullptr}; Thread* FlashUtilityView::thread{nullptr};
static constexpr size_t max_filename_length = 26; static constexpr size_t max_filename_length = 26;
bool valid_firmware_file(std::filesystem::path::string_type path) { bool valid_firmware_file(std::filesystem::path::string_type path) {
File firmware_file; File firmware_file;
bool require_checksum{false};
uint32_t read_buffer[128]; uint32_t read_buffer[128];
uint32_t checksum{(uint32_t)~FLASH_EXPECTED_CHECKSUM}; // initializing to invalid checksum in case file can't be read uint32_t checksum{FLASH_CHECKSUM_ERROR}; // initializing to invalid checksum in case file can't be read
static_assert((FIRMWARE_INFO_AREA_OFFSET % sizeof(read_buffer)) == 0, "Read buffer size must divide evenly into FIRMWARE_INFO_AREA_OFFSET");
// test read of the whole file just to validate checksum (baseband flash code will re-read when flashing) // test read of the whole file just to validate checksum (baseband flash code will re-read when flashing)
auto result = firmware_file.open(path.c_str()); auto result = firmware_file.open(path.c_str());
if (!result.is_valid()) { if (!result.is_valid()) {
checksum = 0; checksum = 0;
for (uint32_t i = 0; i < FLASH_ROM_SIZE / sizeof(read_buffer); i++) { for (uint32_t offset = 0; offset < FLASH_ROM_SIZE; offset += sizeof(read_buffer)) {
auto readResult = firmware_file.read(&read_buffer, sizeof(read_buffer)); auto readResult = firmware_file.read(&read_buffer, sizeof(read_buffer));
// if file is smaller than 1MB, assume it's a downgrade to an old FW version and ignore the checksum
if ((!readResult) || (readResult.value() != sizeof(read_buffer))) { if ((!readResult) || (readResult.value() != sizeof(read_buffer))) {
checksum = FLASH_EXPECTED_CHECKSUM; // File was smaller than 1MB:
// If version is such that the file SHOULD have been 1MB, call it a checksum error (otherwise say it's OK).
checksum = (require_checksum) ? FLASH_CHECKSUM_ERROR : FLASH_EXPECTED_CHECKSUM;
break; break;
} }
// Did we just read the firmware info area?
if (offset == FIRMWARE_INFO_AREA_OFFSET) {
// If there's no info area (missing HACKRFFW signature), it could be an ancient FW version (so skipping check)
if (memcmp(read_buffer, hackrf_magic, 8) == 0) {
char* version_string = (char*)&read_buffer[4];
// Require a 1MB firmware image with a valid checksum if release version >=v2.x or nightly >n_240125
if (((version_string[0] == 'v') && (std::atoi(&version_string[1]) >= 2)) ||
((version_string[0] == 'n') && (version_string[1] == '_') && (std::atoi(&version_string[2]) >= FIRST_CHECKSUM_NIGHTLY)))
require_checksum = true;
}
}
checksum += simple_checksum((uint32_t)read_buffer, sizeof(read_buffer)); checksum += simple_checksum((uint32_t)read_buffer, sizeof(read_buffer));
} }
} }

View File

@ -35,6 +35,7 @@
#define FLASH_ROM_SIZE 1048576 #define FLASH_ROM_SIZE 1048576
#define FLASH_STARTING_ADDRESS 0x00000000 #define FLASH_STARTING_ADDRESS 0x00000000
#define FLASH_EXPECTED_CHECKSUM 0x00000000 #define FLASH_EXPECTED_CHECKSUM 0x00000000
#define FLASH_CHECKSUM_ERROR 0xFFFFFFFF
namespace ui { namespace ui {