From 3c62fbd6fd752b50a4ec0c70e500cbff4c415a6e Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Mon, 2 Dec 2024 15:46:36 +0200 Subject: [PATCH 1/7] ensure file size properly fits in the HID report always --- sonixflasher.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sonixflasher.c b/sonixflasher.c index 4819d51..985e5b3 100644 --- a/sonixflasher.c +++ b/sonixflasher.c @@ -799,6 +799,7 @@ long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { // Recalculate file size file_size = get_file_size(fp); if (file_size == -1L) { + fprintf(stderr, "ERROR: Truncated file size calculation failed.\n"); fclose(fp); return -1; } @@ -813,7 +814,27 @@ long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { padded_file_size++; } printf("File size after padding: %ld bytes\n", padded_file_size); - file_size = padded_file_size; + + fclose(fp); + if (truncate(file_name, padded_file_size) != 0) { + fprintf(stderr, "ERROR: Could not truncate file.\n"); + return -1; + } + + // Reopen the file + fp = fopen(file_name, "rb"); + if (fp == NULL) { + fprintf(stderr, "ERROR: Could not open file after truncation.\n"); + return -1; + } + + // Recalculate file size + file_size = get_file_size(fp); + if (file_size == -1L) { + fprintf(stderr, "ERROR: Truncated file size calculation failed.\n"); + fclose(fp); + return -1; + } } fclose(fp); From a0cf21b8eda04e737ccca98cecf7936b08c998b6 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Mon, 2 Dec 2024 15:56:31 +0200 Subject: [PATCH 2/7] use a common truncate wrapper --- sonixflasher.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/sonixflasher.c b/sonixflasher.c index 985e5b3..8ccfc10 100644 --- a/sonixflasher.c +++ b/sonixflasher.c @@ -757,6 +757,22 @@ long get_file_size(FILE *fp) { return file_size; } +bool truncate_and_reopen(const char *file_name, FILE **fp, long new_size) { + fclose(*fp); // Close the file before truncating + if (truncate(file_name, new_size) != 0) { + fprintf(stderr, "ERROR: Could not truncate file to size %ld.\n", new_size); + return false; + } + + *fp = fopen(file_name, "rb"); // Reopen the file in read mode + if (*fp == NULL) { + fprintf(stderr, "ERROR: Could not reopen file after truncation.\n"); + return false; + } + + return true; +} + long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { FILE *fp = fopen(file_name, "rb"); if (fp == NULL) { @@ -783,16 +799,7 @@ long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { printf("Warning: jumploader binary doesn't have a size of: 0x%04x bytes.\n", QMK_OFFSET_DEFAULT); printf("Truncating jumploader binary to: 0x%04x.\n", QMK_OFFSET_DEFAULT); - fclose(fp); - if (truncate(file_name, QMK_OFFSET_DEFAULT) != 0) { - fprintf(stderr, "ERROR: Could not truncate file.\n"); - return -1; - } - - // Reopen the file - fp = fopen(file_name, "rb"); - if (fp == NULL) { - fprintf(stderr, "ERROR: Could not open file after truncation.\n"); + if (!truncate_and_reopen(file_name, &fp, QMK_OFFSET_DEFAULT)) { return -1; } @@ -815,16 +822,7 @@ long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { } printf("File size after padding: %ld bytes\n", padded_file_size); - fclose(fp); - if (truncate(file_name, padded_file_size) != 0) { - fprintf(stderr, "ERROR: Could not truncate file.\n"); - return -1; - } - - // Reopen the file - fp = fopen(file_name, "rb"); - if (fp == NULL) { - fprintf(stderr, "ERROR: Could not open file after truncation.\n"); + if (!truncate_and_reopen(file_name, &fp, padded_file_size)) { return -1; } From ad639ac10d482058d1dc2982e89a8ea43cfa3e49 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Mon, 2 Dec 2024 18:20:25 +0200 Subject: [PATCH 3/7] dynamically get flash verification flag verification is actually done on last chunk --- sonixflasher.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sonixflasher.c b/sonixflasher.c index 8ccfc10..518bfee 100644 --- a/sonixflasher.c +++ b/sonixflasher.c @@ -51,7 +51,7 @@ #define CMD_VERIFY(x) ((CMD_BASE << 8) | (x)) #define CMD_ACK 0xFAFAFAFA -#define VALID_FW 0xAAAA5555 +#define LAST_CHUNK_OFFSET (REPORT_SIZE - sizeof(uint32_t)) #define SN240 1 #define SN260 2 @@ -657,12 +657,21 @@ bool flash(hid_device *dev, long offset, const char *file_name, long fw_size, bo size_t bytes_read = 0; uint16_t checksum = 0; + uint32_t last_chunk = 0; clear_buffer(buf, REPORT_SIZE); while ((bytes_read = fread(buf, 1, REPORT_SIZE, firmware)) > 0) { if (bytes_read < REPORT_SIZE) { fprintf(stderr, "WARNING: Read %zu bytes, expected %d bytes.\n", bytes_read, REPORT_SIZE); } checksum += checksum16(buf, bytes_read); + + // Capture the last 4 bytes of this buffer for last_chunk + if (bytes_read >= sizeof(uint32_t)) { + memcpy(&last_chunk, buf + (bytes_read - sizeof(uint32_t)), sizeof(uint32_t)); + } else { + memcpy(&last_chunk, buf, bytes_read); + } + if (!hid_set_feature(dev, buf, bytes_read)) return false; clear_buffer(buf, REPORT_SIZE); @@ -675,7 +684,7 @@ bool flash(hid_device *dev, long offset, const char *file_name, long fw_size, bo printf("\n"); printf("Verifying flash completion...\n"); if (!hid_get_feature(dev, buf, REPORT_SIZE, CMD_ENABLE_PROGRAM)) return false; - if (read_response_32(buf, (sizeof(buf) - sizeof(VALID_FW)), VALID_FW, &resp)) { + if (read_response_32(buf, LAST_CHUNK_OFFSET, last_chunk, &resp)) { printf("Flash completion verified. \n"); uint16_t resp_16 = (uint16_t)resp; if (read_response_16(buf, 8, checksum, &resp_16)) { @@ -687,7 +696,7 @@ bool flash(hid_device *dev, long offset, const char *file_name, long fw_size, bo } return false; } else { - fprintf(stderr, "ERROR: Failed to verify flash completion: response is 0x%08x, expected 0x%08x.\n", resp, VALID_FW); + fprintf(stderr, "ERROR: Failed to verify flash completion: response is 0x%08x, expected 0x%08x.\n", resp, last_chunk); return false; } return false; From b0b66e6acd7a95af26897bf1089a29c715d25606 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Mon, 2 Dec 2024 19:05:17 +0200 Subject: [PATCH 4/7] generate checksum before padding --- sonixflasher.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/sonixflasher.c b/sonixflasher.c index 518bfee..763469e 100644 --- a/sonixflasher.c +++ b/sonixflasher.c @@ -87,6 +87,7 @@ #define PROJECT_VER "2.0.7" uint16_t BLANK_CHECKSUM = 0x0000; +uint16_t checksum = 0; uint16_t CS0 = CS0_0; uint16_t USER_ROM_SIZE = USER_ROM_SIZE_SN32F260; uint16_t USER_ROM_PAGES = USER_ROM_PAGES_SN32F260; @@ -656,14 +657,12 @@ bool flash(hid_device *dev, long offset, const char *file_name, long fw_size, bo printf("Flashing device, please wait...\n"); size_t bytes_read = 0; - uint16_t checksum = 0; uint32_t last_chunk = 0; clear_buffer(buf, REPORT_SIZE); while ((bytes_read = fread(buf, 1, REPORT_SIZE, firmware)) > 0) { if (bytes_read < REPORT_SIZE) { fprintf(stderr, "WARNING: Read %zu bytes, expected %d bytes.\n", bytes_read, REPORT_SIZE); } - checksum += checksum16(buf, bytes_read); // Capture the last 4 bytes of this buffer for last_chunk if (bytes_read >= sizeof(uint32_t)) { @@ -676,7 +675,6 @@ bool flash(hid_device *dev, long offset, const char *file_name, long fw_size, bo clear_buffer(buf, REPORT_SIZE); } - printf("Flashed File Checksum: 0x%04x\n", checksum); clear_buffer(buf, REPORT_SIZE); fclose(firmware); @@ -782,6 +780,32 @@ bool truncate_and_reopen(const char *file_name, FILE **fp, long new_size) { return true; } +uint16_t calculate_checksum(FILE *fp, long file_size) { + checksum = 0; + uint16_t checksum_calc = 0; + unsigned char *file_data = malloc(file_size); + + if (file_data == NULL) { + fprintf(stderr, "ERROR: Could not allocate memory for file data.\n"); + return -1; + } + + fseek(fp, 0, SEEK_SET); + + // Read the entire file into the allocated buffer + if (fread(file_data, 1, file_size, fp) != file_size) { + fprintf(stderr, "ERROR: Could not read the entire file.\n"); + free(file_data); + return -1; + } + + // Calculate the checksum + checksum_calc = checksum16(file_data, file_size); + + free(file_data); + return checksum_calc; +} + long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { FILE *fp = fopen(file_name, "rb"); if (fp == NULL) { @@ -803,6 +827,15 @@ long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { printf("\n"); printf("File size: %ld bytes\n", file_size); + uint16_t checksum_calc = calculate_checksum(fp, file_size); + if (checksum_calc == -1L) { + fclose(fp); + return -1; + } + checksum = checksum_calc; + printf("\n"); + printf("File Checksum: 0x%04x\n", checksum); + // If jumploader is not 0x200 in length, add padded zeroes to file if (flash_jumploader && file_size < QMK_OFFSET_DEFAULT) { printf("Warning: jumploader binary doesn't have a size of: 0x%04x bytes.\n", QMK_OFFSET_DEFAULT); From bc96cfa909597f2ba8a7aea94ef451713ba837de Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Sun, 5 Jan 2025 11:31:45 +0200 Subject: [PATCH 5/7] Revert "generate checksum before padding" as expected, this is not necessary This reverts commit b0b66e6acd7a95af26897bf1089a29c715d25606. --- sonixflasher.c | 39 +++------------------------------------ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/sonixflasher.c b/sonixflasher.c index 763469e..518bfee 100644 --- a/sonixflasher.c +++ b/sonixflasher.c @@ -87,7 +87,6 @@ #define PROJECT_VER "2.0.7" uint16_t BLANK_CHECKSUM = 0x0000; -uint16_t checksum = 0; uint16_t CS0 = CS0_0; uint16_t USER_ROM_SIZE = USER_ROM_SIZE_SN32F260; uint16_t USER_ROM_PAGES = USER_ROM_PAGES_SN32F260; @@ -657,12 +656,14 @@ bool flash(hid_device *dev, long offset, const char *file_name, long fw_size, bo printf("Flashing device, please wait...\n"); size_t bytes_read = 0; + uint16_t checksum = 0; uint32_t last_chunk = 0; clear_buffer(buf, REPORT_SIZE); while ((bytes_read = fread(buf, 1, REPORT_SIZE, firmware)) > 0) { if (bytes_read < REPORT_SIZE) { fprintf(stderr, "WARNING: Read %zu bytes, expected %d bytes.\n", bytes_read, REPORT_SIZE); } + checksum += checksum16(buf, bytes_read); // Capture the last 4 bytes of this buffer for last_chunk if (bytes_read >= sizeof(uint32_t)) { @@ -675,6 +676,7 @@ bool flash(hid_device *dev, long offset, const char *file_name, long fw_size, bo clear_buffer(buf, REPORT_SIZE); } + printf("Flashed File Checksum: 0x%04x\n", checksum); clear_buffer(buf, REPORT_SIZE); fclose(firmware); @@ -780,32 +782,6 @@ bool truncate_and_reopen(const char *file_name, FILE **fp, long new_size) { return true; } -uint16_t calculate_checksum(FILE *fp, long file_size) { - checksum = 0; - uint16_t checksum_calc = 0; - unsigned char *file_data = malloc(file_size); - - if (file_data == NULL) { - fprintf(stderr, "ERROR: Could not allocate memory for file data.\n"); - return -1; - } - - fseek(fp, 0, SEEK_SET); - - // Read the entire file into the allocated buffer - if (fread(file_data, 1, file_size, fp) != file_size) { - fprintf(stderr, "ERROR: Could not read the entire file.\n"); - free(file_data); - return -1; - } - - // Calculate the checksum - checksum_calc = checksum16(file_data, file_size); - - free(file_data); - return checksum_calc; -} - long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { FILE *fp = fopen(file_name, "rb"); if (fp == NULL) { @@ -827,15 +803,6 @@ long prepare_file_to_flash(const char *file_name, bool flash_jumploader) { printf("\n"); printf("File size: %ld bytes\n", file_size); - uint16_t checksum_calc = calculate_checksum(fp, file_size); - if (checksum_calc == -1L) { - fclose(fp); - return -1; - } - checksum = checksum_calc; - printf("\n"); - printf("File Checksum: 0x%04x\n", checksum); - // If jumploader is not 0x200 in length, add padded zeroes to file if (flash_jumploader && file_size < QMK_OFFSET_DEFAULT) { printf("Warning: jumploader binary doesn't have a size of: 0x%04x bytes.\n", QMK_OFFSET_DEFAULT); From a60b5ca6db08ee8d215b32013243c50e691afe13 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Sun, 5 Jan 2025 11:41:33 +0200 Subject: [PATCH 6/7] disable checksum verification on partial flashing --- sonixflasher.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonixflasher.c b/sonixflasher.c index 518bfee..e8b5642 100644 --- a/sonixflasher.c +++ b/sonixflasher.c @@ -691,6 +691,10 @@ bool flash(hid_device *dev, long offset, const char *file_name, long fw_size, bo printf("Flash Verification Checksum: OK!\n"); return true; } else { + if (offset != 0) { + printf("Warning: offset 0x%04lx requested. Flash Verification Checksum disabled.\n", offset); + return true; + } fprintf(stderr, "ERROR:Flash Verification Checksum: FAILED! response is 0x%04x, expected 0x%04x.\n", resp_16, checksum); return false; } From 8c5d5909ad5e4a62404024f7aa5805e04dc2d849 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Sun, 5 Jan 2025 11:43:17 +0200 Subject: [PATCH 7/7] abstract MIN_FIRMWARE size --- sonixflasher.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonixflasher.c b/sonixflasher.c index e8b5642..c5a7cda 100644 --- a/sonixflasher.c +++ b/sonixflasher.c @@ -37,6 +37,7 @@ #define USER_ROM_PAGES_SN32F290 256 #define QMK_OFFSET_DEFAULT 0x200 +#define MIN_FIRMWARE 0x100 #define CMD_BASE 0x55AA #define CMD_GET_FW_VERSION 0x1 @@ -730,7 +731,7 @@ bool sanity_check_firmware(long fw_size, long offset) { fprintf(stderr, "ERROR: Firmware is too large too flash: 0x%08lx max allowed is 0x%08lx.\n", fw_size, MAX_FIRMWARE - offset); return false; } - if (fw_size < 0x100) { + if (fw_size < MIN_FIRMWARE) { fprintf(stderr, "ERROR: Firmware is too small."); return false; }