Compare commits

..

No commits in common. "c63883bfa7a118aaba3630e30b9e13fb1351e0f1" and "cf00bedeaf07b48f773fefb8284cc069f4ce41d2" have entirely different histories.

10 changed files with 309 additions and 349 deletions

View File

@ -9,7 +9,6 @@
#include "../cmd.h" #include "../cmd.h"
#include "../common.h" #include "../common.h"
#include "../util.h" #include "../util.h"
#include "parse_file.h"
#define REG_EXTENDED 1 #define REG_EXTENDED 1
#define REG_ICASE (REG_EXTENDED << 1) #define REG_ICASE (REG_EXTENDED << 1)
@ -178,28 +177,46 @@ blisp_return_t blisp_flash_firmware() {
// TODO: Error handling // TODO: Error handling
goto exit1; goto exit1;
} }
parsed_firmware_file_t parsed_file;
memset(&parsed_file, 0, sizeof(parsed_file));
int parsed_result =
parse_firmware_file(binary_to_write->filename[0], &parsed_file);
// If we are injecting a bootloader section, make it, erase flash, and flash // Open the file to be flashed; to determine the size of the section of flash
// it. Then when we do firmware later on; it will be located afterwards // to erase
// the header filles up to a flash erase boundry so this stack should be safe int64_t firmware_file_size = 0;
// __should__ const uint32_t firmware_base_address_offset =
0x2000; // Firmware files start 0x2000 offset into flash to skip the boot
// header
int64_t firmware_file_start_address = 0;
FILE* firmware_file = fopen(binary_to_write->filename[0], "rb");
if (firmware_file == NULL) {
fprintf(stderr, "Failed to open firmware file \"%s\".\n",
binary_to_write->filename[0]);
goto exit1;
}
fseek(firmware_file, 0, SEEK_END);
firmware_file_size = ftell(firmware_file);
rewind(firmware_file);
if (parsed_file.needs_boot_struct) {
// Create a default boot header section in ram to be written out // Create a default boot header section in ram to be written out
struct bfl_boot_header boot_header; struct bfl_boot_header boot_header;
fill_up_boot_header(&boot_header); fill_up_boot_header(&boot_header);
printf("Erasing flash to flash boot header\n");
ret = blisp_device_flash_erase(&device, 0x0000, const uint32_t firmware_base_address = 0x2000;
sizeof(struct bfl_boot_header)); printf("Erasing flash, this might take a while...\n");
ret =
blisp_device_flash_erase(&device, firmware_base_address,
firmware_base_address + firmware_file_size + 1);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to erase flash.\n");
goto exit2;
}
ret =
blisp_device_flash_erase(&device, 0x0000, sizeof(struct bfl_boot_header));
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
fprintf(stderr, "Failed to erase flash.\n"); fprintf(stderr, "Failed to erase flash.\n");
goto exit2; goto exit2;
} }
// Now burn the header
printf("Flashing boot header...\n"); printf("Flashing boot header...\n");
ret = blisp_device_flash_write(&device, 0x0000, (uint8_t*)&boot_header, ret = blisp_device_flash_write(&device, 0x0000, (uint8_t*)&boot_header,
@ -208,33 +225,13 @@ blisp_return_t blisp_flash_firmware() {
fprintf(stderr, "Failed to write boot header.\n"); fprintf(stderr, "Failed to write boot header.\n");
goto exit2; goto exit2;
} }
// Move the firmware to-be-flashed beyond the boot header area printf("Flashing the firmware...\n");
parsed_file.payload_address += 0x2000;
}
// Now that optional boot header is done, we clear out the flash for the new
// firmware; and flash it in.
printf("Erasing flash for firmware, this might take a while...\n");
ret = blisp_device_flash_erase(
&device, parsed_file.payload_address,
parsed_file.payload_address + parsed_file.payload_length + 1);
if (ret != BLISP_OK) {
fprintf(stderr,
"Failed to erase flash. Tried to erase from 0x%08X to 0x%08X\n",
parsed_file.payload_address,
parsed_file.payload_address + parsed_file.payload_length + 1);
goto exit2;
}
printf("Flashing the firmware @ 0x%08X...\n", parsed_file.payload_address);
struct blisp_easy_transport data_transport = struct blisp_easy_transport data_transport =
blisp_easy_transport_new_from_memory(parsed_file.payload, blisp_easy_transport_new_from_file(firmware_file);
parsed_file.payload_length);
ret = blisp_easy_flash_write(
&device, &data_transport, parsed_file.payload_address,
parsed_file.payload_length, blisp_common_progress_callback);
ret = blisp_easy_flash_write(&device, &data_transport, firmware_base_address,
firmware_file_size,
blisp_common_progress_callback);
if (ret < BLISP_OK) { if (ret < BLISP_OK) {
fprintf(stderr, "Failed to write app to flash.\n"); fprintf(stderr, "Failed to write app to flash.\n");
goto exit2; goto exit2;
@ -257,8 +254,8 @@ blisp_return_t blisp_flash_firmware() {
printf("Flash complete!\n"); printf("Flash complete!\n");
exit2: exit2:
if (parsed_file.payload != NULL) if (firmware_file != NULL)
free(parsed_file.payload); fclose(firmware_file);
exit1: exit1:
blisp_device_close(&device); blisp_device_close(&device);
} }

View File

@ -13,7 +13,6 @@ add_library(file_parsers
"${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_file.c" "${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_crc.c" "${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_crc.c"
"${CMAKE_CURRENT_SOURCE_DIR}/parse_file.c" "${CMAKE_CURRENT_SOURCE_DIR}/parse_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/get_file_contents.c"
) )
target_include_directories(file_parsers PUBLIC target_include_directories(file_parsers PUBLIC

View File

@ -1,15 +0,0 @@
#include <stdio.h>
#include "parse_file.h"
int bin_file_parse(const char* file_path_on_disk,
uint8_t** payload,
size_t* payload_length,
size_t* payload_address) {
// Bin files a dumb so we cant do any fancy logic
*payload_address = 0; // We cant know otherwise
ssize_t len = get_file_contents(file_path_on_disk, payload);
if (len > 0) {
*payload_length = len;
}
return len;
}

View File

@ -5,6 +5,7 @@
#ifndef BLISP_BIN_FILE_H #ifndef BLISP_BIN_FILE_H
#define BLISP_BIN_FILE_H #define BLISP_BIN_FILE_H
#include <malloc.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>

View File

@ -2,7 +2,6 @@
// Created by ralim on 25/09/22. // Created by ralim on 25/09/22.
// //
#include "dfu_file.h" #include "dfu_file.h"
#include <stdlib.h>
#define DFU_SUFFIX_LENGTH 16 #define DFU_SUFFIX_LENGTH 16
#define LMDFU_PREFIX_LENGTH 8 #define LMDFU_PREFIX_LENGTH 8
@ -42,10 +41,8 @@ enum prefix_type {
struct dfu_file parse_dfu_suffix(const uint8_t* file_contents, struct dfu_file parse_dfu_suffix(const uint8_t* file_contents,
size_t file_contents_length); size_t file_contents_length);
ssize_t parse_target(const uint8_t* data, ssize_t parse_target(const uint8_t* data, uint8_t* out_ealt,
uint8_t* out_ealt, uint8_t** out_data, size_t* out_data_size,
uint8_t** out_data,
size_t* out_data_size,
size_t* out_data_address); size_t* out_data_address);
ssize_t get_file_contents(const char* file_path_on_disk, ssize_t get_file_contents(const char* file_path_on_disk,
uint8_t** file_contents); uint8_t** file_contents);
@ -67,12 +64,12 @@ ssize_t get_file_contents(const char* file_path_on_disk,
* free(payload); * free(payload);
*/ */
int dfu_file_parse(const char* file_path_on_disk, int
uint8_t** payload, dfu_file_parse(const char* file_path_on_disk, uint8_t** payload,
size_t* payload_length, size_t* payload_length, size_t* payload_address) {
size_t* payload_address) {
uint8_t* dfu_file_contents = NULL; uint8_t* dfu_file_contents = NULL;
ssize_t file_size = get_file_contents(file_path_on_disk, &dfu_file_contents); ssize_t file_size
= get_file_contents(file_path_on_disk, &dfu_file_contents);
if (file_size <= 0 || dfu_file_contents == NULL) { if (file_size <= 0 || dfu_file_contents == NULL) {
return -1; return -1;
} }
@ -91,8 +88,8 @@ int dfu_file_parse(const char* file_path_on_disk,
uint8_t* blob = NULL; uint8_t* blob = NULL;
size_t blob_size = 0; size_t blob_size = 0;
size_t blob_address = 0; size_t blob_address = 0;
ssize_t res = parse_target(dfu_info.firmware + data_consumed, &ealt, &blob, ssize_t res = parse_target(dfu_info.firmware + data_consumed, &ealt,
&blob_size, &blob_address); &blob, &blob_size, &blob_address);
if (res < 0) { if (res < 0) {
break; break;
} }
@ -112,13 +109,11 @@ int dfu_file_parse(const char* file_path_on_disk,
} }
// Read next target, output data+size+alt. Returns bytes consumed // Read next target, output data+size+alt. Returns bytes consumed
ssize_t parse_target(const uint8_t* data, ssize_t
uint8_t* out_ealt, parse_target(const uint8_t* data, uint8_t* out_ealt, uint8_t** out_data,
uint8_t** out_data, size_t* out_data_size, size_t* out_data_address) {
size_t* out_data_size, if (data == NULL || out_ealt == NULL || out_data == NULL
size_t* out_data_address) { || out_data_size == NULL) {
if (data == NULL || out_ealt == NULL || out_data == NULL ||
out_data_size == NULL) {
return -99; return -99;
} }
if (data[0] != 'T' || data[1] != 'a') { if (data[0] != 'T' || data[1] != 'a') {
@ -126,7 +121,7 @@ ssize_t parse_target(const uint8_t* data,
} }
*out_ealt = data[6]; *out_ealt = data[6];
uint8_t* tdata = (uint8_t*)data + 6 + 1 + 4 + 255; uint8_t* tdata = data + 6 + 1 + 4 + 255;
uint32_t len_tdata = *((uint32_t*)tdata); uint32_t len_tdata = *((uint32_t*)tdata);
tdata += 4; tdata += 4;
uint32_t num_images = *((uint32_t*)tdata); uint32_t num_images = *((uint32_t*)tdata);
@ -147,13 +142,14 @@ ssize_t parse_target(const uint8_t* data,
return blob_length; return blob_length;
} }
static int probe_prefix(struct dfu_file* file) { static int
probe_prefix(struct dfu_file* file) {
const uint8_t* prefix = file->firmware; const uint8_t* prefix = file->firmware;
file->size.prefix = 0; file->size.prefix = 0;
if (file->size.total < LMDFU_PREFIX_LENGTH) if (file->size.total < LMDFU_PREFIX_LENGTH)
return 1; return 1;
if (prefix[0] == 'D' && prefix[1] == 'f' && prefix[2] == 'u' && if (prefix[0] == 'D' && prefix[1] == 'f' && prefix[2] == 'u'
prefix[3] == 'S' && prefix[4] == 'e') { && prefix[3] == 'S' && prefix[4] == 'e') {
// DfuSe header // DfuSe header
// https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/dfuse-pack.py#l110 // https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/dfuse-pack.py#l110
@ -163,10 +159,11 @@ static int probe_prefix(struct dfu_file* file) {
printf("Number DFU Targets: %d\n", numTargets); printf("Number DFU Targets: %d\n", numTargets);
} }
if ((prefix[0] == 0x01) && (prefix[1] == 0x00)) { if ((prefix[0] == 0x01) && (prefix[1] == 0x00)) {
uint32_t payload_length = uint32_t payload_length = (prefix[7] << 24) | (prefix[6] << 16)
(prefix[7] << 24) | (prefix[6] << 16) | (prefix[5] << 8) | prefix[4]; | (prefix[5] << 8) | prefix[4];
uint32_t expected_payload_length = uint32_t expected_payload_length = (uint32_t)file->size.total
(uint32_t)file->size.total - LMDFU_PREFIX_LENGTH - file->size.suffix; - LMDFU_PREFIX_LENGTH
- file->size.suffix;
if (payload_length != expected_payload_length) if (payload_length != expected_payload_length)
return 1; return 1;
file->prefix_type = LMDFU_PREFIX; file->prefix_type = LMDFU_PREFIX;
@ -182,7 +179,8 @@ static int probe_prefix(struct dfu_file* file) {
return 0; return 0;
} }
struct dfu_file parse_dfu_suffix(const uint8_t* file_contents, struct dfu_file
parse_dfu_suffix(const uint8_t* file_contents,
const size_t file_contents_length) { const size_t file_contents_length) {
// This is nearly 1:1 based on // This is nearly 1:1 based on
// https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/src/dfu_file.c#l368 // https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/src/dfu_file.c#l368
@ -205,7 +203,8 @@ struct dfu_file parse_dfu_suffix(const uint8_t* file_contents,
dfu_suffix = file_contents + file_contents_length - DFU_SUFFIX_LENGTH; dfu_suffix = file_contents + file_contents_length - DFU_SUFFIX_LENGTH;
if (dfu_suffix[10] != 'D' || dfu_suffix[9] != 'F' || dfu_suffix[8] != 'U') { if (dfu_suffix[10] != 'D' || dfu_suffix[9] != 'F'
|| dfu_suffix[8] != 'U') {
reason = "Invalid DFU suffix signature"; reason = "Invalid DFU suffix signature";
missing_suffix = 1; missing_suffix = 1;
goto checked; goto checked;
@ -215,8 +214,8 @@ struct dfu_file parse_dfu_suffix(const uint8_t* file_contents,
crc = crc32_byte(crc, file_contents[i]); crc = crc32_byte(crc, file_contents[i]);
} }
output.dwCRC = (dfu_suffix[15] << 24) + (dfu_suffix[14] << 16) + output.dwCRC = (dfu_suffix[15] << 24) + (dfu_suffix[14] << 16)
(dfu_suffix[13] << 8) + dfu_suffix[12]; + (dfu_suffix[13] << 8) + dfu_suffix[12];
if (output.dwCRC != crc) { if (output.dwCRC != crc) {
reason = "DFU suffix CRC does not match"; reason = "DFU suffix CRC does not match";
@ -232,7 +231,8 @@ struct dfu_file parse_dfu_suffix(const uint8_t* file_contents,
output.size.suffix = dfu_suffix[11]; output.size.suffix = dfu_suffix[11];
if (output.size.suffix < DFU_SUFFIX_LENGTH) { if (output.size.suffix < DFU_SUFFIX_LENGTH) {
fprintf(stderr, "Unsupported DFU suffix length %d", output.size.suffix); fprintf(stderr, "Unsupported DFU suffix length %d",
output.size.suffix);
} }
if (output.size.suffix > file_contents_length) { if (output.size.suffix > file_contents_length) {
@ -244,32 +244,79 @@ struct dfu_file parse_dfu_suffix(const uint8_t* file_contents,
output.bcdDevice = (dfu_suffix[1] << 8) + dfu_suffix[0]; output.bcdDevice = (dfu_suffix[1] << 8) + dfu_suffix[0];
checked: checked:
int res = probe_prefix(&output); const int res = probe_prefix(&output);
if (output.size.prefix) { if (output.size.prefix) {
const uint8_t* data = file_contents; const uint8_t* data = file_contents;
if (output.prefix_type == DFUSE_PREFIX) { if (output.prefix_type == DFUSE_PREFIX) {
} else if (output.prefix_type == LMDFU_PREFIX) { } else if (output.prefix_type == LMDFU_PREFIX) {
printf( printf("Possible TI Stellaris DFU prefix with "
"Possible TI Stellaris DFU prefix with "
"the following properties\n" "the following properties\n"
"Address: 0x%08x\n" "Address: 0x%08x\n"
"Payload length: %d\n", "Payload length: %d\n",
output.lmdfu_address, output.lmdfu_address,
data[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24)); data[4] | (data[5] << 8) | (data[6] << 16)
| (data[7] << 24));
} else if (output.prefix_type == LPCDFU_UNENCRYPTED_PREFIX) { } else if (output.prefix_type == LPCDFU_UNENCRYPTED_PREFIX) {
printf( printf("Possible unencrypted NXP LPC DFU prefix with "
"Possible unencrypted NXP LPC DFU prefix with "
"the following properties\n" "the following properties\n"
"Payload length: %d kiByte\n", "Payload length: %d kiByte\n",
data[2] >> 1 | (data[3] << 7)); data[2] >> 1 | (data[3] << 7));
} else { } else {
fprintf(stderr, "Unknown DFU prefix type"); fprintf(stderr, "Unknown DFU prefix type");
} }
output.firmware = output.firmware
output.firmware + output.size.prefix; // shift past prefix = output.firmware + output.size.prefix; // shift past prefix
} }
output.size.firmware = output.size.firmware
output.size.total - (output.size.suffix + output.size.prefix); = output.size.total - (output.size.suffix + output.size.prefix);
return output; return output;
} }
// Returns file size _or_ negative on error
ssize_t
get_file_contents(const char* file_path_on_disk, uint8_t** file_contents) {
size_t read_count;
size_t file_size = 0;
size_t read_total = 0;
FILE* f;
if (file_contents == NULL) {
return -99;
}
f = fopen(file_path_on_disk, "rb");
if (f <= 0) {
fprintf(stderr, "Could not open file %s for reading",
file_path_on_disk);
return -1;
}
fseek(f, 0, SEEK_END);
file_size = ftell(f);
fseek(f, 0, SEEK_SET);
*file_contents = calloc(file_size, sizeof(uint8_t));
while (read_total < file_size) {
size_t to_read = file_size - read_total;
/* read() limit on Linux, slightly below MAX_INT on Windows */
if (to_read > 0x7ffff000)
to_read = 0x7ffff000;
read_count = fread((*file_contents) + read_total, 1, to_read, f);
if (read_count == 0)
break;
// If error and not end of file, break
if (read_count == -1 && !feof(f))
break;
read_total += read_count;
}
if (read_total != file_size) {
fprintf(stderr, "Could only read %lld of %lld bytes from %s",
(long long)read_total, (long long)file_size,
file_path_on_disk);
return -1;
}
fclose(f);
return (ssize_t)file_size;
}

View File

@ -5,6 +5,7 @@
#ifndef BLISP_DFU_FILE_H #ifndef BLISP_DFU_FILE_H
#define BLISP_DFU_FILE_H #define BLISP_DFU_FILE_H
#include <malloc.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>

View File

@ -1,48 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "parse_file.h"
// Returns file size _or_ negative on error
ssize_t get_file_contents(const char* file_path_on_disk,
uint8_t** file_contents) {
size_t read_count;
size_t file_size = 0;
size_t read_total = 0;
FILE* f;
if (file_contents == NULL) {
return -99;
}
f = fopen(file_path_on_disk, "rb");
if (f <= 0) {
fprintf(stderr, "Could not open file %s for reading\n", file_path_on_disk);
return -1;
}
fseek(f, 0, SEEK_END);
file_size = ftell(f);
fseek(f, 0, SEEK_SET);
*file_contents = calloc(file_size, sizeof(uint8_t));
while (read_total < file_size) {
size_t to_read = file_size - read_total;
/* read() limit on Linux, slightly below MAX_INT on Windows */
if (to_read > 0x7ffff000)
to_read = 0x7ffff000;
read_count = fread((*file_contents) + read_total, 1, to_read, f);
if (read_count == 0)
break;
// If error and not end of file, break
if (read_count == -1 && !feof(f))
break;
read_total += read_count;
}
if (read_total != file_size) {
fprintf(stderr, "Could only read %lld of %lld bytes from %s",
(long long)read_total, (long long)file_size, file_path_on_disk);
return -1;
}
fclose(f);
return (ssize_t)file_size;
}

View File

@ -1,6 +1,5 @@
#include "parse_file.h" #include "parse_file.h"
#include <string.h> #include <string.h>
#include "bin_file.h"
#include "dfu_file.h" #include "dfu_file.h"
const char* get_filename_ext(const char* filename) { const char* get_filename_ext(const char* filename) {
@ -9,35 +8,22 @@ const char* get_filename_ext(const char* filename) {
return ""; return "";
return dot + 1; return dot + 1;
} }
#define FLASH_MAP_ADDR 0x23000000
int parse_firmware_file(const char* file_path_on_disk, int parse_firmware_file(const char* file_path_on_disk,
parsed_firmware_file_t* parsed_results) { parsed_firmware_file_t* parsed_results) {
// Switchcase on the extension of the file // Switchcase on the extension of the file
const char* ext = get_filename_ext(file_path_on_disk); const char* ext = get_filename_ext(file_path_on_disk);
int res = PARSED_ERROR_INVALID_FILETYPE;
if (strncmp(ext, "dfu", 3) == 0 || strncmp(ext, "DFU", 3) == 0) { if (strncmp(ext, "dfu", 3) == 0 || strncmp(ext, "DFU", 3) == 0) {
printf("Input file identified as a .dfu file\n"); printf("Input file identified as a .dfu file\r\n");
// Handle as a .dfu file // Handle as a .dfu file
res = dfu_file_parse(file_path_on_disk, &parsed_results->payload, return dfu_file_parse("test.dfu", &parsed_results->payload,
&parsed_results->payload_length, &parsed_results->payload_length,
&parsed_results->payload_address); &parsed_results->payload_address);
} else if (strncmp(ext, "bin", 3) == 0 || strncmp(ext, "BIN", 3) == 0) { } else if (strncmp(ext, "bin", 3) == 0 || strncmp(ext, "BIN", 3) == 0) {
printf("Input file identified as a .bin file\n"); printf("Input file identified as a .bin file\r\n");
// Raw binary file // Raw binary file
res = bin_file_parse(file_path_on_disk, &parsed_results->payload,
&parsed_results->payload_length,
&parsed_results->payload_address);
} }
// If we wanted to support hex files, here would be where // TODO: Hex files?
return PARSED_ERROR_INVALID_FILETYPE;
// Normalise address, some builds will base the firmware at flash start but
// for the flasher we use 0 base (i.e. offsets into flash)
if (parsed_results->payload_address >= FLASH_MAP_ADDR) {
parsed_results->payload_address -= FLASH_MAP_ADDR;
}
// If the firmware starts at "0" we need to pre-pend a boot sector later on
parsed_results->needs_boot_struct = parsed_results->payload_address == 0;
return res;
} }

View File

@ -1,10 +1,7 @@
#pragma once #pragma once
#include <stdio.h>
#include <stdlib.h>
#include "parsed_firmware_file.h" #include "parsed_firmware_file.h"
#define PARSED_ERROR_INVALID_FILETYPE -0x1000 #define PARSED_ERROR_INVALID_FILETYPE -0x1000
#define PARSED_ERROR_CANT_OPEN_FILE -0x1001
#define PARSED_ERROR_TOO_BIG -0x1001 /* Input expands to be too big */ #define PARSED_ERROR_TOO_BIG -0x1001 /* Input expands to be too big */
#define PARSED_ERROR_BAD_DFU -0x1002 /* DFU file provided but not valid */ #define PARSED_ERROR_BAD_DFU -0x1002 /* DFU file provided but not valid */
@ -15,7 +12,3 @@
int parse_firmware_file(const char* file_path_on_disk, int parse_firmware_file(const char* file_path_on_disk,
parsed_firmware_file_t* parsed_results); parsed_firmware_file_t* parsed_results);
// Internal util
ssize_t get_file_contents(const char* file_path_on_disk,
uint8_t** file_contents);

View File

@ -1,5 +1,4 @@
#pragma once #pragma once
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>