mirror of
https://github.com/pine64/blisp.git
synced 2025-03-13 10:28:57 +00:00
Pull out get file util
Update CMakeLists.txt
This commit is contained in:
parent
9893a49376
commit
d052d2ebe4
@ -13,6 +13,7 @@ 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
|
||||||
|
@ -41,8 +41,10 @@ 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, uint8_t* out_ealt,
|
ssize_t parse_target(const uint8_t* data,
|
||||||
uint8_t** out_data, size_t* out_data_size,
|
uint8_t* out_ealt,
|
||||||
|
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);
|
||||||
@ -64,12 +66,12 @@ ssize_t get_file_contents(const char* file_path_on_disk,
|
|||||||
* free(payload);
|
* free(payload);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int dfu_file_parse(const char* file_path_on_disk,
|
||||||
dfu_file_parse(const char* file_path_on_disk, uint8_t** payload,
|
uint8_t** payload,
|
||||||
size_t* payload_length, size_t* payload_address) {
|
size_t* payload_length,
|
||||||
|
size_t* payload_address) {
|
||||||
uint8_t* dfu_file_contents = NULL;
|
uint8_t* dfu_file_contents = NULL;
|
||||||
ssize_t file_size
|
ssize_t file_size = get_file_contents(file_path_on_disk, &dfu_file_contents);
|
||||||
= 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;
|
||||||
}
|
}
|
||||||
@ -88,8 +90,8 @@ dfu_file_parse(const char* file_path_on_disk, uint8_t** payload,
|
|||||||
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,
|
ssize_t res = parse_target(dfu_info.firmware + data_consumed, &ealt, &blob,
|
||||||
&blob, &blob_size, &blob_address);
|
&blob_size, &blob_address);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -109,11 +111,13 @@ dfu_file_parse(const char* file_path_on_disk, uint8_t** payload,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read next target, output data+size+alt. Returns bytes consumed
|
// Read next target, output data+size+alt. Returns bytes consumed
|
||||||
ssize_t
|
ssize_t parse_target(const uint8_t* data,
|
||||||
parse_target(const uint8_t* data, uint8_t* out_ealt, uint8_t** out_data,
|
uint8_t* out_ealt,
|
||||||
size_t* out_data_size, size_t* out_data_address) {
|
uint8_t** out_data,
|
||||||
if (data == NULL || out_ealt == NULL || out_data == NULL
|
size_t* out_data_size,
|
||||||
|| out_data_size == NULL) {
|
size_t* out_data_address) {
|
||||||
|
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') {
|
||||||
@ -142,14 +146,13 @@ parse_target(const uint8_t* data, uint8_t* out_ealt, uint8_t** out_data,
|
|||||||
return blob_length;
|
return blob_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int probe_prefix(struct dfu_file* file) {
|
||||||
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
|
||||||
|
|
||||||
@ -159,11 +162,10 @@ 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 = (prefix[7] << 24) | (prefix[6] << 16)
|
uint32_t payload_length =
|
||||||
| (prefix[5] << 8) | prefix[4];
|
(prefix[7] << 24) | (prefix[6] << 16) | (prefix[5] << 8) | prefix[4];
|
||||||
uint32_t expected_payload_length = (uint32_t)file->size.total
|
uint32_t expected_payload_length =
|
||||||
- LMDFU_PREFIX_LENGTH
|
(uint32_t)file->size.total - LMDFU_PREFIX_LENGTH - file->size.suffix;
|
||||||
- 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;
|
||||||
@ -179,8 +181,7 @@ probe_prefix(struct dfu_file* file) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dfu_file
|
struct dfu_file parse_dfu_suffix(const uint8_t* file_contents,
|
||||||
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
|
||||||
@ -203,8 +204,7 @@ 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'
|
if (dfu_suffix[10] != 'D' || dfu_suffix[9] != 'F' || dfu_suffix[8] != 'U') {
|
||||||
|| dfu_suffix[8] != 'U') {
|
|
||||||
reason = "Invalid DFU suffix signature";
|
reason = "Invalid DFU suffix signature";
|
||||||
missing_suffix = 1;
|
missing_suffix = 1;
|
||||||
goto checked;
|
goto checked;
|
||||||
@ -214,8 +214,8 @@ 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";
|
||||||
@ -231,8 +231,7 @@ 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",
|
fprintf(stderr, "Unsupported DFU suffix length %d", output.size.suffix);
|
||||||
output.size.suffix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.size.suffix > file_contents_length) {
|
if (output.size.suffix > file_contents_length) {
|
||||||
@ -250,73 +249,26 @@ checked:
|
|||||||
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("Possible TI Stellaris DFU prefix with "
|
printf(
|
||||||
|
"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[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24));
|
||||||
| (data[7] << 24));
|
|
||||||
} else if (output.prefix_type == LPCDFU_UNENCRYPTED_PREFIX) {
|
} else if (output.prefix_type == LPCDFU_UNENCRYPTED_PREFIX) {
|
||||||
printf("Possible unencrypted NXP LPC DFU prefix with "
|
printf(
|
||||||
|
"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;
|
|
||||||
}
|
|
47
tools/blisp/src/file_parsers/get_file_contents.c
Normal file
47
tools/blisp/src/file_parsers/get_file_contents.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include <stdio.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", 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;
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#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) {
|
||||||
@ -13,17 +14,23 @@ 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\r\n");
|
printf("Input file identified as a .dfu file\r\n");
|
||||||
// Handle as a .dfu file
|
// Handle as a .dfu file
|
||||||
return dfu_file_parse("test.dfu", &parsed_results->payload,
|
res = 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\r\n");
|
printf("Input file identified as a .bin file\r\n");
|
||||||
// Raw binary file
|
// Raw binary file
|
||||||
|
res = bin_file_parse("test.dfu", &parsed_results->payload,
|
||||||
|
&parsed_results->payload_length,
|
||||||
|
&parsed_results->payload_address);
|
||||||
}
|
}
|
||||||
// TODO: Hex files?
|
// If we wanted to support hex files, here would be where
|
||||||
return PARSED_ERROR_INVALID_FILETYPE;
|
|
||||||
|
parsed_results->needs_boot_struct = parsed_results->payload_address == 0;
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <stdio.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 */
|
||||||
|
|
||||||
@ -12,3 +14,7 @@
|
|||||||
|
|
||||||
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);
|
Loading…
Reference in New Issue
Block a user