Merge branch 'nrf52-hash-fix' into radiolib

This commit is contained in:
jacob.eva 2024-10-03 20:33:42 +01:00
commit e68fe37fb1
No known key found for this signature in database
GPG Key ID: 0B92E083BBCCAA1E
6 changed files with 3729 additions and 82 deletions

102
Device.h
View File

@ -141,6 +141,38 @@ void device_save_firmware_hash() {
} }
#if MCU_VARIANT == MCU_NRF52 #if MCU_VARIANT == MCU_NRF52
#define FW_LENGTH_LEN 4
#if MCU_VARIANT == MCU_NRF52
void set_fw_length(uint8_t* length_array) {
fw_length_file.open(FW_LENGTH_FILE, FILE_O_WRITE);
fw_length_file.seek(0);
fw_length_file.write(length_array, FW_LENGTH_LEN);
fw_length_file.close();
hard_reset();
}
unsigned long get_fw_length() {
fw_length_file.open(FW_LENGTH_FILE, FILE_O_READ);
// If file doesn't exist yet
if (!fw_length_file) {
return 0;
}
uint8_t length_array[4];
fw_length_file.read(length_array, 4);
unsigned long length = (length_array[0] << 24) | (length_array[1] << 16) | (length_array[2] << 8) | length_array[3];
return length;
}
#endif
void calculate_region_hash(unsigned long long start, unsigned long long end, uint8_t* return_hash) { void calculate_region_hash(unsigned long long start, unsigned long long end, uint8_t* return_hash) {
// this function calculates the hash digest of a region of memory, // this function calculates the hash digest of a region of memory,
// currently it is only designed to work for the application region // currently it is only designed to work for the application region
@ -158,10 +190,10 @@ void calculate_region_hash(unsigned long long start, unsigned long long end, uin
int end_count = 0; int end_count = 0;
unsigned long length = 0; unsigned long length = 0;
while (start < end - 1 ) { while (start < end) {
const void* src = (const void*)start; const void* src = (const void*)start;
if (start + CHUNK_SIZE >= end) { if (start + CHUNK_SIZE >= end) {
size = (end - 1) - start; size = end - start;
} }
else { else {
size = CHUNK_SIZE; size = CHUNK_SIZE;
@ -169,74 +201,14 @@ void calculate_region_hash(unsigned long long start, unsigned long long end, uin
memcpy(chunk, src, CHUNK_SIZE); memcpy(chunk, src, CHUNK_SIZE);
// check if we've reached the end of the program
// if we're checking the application region
if (application) { if (application) {
for (int i = 0; i < CHUNK_SIZE; i++) { for (int i = 0; i < CHUNK_SIZE; i++) {
if (chunk[i] == 0xFF) { // do nothing
bool matched = true;
end_count = 1;
// check if rest of chunk is FFs as well, only if FF is not
// at the end of chunk
if (i < CHUNK_SIZE - 1) {
for (int x = 0; x < CHUNK_SIZE - i; x++) {
if (chunk[i+x] != 0xFF) {
matched = false;
break;
} }
end_count++;
}
}
if (matched) {
while (end_count < END_SECTION_SIZE) {
// check if bytes in next chunk up to total
// required are also FFs
for (int x = 1; x <= ceil(END_SECTION_SIZE / CHUNK_SIZE); x++) {
const void* src_next = (const void*)start + CHUNK_SIZE*x;
if ((END_SECTION_SIZE - end_count) > CHUNK_SIZE) {
size = CHUNK_SIZE;
} else {
size = END_SECTION_SIZE - end_count;
}
memcpy(chunk_next, src_next, size);
for (int y = 0; y < size; y++) {
if (chunk_next[y] != 0xFF) {
matched = false;
break;
}
end_count++;
}
if (!matched) {
break;
}
}
if (!matched) {
break;
}
}
if (matched) {
finish = true;
size = i;
break;
}
}
}
}
}
if (finish) {
hash.update(chunk, size); hash.update(chunk, size);
length += size; length += size;
break;
} else {
hash.update(chunk, size);
}
start += CHUNK_SIZE; start += CHUNK_SIZE;
length += CHUNK_SIZE; }
} }
hash.end(return_hash); hash.end(return_hash);
} }
@ -257,7 +229,7 @@ void device_validate_partitions() {
esp_partition_get_sha256(esp_ota_get_running_partition(), dev_firmware_hash); esp_partition_get_sha256(esp_ota_get_running_partition(), dev_firmware_hash);
#elif MCU_VARIANT == MCU_NRF52 #elif MCU_VARIANT == MCU_NRF52
// todo, add bootloader, partition table, or softdevice? // todo, add bootloader, partition table, or softdevice?
calculate_region_hash(APPLICATION_START, USER_DATA_START, dev_firmware_hash); calculate_region_hash(APPLICATION_START, APPLICATION_START+get_fw_length(), dev_firmware_hash);
#endif #endif
for (uint8_t i = 0; i < DEV_HASH_LEN; i++) { for (uint8_t i = 0; i < DEV_HASH_LEN; i++) {
if (dev_firmware_hash_target[i] != dev_firmware_hash[i]) { if (dev_firmware_hash_target[i] != dev_firmware_hash[i]) {

View File

@ -73,6 +73,7 @@
#define ROM_UNLOCK_BYTE 0xF8 #define ROM_UNLOCK_BYTE 0xF8
#define CMD_RESET 0x55 #define CMD_RESET 0x55
#define CMD_RESET_BYTE 0xF8 #define CMD_RESET_BYTE 0xF8
#define CMD_FW_LENGTH 0x65
#define CMD_INTERFACES 0x64 #define CMD_INTERFACES 0x64

View File

@ -211,6 +211,12 @@ upload-rak4631:
arduino-cli upload -p $(or $(port), /dev/ttyACM0) --fqbn rakwireless:nrf52:WisCoreRAK4631Board arduino-cli upload -p $(or $(port), /dev/ttyACM0) --fqbn rakwireless:nrf52:WisCoreRAK4631Board
unzip -o build/rakwireless.nrf52.WisCoreRAK4631Board/RNode_Firmware_CE.ino.zip -d build/rakwireless.nrf52.WisCoreRAK4631Board unzip -o build/rakwireless.nrf52.WisCoreRAK4631Board/RNode_Firmware_CE.ino.zip -d build/rakwireless.nrf52.WisCoreRAK4631Board
rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(sha256sum ./build/rakwireless.nrf52.WisCoreRAK4631Board/RNode_Firmware_CE.ino.bin | grep -o '^\S*') rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(sha256sum ./build/rakwireless.nrf52.WisCoreRAK4631Board/RNode_Firmware_CE.ino.bin | grep -o '^\S*')
@echo
@echo This target currently uses a custom version of rnodeconf to set the firmware length on the device.
@echo This will be removed once the feature has been included upstream, or another solution has been found.
@echo
@sleep 2
python3 rnodeconf.py /dev/ttyACM0 --set-firmware-length $$(ls -l ./build/rakwireless.nrf52.WisCoreRAK4631Board/RNode_Firmware_CE.ino.bin | awk '{print $$5}')
release: release-all release: release-all

View File

@ -1288,6 +1288,21 @@ void serialCallback(uint8_t sbyte) {
} }
#endif #endif
} else if (command == CMD_FW_LENGTH) {
if (sbyte == FESC) {
ESCAPE = true;
} else {
if (ESCAPE) {
if (sbyte == TFEND) sbyte = FEND;
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte;
}
if (frame_len == FW_LENGTH_LEN) {
set_fw_length(cmdbuf);
}
} }
} }
} }

View File

@ -31,9 +31,11 @@
#include <InternalFileSystem.h> #include <InternalFileSystem.h>
using namespace Adafruit_LittleFS_Namespace; using namespace Adafruit_LittleFS_Namespace;
#define EEPROM_FILE "eeprom" #define EEPROM_FILE "eeprom"
#define FW_LENGTH_FILE "fw_length"
bool file_exists = false; bool file_exists = false;
int written_bytes = 4; int written_bytes = 4;
File file(InternalFS); File eeprom_file(InternalFS);
File fw_length_file(InternalFS);
#endif #endif
#include <stddef.h> #include <stddef.h>
@ -1380,21 +1382,21 @@ void promisc_disable() {
bool eeprom_begin() { bool eeprom_begin() {
InternalFS.begin(); InternalFS.begin();
file.open(EEPROM_FILE, FILE_O_READ); eeprom_file.open(EEPROM_FILE, FILE_O_READ);
// if file doesn't exist // if file doesn't exist
if (!file) { if (!eeprom_file) {
if (file.open(EEPROM_FILE, FILE_O_WRITE)) { if (eeprom_file.open(EEPROM_FILE, FILE_O_WRITE)) {
// initialise the file with empty content // initialise the file with empty content
uint8_t empty_content[EEPROM_SIZE] = {0}; uint8_t empty_content[EEPROM_SIZE] = {0};
file.write(empty_content, EEPROM_SIZE); eeprom_file.write(empty_content, EEPROM_SIZE);
return true; return true;
} else { } else {
return false; return false;
} }
} else { } else {
file.close(); eeprom_file.close();
file.open(EEPROM_FILE, FILE_O_WRITE); eeprom_file.open(EEPROM_FILE, FILE_O_WRITE);
return true; return true;
} }
} }
@ -1402,8 +1404,8 @@ void promisc_disable() {
uint8_t eeprom_read(uint32_t mapped_addr) { uint8_t eeprom_read(uint32_t mapped_addr) {
uint8_t byte; uint8_t byte;
void* byte_ptr = &byte; void* byte_ptr = &byte;
file.seek(mapped_addr); eeprom_file.seek(mapped_addr);
file.read(byte_ptr, 1); eeprom_file.read(byte_ptr, 1);
return byte; return byte;
} }
#endif #endif
@ -1464,8 +1466,8 @@ void kiss_dump_eeprom() {
#if !HAS_EEPROM && MCU_VARIANT == MCU_NRF52 #if !HAS_EEPROM && MCU_VARIANT == MCU_NRF52
void eeprom_flush() { void eeprom_flush() {
// sync file contents to flash // sync file contents to flash
file.close(); eeprom_file.close();
file.open(EEPROM_FILE, FILE_O_WRITE); eeprom_file.open(EEPROM_FILE, FILE_O_WRITE);
written_bytes = 0; written_bytes = 0;
} }
#endif #endif
@ -1481,11 +1483,11 @@ void eeprom_update(int mapped_addr, uint8_t byte) {
// each time is really slow, but this is also suboptimal // each time is really slow, but this is also suboptimal
uint8_t read_byte; uint8_t read_byte;
void* read_byte_ptr = &read_byte; void* read_byte_ptr = &read_byte;
file.seek(mapped_addr); eeprom_file.seek(mapped_addr);
file.read(read_byte_ptr, 1); eeprom_file.read(read_byte_ptr, 1);
file.seek(mapped_addr); eeprom_file.seek(mapped_addr);
if (read_byte != byte) { if (read_byte != byte) {
file.write(byte); eeprom_file.write(byte);
} }
written_bytes++; written_bytes++;
@ -1495,8 +1497,8 @@ void eeprom_update(int mapped_addr, uint8_t byte) {
} }
if (written_bytes >= 4) { if (written_bytes >= 4) {
file.close(); eeprom_file.close();
file.open(EEPROM_FILE, FILE_O_WRITE); eeprom_file.open(EEPROM_FILE, FILE_O_WRITE);
written_bytes = 0; written_bytes = 0;
} }
#endif #endif

3651
rnodeconf.py Executable file

File diff suppressed because one or more lines are too long