mirror of
https://github.com/pine64/blisp.git
synced 2024-12-22 14:30:28 +00:00
f1b93a1881
* DFU file work
Just grabbing first one for now
Expose crc
Update CMakeLists.txt
Test DFU file
Split crc function
Fixup
Zero init struct
Dont null the pointer 🤦
correct fread
Adding tests
Create dfu_file.h
Format
Scratching out more parsing
Basic port parser
Scratching fread wrapper
* Relocate dfu parsing and link in
* Scratching out parsers
* Generic bin parser
* Pull out get file util
Update CMakeLists.txt
* Pull in the generic parser
Fixup
.
* Print flash address
* Rebase address
* stdlib
Update dfu_file.c
* FIXUP! flash offset
* Update dfu_file.c
* Improve logging
* Drop extra erase
* Adjust DFU to avoid goto
* Pragma -> ifndef
* Include Windows headers for missing data types
---------
Co-authored-by: Marek Kraus <gamelaster@outlook.com>
373 lines
13 KiB
C
373 lines
13 KiB
C
// SPDX-License-Identifier: MIT
|
|
#include "blisp_easy.h"
|
|
#include "blisp_struct.h"
|
|
#include "blisp_util.h"
|
|
|
|
#include <inttypes.h>
|
|
#include <string.h>
|
|
|
|
static blisp_return_t blisp_easy_transport_read(
|
|
struct blisp_easy_transport* transport,
|
|
void* buffer,
|
|
uint32_t size) {
|
|
if (transport->type == 0) {
|
|
// TODO: Implement reading more than available
|
|
memcpy(buffer,
|
|
(uint8_t*)transport->data.memory.data_location +
|
|
transport->data.memory.current_position,
|
|
size);
|
|
transport->data.memory.current_position += size;
|
|
return size;
|
|
} else {
|
|
return fread(buffer, size, 1, transport->data.file_handle);
|
|
}
|
|
}
|
|
|
|
static blisp_return_t blisp_easy_transport_size(
|
|
struct blisp_easy_transport* transport) {
|
|
if (transport->type == 0) {
|
|
return transport->data.memory.data_size;
|
|
} else {
|
|
// TODO: Implement
|
|
printf("%s() Warning: calling non-implemented function\n", __func__);
|
|
return BLISP_ERR_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
static void blisp_easy_report_progress(blisp_easy_progress_callback callback,
|
|
uint32_t current_value,
|
|
uint32_t max_value) {
|
|
if (callback != NULL) {
|
|
callback(current_value, max_value);
|
|
}
|
|
}
|
|
|
|
struct blisp_easy_transport blisp_easy_transport_new_from_file(FILE* file) {
|
|
struct blisp_easy_transport transport = {.type = 1, .data.file_handle = file};
|
|
return transport;
|
|
}
|
|
|
|
struct blisp_easy_transport blisp_easy_transport_new_from_memory(
|
|
void* data_location,
|
|
uint32_t data_size) {
|
|
struct blisp_easy_transport transport = {
|
|
.type = 0,
|
|
.data.memory.data_location = data_location,
|
|
.data.memory.data_size = data_size,
|
|
.data.memory.current_position = 0};
|
|
return transport;
|
|
}
|
|
|
|
int32_t blisp_easy_load_segment_data(
|
|
struct blisp_device* device,
|
|
uint32_t segment_size,
|
|
struct blisp_easy_transport* segment_transport,
|
|
blisp_easy_progress_callback progress_callback) {
|
|
int32_t ret;
|
|
#ifdef __APPLE__
|
|
const uint16_t buffer_max_size = 252 * 16;
|
|
#else
|
|
const uint16_t buffer_max_size = 4092;
|
|
#endif
|
|
|
|
uint32_t sent_data = 0;
|
|
uint32_t buffer_size = 0;
|
|
#ifdef _WIN32
|
|
uint8_t buffer[4092];
|
|
#else
|
|
uint8_t buffer[buffer_max_size];
|
|
#endif
|
|
|
|
blisp_easy_report_progress(progress_callback, 0, segment_size);
|
|
|
|
while (sent_data < segment_size) {
|
|
buffer_size = segment_size - sent_data;
|
|
if (buffer_size > buffer_max_size) {
|
|
buffer_size = buffer_max_size;
|
|
}
|
|
blisp_easy_transport_read(segment_transport, buffer,
|
|
buffer_size); // TODO: Error Handling
|
|
ret = blisp_device_load_segment_data(device, buffer, buffer_size);
|
|
if (ret < BLISP_OK) {
|
|
// TODO: Error logging fprintf(stderr, "Failed to load segment data. (ret
|
|
// %d)\n", ret);
|
|
return ret;
|
|
}
|
|
sent_data += buffer_size;
|
|
blisp_easy_report_progress(progress_callback, sent_data, segment_size);
|
|
}
|
|
return BLISP_OK;
|
|
}
|
|
|
|
int32_t blisp_easy_load_ram_image(
|
|
struct blisp_device* device,
|
|
struct blisp_easy_transport* image_transport,
|
|
blisp_easy_progress_callback progress_callback) {
|
|
int32_t ret;
|
|
|
|
struct bfl_boot_header image_boot_header;
|
|
// TODO: Error handling
|
|
blisp_easy_transport_read(image_transport, &image_boot_header, 176);
|
|
|
|
ret = blisp_device_load_boot_header(device, (uint8_t*)&image_boot_header);
|
|
if (ret != BLISP_OK) {
|
|
// TODO: Error printing: fprintf(stderr, "Failed to load boot header.\n");
|
|
return ret;
|
|
}
|
|
|
|
{
|
|
for (uint8_t seg_index = 0;
|
|
seg_index < image_boot_header.segment_info.segment_cnt; seg_index++) {
|
|
struct blisp_segment_header segment_header = {0};
|
|
blisp_easy_transport_read(image_transport, &segment_header,
|
|
16); // TODO: Error handling
|
|
|
|
ret = blisp_device_load_segment_header(device, &segment_header);
|
|
if (ret != 0) {
|
|
// TODO: Error printing: fprintf(stderr, "Failed to load segment
|
|
// header.");
|
|
return ret;
|
|
}
|
|
// TODO: Info printing: printf("Flashing %d. segment\n", seg_index + 1);
|
|
|
|
ret = blisp_easy_load_segment_data(device, segment_header.length,
|
|
image_transport, progress_callback);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
ret = blisp_device_check_image(device);
|
|
if (ret != BLISP_OK) {
|
|
// TODO: Error printing: fprintf(stderr, "Failed to check image.\n");
|
|
return BLISP_EASY_ERR_CHECK_IMAGE_FAILED;
|
|
}
|
|
|
|
return BLISP_OK;
|
|
}
|
|
|
|
int32_t blisp_easy_load_ram_app(
|
|
struct blisp_device* device,
|
|
struct blisp_easy_transport* app_transport,
|
|
blisp_easy_progress_callback progress_callback) {
|
|
int32_t ret;
|
|
// TODO: Rework
|
|
// region boot header fill
|
|
struct bfl_boot_header boot_header;
|
|
memcpy(boot_header.magiccode, "BFNP", 4);
|
|
memcpy(boot_header.flashCfg.magiccode, "FCFG", 4);
|
|
boot_header.revison = 0x01;
|
|
boot_header.flashCfg.cfg.ioMode = 0x04;
|
|
boot_header.flashCfg.cfg.cReadSupport = 0x01;
|
|
boot_header.flashCfg.cfg.clkDelay = 0x01;
|
|
boot_header.flashCfg.cfg.clkInvert = 0x01;
|
|
boot_header.flashCfg.cfg.resetEnCmd = 0x66;
|
|
boot_header.flashCfg.cfg.resetCmd = 0x99;
|
|
boot_header.flashCfg.cfg.resetCreadCmd = 0xFF;
|
|
boot_header.flashCfg.cfg.resetCreadCmdSize = 0x03;
|
|
boot_header.flashCfg.cfg.jedecIdCmd = 0x9F;
|
|
boot_header.flashCfg.cfg.jedecIdCmdDmyClk = 0x00;
|
|
boot_header.flashCfg.cfg.qpiJedecIdCmd = 0x9F;
|
|
boot_header.flashCfg.cfg.qpiJedecIdCmdDmyClk = 0x00;
|
|
boot_header.flashCfg.cfg.sectorSize = 0x04;
|
|
boot_header.flashCfg.cfg.mid = 0xEF;
|
|
boot_header.flashCfg.cfg.pageSize = 0x100;
|
|
boot_header.flashCfg.cfg.chipEraseCmd = 0xC7;
|
|
boot_header.flashCfg.cfg.sectorEraseCmd = 0x20;
|
|
boot_header.flashCfg.cfg.blk32EraseCmd = 0x52;
|
|
boot_header.flashCfg.cfg.blk64EraseCmd = 0xD8;
|
|
boot_header.flashCfg.cfg.writeEnableCmd = 0x06;
|
|
boot_header.flashCfg.cfg.pageProgramCmd = 0x02;
|
|
boot_header.flashCfg.cfg.qpageProgramCmd = 0x32;
|
|
boot_header.flashCfg.cfg.qppAddrMode = 0x00;
|
|
boot_header.flashCfg.cfg.fastReadCmd = 0x0B;
|
|
boot_header.flashCfg.cfg.frDmyClk = 0x01;
|
|
boot_header.flashCfg.cfg.qpiFastReadCmd = 0x0B;
|
|
boot_header.flashCfg.cfg.qpiFrDmyClk = 0x01;
|
|
boot_header.flashCfg.cfg.fastReadDoCmd = 0x3B;
|
|
boot_header.flashCfg.cfg.frDoDmyClk = 0x01;
|
|
boot_header.flashCfg.cfg.fastReadDioCmd = 0xBB;
|
|
boot_header.flashCfg.cfg.frDioDmyClk = 0x00;
|
|
boot_header.flashCfg.cfg.fastReadQoCmd = 0x6B;
|
|
boot_header.flashCfg.cfg.frQoDmyClk = 0x01;
|
|
boot_header.flashCfg.cfg.fastReadQioCmd = 0xEB;
|
|
boot_header.flashCfg.cfg.frQioDmyClk = 0x02;
|
|
boot_header.flashCfg.cfg.qpiFastReadQioCmd = 0xEB;
|
|
boot_header.flashCfg.cfg.qpiFrQioDmyClk = 0x02;
|
|
boot_header.flashCfg.cfg.qpiPageProgramCmd = 0x02;
|
|
boot_header.flashCfg.cfg.writeVregEnableCmd = 0x50;
|
|
boot_header.flashCfg.cfg.wrEnableIndex = 0x00;
|
|
boot_header.flashCfg.cfg.qeIndex = 0x01;
|
|
boot_header.flashCfg.cfg.busyIndex = 0x00;
|
|
boot_header.flashCfg.cfg.wrEnableBit = 0x01;
|
|
boot_header.flashCfg.cfg.qeBit = 0x01;
|
|
boot_header.flashCfg.cfg.busyBit = 0x00;
|
|
boot_header.flashCfg.cfg.wrEnableWriteRegLen = 0x02;
|
|
boot_header.flashCfg.cfg.wrEnableReadRegLen = 0x01;
|
|
boot_header.flashCfg.cfg.qeWriteRegLen = 0x01;
|
|
boot_header.flashCfg.cfg.qeReadRegLen = 0x01;
|
|
boot_header.flashCfg.cfg.releasePowerDown = 0xAB;
|
|
boot_header.flashCfg.cfg.busyReadRegLen = 0x01;
|
|
boot_header.flashCfg.cfg.readRegCmd[0] = 0x05;
|
|
boot_header.flashCfg.cfg.readRegCmd[1] = 0x35;
|
|
boot_header.flashCfg.cfg.readRegCmd[2] = 0x00;
|
|
boot_header.flashCfg.cfg.readRegCmd[3] = 0x00;
|
|
boot_header.flashCfg.cfg.writeRegCmd[0] = 0x01;
|
|
boot_header.flashCfg.cfg.writeRegCmd[1] = 0x31;
|
|
boot_header.flashCfg.cfg.writeRegCmd[2] = 0x00;
|
|
boot_header.flashCfg.cfg.writeRegCmd[3] = 0x00;
|
|
boot_header.flashCfg.cfg.enterQpi = 0x38;
|
|
boot_header.flashCfg.cfg.exitQpi = 0xFF;
|
|
boot_header.flashCfg.cfg.cReadMode = 0x20;
|
|
boot_header.flashCfg.cfg.cRExit = 0xFF;
|
|
boot_header.flashCfg.cfg.burstWrapCmd = 0x77;
|
|
boot_header.flashCfg.cfg.burstWrapCmdDmyClk = 0x03;
|
|
boot_header.flashCfg.cfg.burstWrapDataMode = 0x02;
|
|
boot_header.flashCfg.cfg.burstWrapData = 0x40;
|
|
boot_header.flashCfg.cfg.deBurstWrapCmd = 0x77;
|
|
boot_header.flashCfg.cfg.deBurstWrapCmdDmyClk = 0x03;
|
|
boot_header.flashCfg.cfg.deBurstWrapDataMode = 0x02;
|
|
boot_header.flashCfg.cfg.deBurstWrapData = 0xF0;
|
|
boot_header.flashCfg.cfg.timeEsector = 0x12C;
|
|
boot_header.flashCfg.cfg.timeE32k = 0x4B0;
|
|
boot_header.flashCfg.cfg.timeE64k = 0x4B0;
|
|
boot_header.flashCfg.cfg.timePagePgm = 0x05;
|
|
boot_header.flashCfg.cfg.timeCe = 0xD40;
|
|
boot_header.flashCfg.cfg.pdDelay = 0x03;
|
|
boot_header.flashCfg.cfg.qeData = 0x00;
|
|
boot_header.flashCfg.crc32 = 0xC4BDD748;
|
|
boot_header.clkCfg.cfg.xtal_type = 0x04;
|
|
boot_header.clkCfg.cfg.pll_clk = 0x04;
|
|
boot_header.clkCfg.cfg.hclk_div = 0x00;
|
|
boot_header.clkCfg.cfg.bclk_div = 0x01;
|
|
boot_header.clkCfg.cfg.flash_clk_type = 0x02;
|
|
boot_header.clkCfg.cfg.flash_clk_div = 0x00;
|
|
boot_header.clkCfg.crc32 = 0x824E14BB;
|
|
boot_header.bootcfg.bval.sign = 0x00;
|
|
boot_header.bootcfg.bval.encrypt_type = 0x00;
|
|
boot_header.bootcfg.bval.key_sel = 0x00;
|
|
boot_header.bootcfg.bval.rsvd6_7 = 0x00;
|
|
boot_header.bootcfg.bval.no_segment = 0x01;
|
|
boot_header.bootcfg.bval.cache_enable = 0x01;
|
|
boot_header.bootcfg.bval.notload_in_bootrom = 0x00;
|
|
boot_header.bootcfg.bval.aes_region_lock = 0x00;
|
|
boot_header.bootcfg.bval.cache_way_disable = 0x00;
|
|
boot_header.bootcfg.bval.crc_ignore = 0x01;
|
|
boot_header.bootcfg.bval.hash_ignore = 0x01;
|
|
boot_header.bootcfg.bval.halt_ap = 0x00;
|
|
boot_header.bootcfg.bval.rsvd19_31 = 0x00;
|
|
boot_header.segment_info.segment_cnt = 0x01;
|
|
boot_header.bootentry = 0x00;
|
|
boot_header.flashoffset = device->chip->tcm_address;
|
|
boot_header.hash[0x00] = 0xEF;
|
|
boot_header.hash[0x01] = 0xBE;
|
|
boot_header.hash[0x02] = 0xAD;
|
|
boot_header.hash[0x03] = 0xDE;
|
|
boot_header.hash[0x04] = 0x00;
|
|
boot_header.hash[0x05] = 0x00;
|
|
boot_header.hash[0x06] = 0x00;
|
|
boot_header.hash[0x07] = 0x00;
|
|
boot_header.hash[0x08] = 0x00;
|
|
boot_header.hash[0x09] = 0x00;
|
|
boot_header.hash[0x0a] = 0x00;
|
|
boot_header.hash[0x0b] = 0x00;
|
|
boot_header.hash[0x0c] = 0x00;
|
|
boot_header.hash[0x0d] = 0x00;
|
|
boot_header.hash[0x0e] = 0x00;
|
|
boot_header.hash[0x0f] = 0x00;
|
|
boot_header.hash[0x10] = 0x00;
|
|
boot_header.hash[0x11] = 0x00;
|
|
boot_header.hash[0x12] = 0x00;
|
|
boot_header.hash[0x13] = 0x00;
|
|
boot_header.hash[0x14] = 0x00;
|
|
boot_header.hash[0x15] = 0x00;
|
|
boot_header.hash[0x16] = 0x00;
|
|
boot_header.hash[0x17] = 0x00;
|
|
boot_header.hash[0x18] = 0x00;
|
|
boot_header.hash[0x19] = 0x00;
|
|
boot_header.hash[0x1a] = 0x00;
|
|
boot_header.hash[0x1b] = 0x00;
|
|
boot_header.hash[0x1c] = 0x00;
|
|
boot_header.hash[0x1d] = 0x00;
|
|
boot_header.hash[0x1e] = 0x00;
|
|
boot_header.hash[0x1f] = 0x00;
|
|
boot_header.rsv1 = 0x00;
|
|
boot_header.rsv2 = 0x00;
|
|
boot_header.crc32 = 0xDEADBEEF;
|
|
// endregion
|
|
|
|
ret = blisp_device_load_boot_header(device, (uint8_t*)&boot_header);
|
|
if (ret != BLISP_OK) {
|
|
blisp_dlog("Failed to load boot header, ret: %d.", ret);
|
|
return ret;
|
|
}
|
|
|
|
struct blisp_segment_header segment_header = {
|
|
.dest_addr = device->chip->tcm_address,
|
|
.length = blisp_easy_transport_size(app_transport),
|
|
.reserved = 0,
|
|
.crc32 = 0};
|
|
segment_header.crc32 = crc32_calculate(
|
|
&segment_header, 3 * sizeof(uint32_t)); // TODO: Make function
|
|
|
|
ret = blisp_device_load_segment_header(device, &segment_header);
|
|
if (ret != 0) {
|
|
blisp_dlog("Failed to load segment header, ret: %d.", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = blisp_easy_load_segment_data(device,
|
|
blisp_easy_transport_size(app_transport),
|
|
app_transport, progress_callback);
|
|
if (ret != 0) {
|
|
// TODO: Error printing
|
|
return ret;
|
|
}
|
|
|
|
return BLISP_OK;
|
|
}
|
|
|
|
int32_t blisp_easy_flash_write(struct blisp_device* device,
|
|
struct blisp_easy_transport* data_transport,
|
|
uint32_t flash_location,
|
|
uint32_t data_size,
|
|
blisp_easy_progress_callback progress_callback) {
|
|
int32_t ret;
|
|
#if defined(__APPLE__) || defined(__FreeBSD__)
|
|
const uint16_t buffer_max_size = 372 * 1;
|
|
#else
|
|
const uint16_t buffer_max_size = 2052;
|
|
#endif
|
|
|
|
uint32_t sent_data = 0;
|
|
uint32_t buffer_size = 0;
|
|
#ifdef _WIN32
|
|
uint8_t buffer[2052];
|
|
#else
|
|
uint8_t buffer[buffer_max_size];
|
|
#endif
|
|
blisp_easy_report_progress(progress_callback, 0, data_size);
|
|
|
|
while (sent_data < data_size) {
|
|
buffer_size = data_size - sent_data;
|
|
if (buffer_size > buffer_max_size) {
|
|
buffer_size = buffer_max_size;
|
|
}
|
|
ret = blisp_easy_transport_read(data_transport, buffer, buffer_size);
|
|
if (ret < BLISP_OK) {
|
|
fprintf(stderr, "Failed to read firmware chunk! (ret:%d)\n ", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = blisp_device_flash_write(device, flash_location + sent_data, buffer,
|
|
buffer_size);
|
|
if (ret < BLISP_OK) {
|
|
fprintf(stderr, "Failed to write firmware! (ret:%d)\n ", ret);
|
|
return ret;
|
|
}
|
|
sent_data += buffer_size;
|
|
blisp_easy_report_progress(progress_callback, sent_data, data_size);
|
|
}
|
|
return BLISP_OK;
|
|
} |