16 Commits
Author SHA1 Message Date
Marek Kraus 0e0ffb1d8c Change version to 0.0.1 2023-01-09 21:49:44 +01:00
Marek Kraus a6b9b4102b Fix Windows support 2023-01-09 21:38:06 +01:00
Marek Kraus 279f2433ea Integrated eflash_loader 2023-01-09 21:23:46 +01:00
Marek Kraus 59cf5fb038 Add blisp_easy, many improvements, adds iot single download feature 2023-01-07 23:25:42 +01:00
Marek Kraus ed2c9b80b8 Creating common functions: prepare flash 2023-01-07 19:57:23 +01:00
Marek Kraus a072ddb3f3 Move some stuff to new util file 2023-01-07 16:57:58 +01:00
Marek Kraus 2740d305ba Added initial BL61X and BL808 support, some chip changes 2023-01-07 16:57:45 +01:00
Marek Kraus 841a52177b Some improvements to readme and added blisp_dlog 2023-01-07 15:07:25 +01:00
Marek Kraus 8a00a63600 Make proper error handling 2023-01-07 13:34:33 +01:00
Marek Kraus da34daf69f Update code styly and reformat code 2023-01-07 11:50:51 +01:00
Marek Kraus 9fbaa05b64 Migrate Pinecil V2 instructions to Github Wiki 2023-01-07 10:38:06 +01:00
RiverandBen V. Brown 7601709a4c improved blisp instructions (#12)
* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

Co-authored-by: Ben V. Brown <5425387+Ralim@users.noreply.github.com>

* Update README.md

Co-authored-by: Ben V. Brown <5425387+Ralim@users.noreply.github.com>
2023-01-01 13:07:37 +11:00
River 4618e722ab Added instructions (#11)
* Update README.md

* Update README.md

* Update README.md

* Update README.md
2022-12-14 07:01:16 +01:00
Marek Kraus eb086f6fe3 Add initial MacOS support 2022-12-06 17:15:53 +01:00
Marek Kraus a68c54ed2b Fix indentation 2022-12-06 16:10:46 +01:00
Marek Kraus b9a2baae13 Merge pull request #3 from pine64/write
Modifications for MacOS to let it find data files in the same directory as the executable. This is totally wrong for a "normal" MacOS app bundle, but it follows the existing Linux convention.
2022-12-06 16:09:22 +01:00
26 changed files with 9832 additions and 1157 deletions
+2 -56
View File
@@ -1,58 +1,4 @@
---
Language: Cpp
BasedOnStyle: GNU
IndentWidth: 4
AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: None
BreakBeforeBraces: Custom
BraceWrapping:
AfterFunction: false
AfterCaseLabel: false
AfterEnum: false
AfterControlStatement: Never
AfterStruct : false
AfterUnion : false
AfterExternBlock : false
BeforeElse : false
BeforeWhile : false
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
AlignEscapedNewlines: Right
AlignOperands: Align
AllowShortEnumsOnASingleLine: False
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine : false
AlwaysBreakAfterReturnType: AllDefinitions
AlignTrailingComments : true
AlignConsecutiveMacros: AcrossEmptyLines
KeepEmptyLinesAtTheStartOfBlocks : false
PointerAlignment : Left
QualifierAlignment : Left
ReferenceAlignment : Left
RemoveBracesLLVM : false
SpaceAfterCStyleCast : false
SpaceAfterLogicalNot : false
SpaceAfterTemplateKeyword : false
SpaceAroundPointerQualifiers : Before
SpaceBeforeAssignmentOperators : true
SpaceBeforeCaseColon : false
SpaceBeforeCpp11BracedList : false
SpaceBeforeParens : ControlStatements
SpaceBeforeParensOptions :
AfterControlStatements : true
AfterFunctionDeclarationName : false
AfterFunctionDefinitionName : false
AfterOverloadedOperator : false
SpaceBeforeRangeBasedForLoopColon : false
SpaceBeforeSquareBrackets : false
SpaceInEmptyBlock : false
SpaceInEmptyParentheses : false
SpacesInCStyleCastParentheses : false
SpacesInConditionalStatement : false
SpacesInContainerLiterals : false
SpacesInParentheses: false
SpacesInSquareBrackets : false
UseTab : Never
BasedOnStyle: Chromium
BitFieldColonSpacing: None
BreakBeforeBinaryOperators: All
...
+2
View File
@@ -76,3 +76,5 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
build/
.DS_Store
+9 -6
View File
@@ -8,7 +8,7 @@ option(BLISP_BUILD_CLI "Build CLI Tool" OFF)
add_library(libblisp_obj OBJECT
lib/blisp.c
lib/chip/blisp_chip_bl60x.c
lib/chip/blisp_chip_bl70x.c)
lib/chip/blisp_chip_bl70x.c lib/blisp_easy.c)
target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/include/)
@@ -20,15 +20,15 @@ add_library(libblisp_static STATIC $<TARGET_OBJECTS:libblisp_obj>)
set_target_properties(libblisp PROPERTIES
PUBLIC_HEADER "include/blisp.h"
VERSION 1.0
VERSION 0.0.1
SOVERSION 1
LIBRARY_OUTPUT_DIRECTORY "shared"
OUTPUT_NAME "blisp")
set_target_properties(libblisp_static PROPERTIES
PUBLIC_HEADER "include/blisp.h"
VERSION 1.0
SOVERSION 1
VERSION 0.0.1
SOVERSION 2
ARCHIVE_OUTPUT_DIRECTORY "static"
OUTPUT_NAME "blisp")
@@ -58,8 +58,11 @@ elseif(UNIX AND NOT APPLE)
elseif(APPLE)
target_sources(libblisp_obj PRIVATE
${CMAKE_SOURCE_DIR}/vendor/libserialport/macosx.c)
target_link_libraries(libblisp_obj PRIVATE "-framework IOKit" "-framework CoreFoundation")
target_compile_definitions(libblisp_obj PRIVATE LIBSERIALPORT_ATBUILD "SP_API=__attribute__((visibility(\"default\")))")
target_link_libraries(libblisp PRIVATE "-framework IOKit" "-framework CoreFoundation")
target_compile_definitions(libblisp_obj PRIVATE
LIBSERIALPORT_ATBUILD
"SP_PRIV=__attribute__((visibility(\"hidden\")))"
"SP_API=__attribute__((visibility(\"default\")))")
target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/vendor/libserialport)
write_file(${CMAKE_SOURCE_DIR}/vendor/libserialport/config.h "// bypass errors.")
endif()
+7 -93
View File
@@ -12,14 +12,16 @@ Open source tool and library for flashing Bouffalo RISC-V MCUs.
- [ ] `bl61x` - BL616 / BL618
- [ ] `bl808` - BL808
# Supported Devices
- [X] [Pinecil V2](https://wiki.pine64.org/wiki/Pinecil)
# Supported OS
- [x] Windows
- [x] Linux
- [ ] Apple (WIP: work-in-progress)
# Building
## Clone repository
If you have not cloned this repository locally; check out the git repository locally by running
If you have not cloned this repository locally; clone the git repository locally by running
```bash
git clone --recursive https://github.com/pine64/blisp.git
@@ -50,94 +52,6 @@ For BL60X, you need to specify also the serial port path:
blisp --chip bl60x --reset -p /dev/ttyUSB0 name_of_firmware.bin
```
# Updating Pinecil V2: How to build BLISP Flasher
# How to flash Pinecil V2
_Note: This has been tested on x86-64. The build process also works on aarch64 and armv7._
## Linux Steps
⛔ Do not use the Pinecil DC barrel jack while updating firmware or you may destroy your PC. ⛔
1. **Linux set-up**
```
git clone --recursive https://github.com/pine64/blisp.git
cd blisp
mkdir build && cd build
cmake -DBLISP_BUILD_CLI=ON ..
cmake --build .
mkdir tools/blisp/data
mkdir -p tools/blisp/data/bl70x
```
Note: the blisp command will now be in build/tools/blisp/ folder and could later be run with flags as ` ./tools/blisp/blisp` unless you cd into that folder.
2. Get and cp or mv eflash_loader_32m.bin to bl70x folder
```
/build/tools/blisp/data/bl70x/eflash_loader_32m.bin
```
a. Download [eflash*32m.bin here](https://github.com/River-b/blisp/tree/master/eflash).
b. Move eflash*32m.bin to the build/tools/data/bl70x folder
b. Move eflash*32m.bin to the folder build/tools/data/bl70x
c. If it is a Zip, then unzip & move it.
```
unzip eflash_loader_32m.zip -d tools/blisp/data/bl70x/
```
3. **Get V2 firmware** from Github Ralim's IronOS
a. Download the newest stable [firmware release here](https://github.com/Ralim/IronOS).
b. Or download the Beta firmware [IronOS here](https://github.com/Ralim/IronOS/actions/runs/3545583488)
Scroll to the very bottom of the page and download **Pinecilv2**. This link is to [beta that has BLE and also works for EPR chargers](https://github.com/Ralim/IronOS/actions/runs/3545583488)
d. Extract **Pinecilv2.zip** and select a single language file (English = ```Pinecilv2_EN.bin```).
e. Move the Pinecilv2_EN.bin (or selected language) into the same folder as the blisp command.
```
build/tools/blisp/Pinecilv2_EN.bin
```
can delete all the rest of the Pinecilv2**.zip as it is not needed.
4. Connect Pinecil to PC/laptop: long hold [`-`] , then connect cable. Can release the [-] after about 15-20second. V2 screen should be Empty/black, if not, then repeat connection, or find another cable/port. Pinecil connects as a serial COM port.
5. If this fails, see [troubleshooting below](https://github.com/River-b/blisp/blob/master/README.md#troubleshooting).
6. If you are in the folder `blisp/build/tools/blisp/` then execute
```
sudo ./blisp write -c bl70x --reset Pinecilv2_EN.bin
```
Note: if a different language was selected, replace `Pinecilv2_**.bin` above with the chosen file name.
7. Almost done: unplug from the PC and restart V2. Hold down the minus `(-)` button to see the new version number.
8. Before making menu changes, it is recommended to first [Restore Settings to Default](https://github.com/Ralim/IronOS/blob/dev/Documentation/GettingStarted.md#settings-menu).
Simply go to Advanced settings > Restore default settings, confirm using the `(+)` button. This sets all menu items to defaults, keeps the same firmware version, and does not affect any Boot-up logo art if applicable. Setting defaults first avoids unexpected behavior due to some changes in upgrades.
9. Congradulations, and [Stay Fluxey, my friends!](https://www.reddit.com/r/PINE64official/comments/xk9vxu/most_interesting_man_in_the_world_i_dont_always/?utm_source=share&utm_medium=web2x&context=3)
## Troubleshooting
1. If the Pinecil V2 fails to connect to the PC, check the `dmesg` command output.
a. try different cable: usb-C to C is recommended over Usb-A, especially if you are having issues.
b. don't use a USB hub, directly connect to the USB port on the PC or laptop.
c. try different Usb ports (usb-c recommended). Sometimes the rear ports on a PC are better because they are directly connected to the motherboard.
d. try a different PC/laptop
2. It is important to hold down the `(-)` minus button _before_ plugging in the Usb-c cable, and do not release the button for another 15-20 seconds. Try to hold it a little longer before releasing if your computer is slow and it is not working. In rare circumstances on fussy USB ports, keep holding the `(-)` for the entire update.
3. If all of this fails, then join one of the [Live Community Chat channels linked](https://wiki.pine64.org/wiki/Pinecil#Community_links) in the Pinecil Wiki as volunteers there might be able to help.
4. Open a an new issue ticket in this Github/Blisp flasher at https://github.com/pine64/blisp/issues
5. See [Pinecil Wiki](https://wiki.pine64.org/wiki/Pinecil) for hardware information.
6. See [Github Ralim's IronOS](https://ralim.github.io/IronOS/#getting-started) for firmware/software information. This is only the Flasher that loads the firmware; all Pinecil firmware documents and menu instructions are in IronOS.
# To Do
- [ ] Another code style
- [ ] Finalize API
- [ ] SDIO and JTAG support
Check out the [wiki page](https://github.com/pine64/blisp/wiki/Update-Pinecil-V2).
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+33 -8
View File
@@ -6,6 +6,18 @@
#include "blisp_chip.h"
enum blisp_return {
BLISP_OK = 0,
BLISP_ERR_UNKNOWN = -1,
BLISP_ERR_NO_RESPONSE = -2,
BLISP_ERR_DEVICE_NOT_FOUND = -3,
BLISP_ERR_CANT_OPEN_DEVICE = -4,
// Can't auto-find device due it doesn't have native USB
BLISP_ERR_NO_AUTO_FIND_AVAILABLE = -5,
BLISP_ERR_PENDING = -6,
BLISP_ERR_CHIP_ERR = -7
};
struct blisp_segment_header {
uint32_t dest_addr;
uint32_t length;
@@ -28,22 +40,35 @@ struct blisp_boot_info {
uint8_t chip_id[8]; // TODO: BL60X only 6 bytes
};
// TODO: Refactor variable names, so all will follow same semantic, like image_run, image_check etc.
// TODO: Refactor variable names, so all will follow same semantic, like
// image_run, image_check etc.
int32_t blisp_device_init(struct blisp_device* device, struct blisp_chip* chip);
int32_t blisp_device_open(struct blisp_device* device, const char* port_name);
int32_t blisp_device_handshake(struct blisp_device* device, bool in_ef_loader);
int32_t blisp_device_get_boot_info(struct blisp_device* device, struct blisp_boot_info* boot_info);
int32_t blisp_device_load_boot_header(struct blisp_device* device, uint8_t* boot_header);
int32_t blisp_device_load_segment_header(struct blisp_device* device, struct blisp_segment_header* segment_header);
int32_t blisp_device_load_segment_data(struct blisp_device* device, uint8_t* segment_data, uint32_t segment_data_length);
int32_t blisp_device_get_boot_info(struct blisp_device* device,
struct blisp_boot_info* boot_info);
int32_t blisp_device_load_boot_header(struct blisp_device* device,
uint8_t* boot_header);
int32_t blisp_device_load_segment_header(
struct blisp_device* device,
struct blisp_segment_header* segment_header);
int32_t blisp_device_load_segment_data(struct blisp_device* device,
uint8_t* segment_data,
uint32_t segment_data_length);
int32_t blisp_device_write_memory(struct blisp_device* device,
uint32_t address, uint32_t value,
uint32_t address,
uint32_t value,
bool wait_for_res);
int32_t blisp_device_check_image(struct blisp_device* device);
int32_t blisp_device_run_image(struct blisp_device* device);
int32_t blisp_device_flash_erase(struct blisp_device* device, uint32_t start_address, uint32_t end_address);
int32_t blisp_device_flash_write(struct blisp_device* device, uint32_t start_address, uint8_t* payload, uint32_t payload_size);
int32_t blisp_device_flash_erase(struct blisp_device* device,
uint32_t start_address,
uint32_t end_address);
int32_t blisp_device_flash_write(struct blisp_device* device,
uint32_t start_address,
uint8_t* payload,
uint32_t payload_size);
int32_t blisp_device_program_check(struct blisp_device* device);
int32_t blisp_device_reset(struct blisp_device* device);
void blisp_device_close(struct blisp_device* device);
+10 -3
View File
@@ -2,12 +2,15 @@
#ifndef _BLISP_CHIP_H
#define _BLISP_CHIP_H
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
enum blisp_chip_type {
BLISP_CHIP_BL60X,
BLISP_CHIP_BL70X
BLISP_CHIP_BL70X,
BLISP_CHIP_BL606P,
BLISP_CHIP_BL808,
BLISP_CHIP_BL61X,
};
struct blisp_chip { // TODO: Move elsewhere?
@@ -15,10 +18,14 @@ struct blisp_chip { // TODO: Move elsewhere?
const char* type_str;
bool usb_isp_available;
float handshake_byte_multiplier;
const char* default_eflash_loader_xtal; // TODO: Make this selectable
const char* default_xtal; // TODO: Make this selectable
int64_t (*load_eflash_loader)(uint8_t clk_type, uint8_t** firmware_buf_ptr);
uint32_t tcm_address;
};
extern struct blisp_chip blisp_chip_bl60x;
extern struct blisp_chip blisp_chip_bl70x;
extern struct blisp_chip blisp_chip_bl808;
extern struct blisp_chip blisp_chip_bl61x;
#endif
+54
View File
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: MIT
#ifndef BLISP_BLISP_EASY_H
#define BLISP_BLISP_EASY_H
#include <stdio.h>
#include "blisp.h"
struct blisp_easy_transport {
uint8_t type; // 0 - memory, 1 - FILE file_handle
union {
FILE* file_handle;
struct {
void* data_location;
uint32_t data_size;
uint32_t current_position;
} memory;
} data;
};
enum blisp_easy_error {
BLISP_EASY_ERR_TRANSPORT_ERROR = -100,
BLISP_EASY_ERR_CHECK_IMAGE_FAILED = -101
};
typedef void (*blisp_easy_progress_callback)(uint32_t current_value,
uint32_t max_value);
struct blisp_easy_transport blisp_easy_transport_new_from_file(FILE* file);
struct blisp_easy_transport blisp_easy_transport_new_from_memory(
void* data_location,
uint32_t data_size);
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 blisp_easy_load_ram_image(
struct blisp_device* device,
struct blisp_easy_transport* image_transport,
blisp_easy_progress_callback progress_callback);
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 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);
#endif // BLISP_BLISP_EASY_H
+18 -19
View File
@@ -6,16 +6,18 @@
#ifndef _LIBBLISP_STRUCT_H
#define _LIBBLISP_STRUCT_H
#include <stdint.h>
#include <assert.h>
#include <stdint.h>
#pragma pack(push, 1)
typedef struct {
uint8_t ioMode; /*!< Serail flash interface mode,bit0-3:IF mode,bit4:unwrap */
uint8_t cReadSupport; /*!< Support continuous read mode,bit0:continuous read mode support,bit1:read mode cfg */
uint8_t cReadSupport; /*!< Support continuous read mode,bit0:continuous read
mode support,bit1:read mode cfg */
uint8_t clkDelay; /*!< SPI clock delay,bit0-3:delay,bit4-6:pad delay */
uint8_t clkInvert; /*!< SPI clock phase invert,bit0:clck invert,bit1:rx invert,bit2-4:pad delay,bit5-7:pad delay */
uint8_t clkInvert; /*!< SPI clock phase invert,bit0:clck invert,bit1:rx
invert,bit2-4:pad delay,bit5-7:pad delay */
uint8_t resetEnCmd; /*!< Flash enable reset command */
uint8_t resetCmd; /*!< Flash reset command */
uint8_t resetCreadCmd; /*!< Flash reset continuous read command */
@@ -88,15 +90,13 @@ typedef struct {
#define BFLB_BOOTROM_HASH_SIZE 256 / 8
struct boot_flash_cfg_t
{
struct boot_flash_cfg_t {
char magiccode[4]; /*'FCFG'*/
SPI_Flash_Cfg_Type cfg;
uint32_t crc32;
};
struct sys_clk_cfg_t
{
struct sys_clk_cfg_t {
uint8_t xtal_type;
uint8_t pll_clk;
uint8_t hclk_div;
@@ -107,15 +107,13 @@ struct sys_clk_cfg_t
uint8_t rsvd[2];
};
struct boot_clk_cfg_t
{
struct boot_clk_cfg_t {
char magiccode[4]; /*'PCFG'*/
struct sys_clk_cfg_t cfg;
uint32_t crc32;
};
struct bfl_boot_header
{
struct bfl_boot_header {
char magiccode[4]; /*'BFXP'*/
uint32_t revison;
struct boot_flash_cfg_t flashCfg;
@@ -128,7 +126,8 @@ struct bfl_boot_header
uint32_t rsvd6_7 : 2; /* [7: 6] for encrypt*/
uint32_t no_segment : 1; /* [8] no segment info */
uint32_t cache_enable : 1; /* [9] for cache */
uint32_t notload_in_bootrom : 1; /* [10] not load this img in bootrom */
uint32_t
notload_in_bootrom : 1; /* [10] not load this img in bootrom */
uint32_t aes_region_lock : 1; /* [11] aes region lock */
uint32_t cache_way_disable : 4; /* [15: 12] cache way disable info*/
uint32_t crc_ignore : 1; /* [16] ignore crc */
@@ -137,12 +136,12 @@ struct bfl_boot_header
uint32_t rsvd19_31 : 13; /* [31:19] rsvd */
} bval;
uint32_t wval;
}bootcfg ;
} bootcfg;
union {
uint32_t segment_cnt;
uint32_t img_length;
}segment_info;
} segment_info;
uint32_t bootentry; /* entry point of the image*/
@@ -155,18 +154,18 @@ struct bfl_boot_header
uint32_t crc32;
};
static_assert(sizeof(struct bfl_boot_header) == 176, "Bootheader have wrong size");
static_assert(sizeof(struct bfl_boot_header) == 176,
"Bootheader have wrong size");
struct blflash_segment_header
{
struct blflash_segment_header {
uint32_t destaddr;
uint32_t len;
uint32_t rsvd;
uint32_t crc32;
};
static_assert(sizeof(struct blflash_segment_header) == 16, "Segment header have wrong size");
static_assert(sizeof(struct blflash_segment_header) == 16,
"Segment header have wrong size");
#pragma pack(pop)
+77 -1
View File
@@ -2,13 +2,26 @@
#ifndef _BLISP_UTIL_H
#define _BLISP_UTIL_H
#include <stdarg.h>
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#else
#include <time.h>
#endif
static void sleep_ms(int milliseconds){
static void blisp_dlog(const char* format, ...)
{
fflush(stdout);
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
fputc('\n', stderr);
}
static void sleep_ms(int milliseconds) {
#ifdef WIN32
Sleep(milliseconds);
#else
@@ -19,4 +32,67 @@ static void sleep_ms(int milliseconds){
#endif
}
/**
* * Generated on Mon Jan 9 19:56:36 2023
* by pycrc vunknown, https://pycrc.org
* using the configuration:
* - Width = 32
* - Poly = 0x04c11db7
* - XorIn = 0xffffffff
* - ReflectIn = True
* - XorOut = 0xffffffff
* - ReflectOut = True
* - Algorithm = table-driven
*/
static const uint32_t crc_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
static uint32_t crc32_calculate(const void *data, size_t data_len)
{
uint32_t crc = 0xffffffff;
const unsigned char *d = (const unsigned char *)data;
unsigned int tbl_idx;
while (data_len--) {
tbl_idx = (crc ^ *d) & 0xff;
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
d++;
}
return (crc & 0xffffffff) ^ 0xffffffff;
}
#endif
+154 -114
View File
@@ -2,8 +2,8 @@
#include <blisp.h>
#include <blisp_util.h>
#include <libserialport.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __linux__
@@ -13,55 +13,61 @@
#define DEBUG
int32_t blisp_device_init(struct blisp_device* device, struct blisp_chip* chip)
{
int32_t blisp_device_init(struct blisp_device* device,
struct blisp_chip* chip) {
device->chip = chip;
device->is_usb = false;
return 0;
}
int32_t blisp_device_open(struct blisp_device* device, const char* port_name)
{
int32_t blisp_device_open(struct blisp_device* device, const char* port_name) {
int ret;
struct sp_port* serial_port = NULL;
if (port_name != NULL) {
ret = sp_get_port_by_name(port_name, &serial_port);
if (ret != SP_OK) {
return -1; // TODO: Improve error codes
blisp_dlog("Couldn't open device, err: %d", ret);
return BLISP_ERR_CANT_OPEN_DEVICE;
}
} else {
if (!device->chip->usb_isp_available) {
return -2; // Can't auto-find device due it doesn't have native USB
return BLISP_ERR_NO_AUTO_FIND_AVAILABLE;
}
struct sp_port **port_list;
struct sp_port** port_list;
ret = sp_list_ports(&port_list);
if (ret != SP_OK) {
return -1; // TODO: Improve error codes
blisp_dlog("Couldn't list ports, err: %d", ret);
return BLISP_ERR_UNKNOWN;
}
for (int i = 0; port_list[i] != NULL; i++) {
struct sp_port *port = port_list[i];
struct sp_port* port = port_list[i];
int vid, pid;
sp_get_port_usb_vid_pid(port, &vid, &pid);
if (vid == 0xFFFF && pid == 0xFFFF) {
ret = sp_get_port_by_name(sp_get_port_name(port), &serial_port);
if (ret != SP_OK) {
return -1; // TODO: Improve error codes
blisp_dlog("Couldn't open device, err: %d", ret);
return BLISP_ERR_CANT_OPEN_DEVICE;
}
break;
}
}
sp_free_port_list(port_list);
if (serial_port == NULL) {
return -3; // Device not found
return BLISP_ERR_DEVICE_NOT_FOUND;
}
}
ret = sp_open(serial_port, SP_MODE_READ_WRITE);
if (ret != SP_OK) { // TODO: Handle not found
return -1;
if (ret != SP_OK) {
blisp_dlog("SP open failed: %d", ret);
return BLISP_ERR_UNKNOWN; // TODO: Maybe this should be that it can't open
// device?
}
// TODO: Handle errors in following functions, although, none of them *should*
// fail
sp_set_bits(serial_port, 8);
sp_set_parity(serial_port, SP_PARITY_NONE);
sp_set_stopbits(serial_port, 1);
@@ -70,11 +76,11 @@ int32_t blisp_device_open(struct blisp_device* device, const char* port_name)
uint32_t vid, pid;
sp_get_port_usb_vid_pid(serial_port, &vid, &pid);
device->is_usb = pid == 0xFFFF;
// if (device->is_usb) {
// device->current_baud_rate = 2000000;
// } else {
// if (device->is_usb) {
// device->current_baud_rate = 2000000;
// } else {
device->current_baud_rate = 500000;
// }
// }
#if 0
int fd;
@@ -87,15 +93,19 @@ int32_t blisp_device_open(struct blisp_device* device, const char* port_name)
#endif
ret = sp_set_baudrate(serial_port, device->current_baud_rate);
if (ret != SP_OK) {
return -1; // TODO: Handle this
blisp_dlog("Set baud rate failed: %d... Also hello macOS user :)", ret);
return BLISP_ERR_UNKNOWN;
}
device->serial_port = serial_port;
return 0;
return BLISP_OK;
}
int32_t blisp_send_command(struct blisp_device* device, uint8_t command, void* payload, uint16_t payload_size, bool add_checksum)
{
int32_t blisp_send_command(struct blisp_device* device,
uint8_t command,
void* payload,
uint16_t payload_size,
bool add_checksum) {
int ret;
struct sp_port* serial_port = device->serial_port;
@@ -114,46 +124,49 @@ int32_t blisp_send_command(struct blisp_device* device, uint8_t command, void* p
if (payload_size != 0) {
memcpy(&device->tx_buffer[4], payload, payload_size);
}
ret = sp_blocking_write(serial_port, device->tx_buffer, 4 + payload_size, 1000);
ret =
sp_blocking_write(serial_port, device->tx_buffer, 4 + payload_size, 1000);
if (ret != (4 + payload_size)) {
return -1;
blisp_dlog("Received error or not written all data: %d", ret);
return BLISP_ERR_UNKNOWN;
}
return 0;
return BLISP_OK;
}
int32_t blisp_receive_response(struct blisp_device* device, bool expect_payload) {
int32_t blisp_receive_response(struct blisp_device* device,
bool expect_payload) {
// TODO: Check checksum
int ret;
struct sp_port* serial_port = device->serial_port;
ret = sp_blocking_read(serial_port, &device->rx_buffer[0], 2, 1000);
if (ret < 2) {
#ifdef DEBUG
fprintf(stderr, "Failed to receive response. (ret = %d)\n", ret);
#endif
return -1; // TODO: Terrible
blisp_dlog("Failed to receive response, ret: %d", ret);
return BLISP_ERR_UNKNOWN; // TODO: Terrible
} else if (device->rx_buffer[0] == 'O' && device->rx_buffer[1] == 'K') {
if (expect_payload) {
sp_blocking_read(serial_port, &device->rx_buffer[2], 2, 100); // TODO: Check if really we received the data.
uint16_t data_length = (device->rx_buffer[3] << 8) | (device->rx_buffer[2]);
sp_blocking_read(serial_port, &device->rx_buffer[2], 2,
100); // TODO: Check if really we received the data.
uint16_t data_length =
(device->rx_buffer[3] << 8) | (device->rx_buffer[2]);
sp_blocking_read(serial_port, &device->rx_buffer[0], data_length, 100);
return data_length;
}
return 0;
} else if (device->rx_buffer[0] == 'P' && device->rx_buffer[1] == 'D') {
return -3; // TODO: Terrible
return BLISP_ERR_PENDING; // TODO: This might be rather positive return
// number?
} else if (device->rx_buffer[0] == 'F' && device->rx_buffer[1] == 'L') {
sp_blocking_read(serial_port, &device->rx_buffer[2], 2, 100);
device->error_code = (device->rx_buffer[3] << 8) | (device->rx_buffer[2]);
return -4; // Failed
blisp_dlog("Chip returned error: %d", device->error_code);
return BLISP_ERR_CHIP_ERR;
}
#ifdef DEBUG
fprintf(stderr, "Receive response failed... (err: %d, %d - %d)\n", ret, device->rx_buffer[0], device->rx_buffer[1]);
#endif
return -1;
blisp_dlog("Failed to receive any response (err: %d, %d - %d)", ret,
device->rx_buffer[0], device->rx_buffer[1]);
return BLISP_ERR_UNKNOWN;
}
int32_t
blisp_device_handshake(struct blisp_device* device, bool in_ef_loader) {
int32_t blisp_device_handshake(struct blisp_device* device, bool in_ef_loader) {
int ret;
uint8_t handshake_buffer[600];
struct sp_port* serial_port = device->serial_port;
@@ -168,21 +181,22 @@ blisp_device_handshake(struct blisp_device* device, bool in_ef_loader) {
sleep_ms(50); // Wait a bit so BootROM can init
}
uint32_t bytes_count = device->chip->handshake_byte_multiplier * (float)device->current_baud_rate / 10.0f;
if (bytes_count > 600) bytes_count = 600;
uint32_t bytes_count = device->chip->handshake_byte_multiplier *
(float)device->current_baud_rate / 10.0f;
if (bytes_count > 600)
bytes_count = 600;
memset(handshake_buffer, 'U', bytes_count);
for (uint8_t i = 0; i < 5; i++) {
if (!in_ef_loader) {
if (device->is_usb) {
sp_blocking_write(serial_port, "BOUFFALOLAB5555RESET\0\0", 22,
100);
sp_blocking_write(serial_port, "BOUFFALOLAB5555RESET\0\0", 22, 100);
}
}
ret = sp_blocking_write(serial_port, handshake_buffer, bytes_count,
500);
ret = sp_blocking_write(serial_port, handshake_buffer, bytes_count, 500);
if (ret < 0) {
return -1;
blisp_dlog("Handshake write failed, ret %d", ret);
return BLISP_ERR_UNKNOWN;
}
if (!in_ef_loader && !device->is_usb) {
@@ -193,171 +207,197 @@ blisp_device_handshake(struct blisp_device* device, bool in_ef_loader) {
ret = sp_blocking_read(serial_port, device->rx_buffer, 2, 50);
if (ret >= 2) {
if (device->rx_buffer[0] == 'O' && device->rx_buffer[1] == 'K') {
return 0;
return BLISP_OK;
}
}
}
return -4; // didn't received response
blisp_dlog("Received no response from chip.");
return BLISP_ERR_NO_RESPONSE;
}
int32_t blisp_device_get_boot_info(struct blisp_device* device, struct blisp_boot_info* boot_info)
{
int32_t blisp_device_get_boot_info(struct blisp_device* device,
struct blisp_boot_info* boot_info) {
int ret;
ret = blisp_send_command(device, 0x10, NULL, 0, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
ret = blisp_receive_response(device, true);
if (ret < 0) return ret;
if (ret < 0)
return ret;
memcpy(boot_info->boot_rom_version, &device->rx_buffer[0], 4); // TODO: Endianess
memcpy(boot_info->boot_rom_version, &device->rx_buffer[0],
4); // TODO: Endianess
if (device->chip->type == BLISP_CHIP_BL70X) {
memcpy(boot_info->chip_id, &device->rx_buffer[16], 8);
}
// TODO: BL60X
return 0;
return BLISP_OK;
}
// TODO: Use struct instead of uint8_t*
int32_t blisp_device_load_boot_header(struct blisp_device* device, uint8_t* boot_header)
{
int32_t blisp_device_load_boot_header(struct blisp_device* device,
uint8_t* boot_header) {
int ret;
ret = blisp_send_command(device, 0x11, boot_header, 176, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
ret = blisp_receive_response(device, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
return 0;
return BLISP_OK;
}
int32_t blisp_device_load_segment_header(struct blisp_device* device, struct blisp_segment_header* segment_header)
{
int32_t blisp_device_load_segment_header(
struct blisp_device* device,
struct blisp_segment_header* segment_header) {
int ret;
ret = blisp_send_command(device, 0x17, segment_header, 16, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
ret = blisp_receive_response(device, true); // TODO: Handle response
if (ret < 0) return ret;
if (ret < 0)
return ret;
return 0;
return BLISP_OK;
}
int32_t blisp_device_load_segment_data(struct blisp_device* device, uint8_t* segment_data, uint32_t segment_data_length)
{
int32_t blisp_device_load_segment_data(struct blisp_device* device,
uint8_t* segment_data,
uint32_t segment_data_length) {
int ret;
ret = blisp_send_command(device, 0x18, segment_data, segment_data_length, false);
if (ret < 0) return ret;
ret = blisp_send_command(device, 0x18, segment_data, segment_data_length,
false);
if (ret < 0)
return ret;
ret = blisp_receive_response(device, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
return 0;
return BLISP_OK;
}
int32_t blisp_device_check_image(struct blisp_device* device)
{
int32_t blisp_device_check_image(struct blisp_device* device) {
int ret;
ret = blisp_send_command(device, 0x19, NULL, 0, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
ret = blisp_receive_response(device, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
return 0;
return BLISP_OK;
}
int32_t
blisp_device_write_memory(struct blisp_device* device, uint32_t address,
uint32_t value, bool wait_for_res) {
int32_t blisp_device_write_memory(struct blisp_device* device,
uint32_t address,
uint32_t value,
bool wait_for_res) {
int ret;
uint8_t payload[8];
*(uint32_t*)(payload) = address;
*(uint32_t*)(payload + 4) = value; // TODO: Endianness
ret = blisp_send_command(device, 0x50, payload, 8, true);
if (ret < 0) return ret;
if (ret < 0)
return ret;
if (wait_for_res) {
ret = blisp_receive_response(device, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
}
return 0;
return BLISP_OK;
}
int32_t blisp_device_run_image(struct blisp_device* device)
{
int32_t blisp_device_run_image(struct blisp_device* device) {
int ret;
if (device->chip->type == BLISP_CHIP_BL70X) { // ERRATA
ret = blisp_device_write_memory(device, 0x4000F100, 0x4E424845, true);
if (ret < 0) return ret;
if (ret < 0)
return ret;
ret = blisp_device_write_memory(device, 0x4000F104, 0x22010000, true);
if (ret < 0) return ret;
// ret = blisp_device_write_memory(device, 0x40000018, 0x00000000);
// if (ret < 0) return ret;
if (ret < 0)
return ret;
// ret = blisp_device_write_memory(device, 0x40000018, 0x00000000);
// if (ret < 0) return ret;
ret = blisp_device_write_memory(device, 0x40000018, 0x00000002, false);
if (ret < 0) return ret;
return 0;
if (ret < 0)
return ret;
return BLISP_OK;
}
ret = blisp_send_command(device, 0x1A, NULL, 0, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
ret = blisp_receive_response(device, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
return 0;
return BLISP_OK;
}
int32_t
blisp_device_flash_erase(struct blisp_device* device, uint32_t start_address, uint32_t end_address)
{
int32_t blisp_device_flash_erase(struct blisp_device* device,
uint32_t start_address,
uint32_t end_address) {
uint8_t payload[8];
*(uint32_t*)(payload + 0) = start_address;
*(uint32_t*)(payload + 4) = end_address;
int ret = blisp_send_command(device, 0x30, payload, 8, true);
if (ret < 0) return ret;
if (ret < 0)
return ret;
do {
ret = blisp_receive_response(device, false);
} while (ret == -3);
} while (ret == BLISP_ERR_PENDING);
return 0;
}
int32_t
blisp_device_flash_write(struct blisp_device* device, uint32_t start_address, uint8_t* payload, uint32_t payload_size)
{
int32_t blisp_device_flash_write(struct blisp_device* device,
uint32_t start_address,
uint8_t* payload,
uint32_t payload_size) {
// TODO: Add max payload size (8184?)
// TODO: Don't use malloc + add check
uint8_t* buffer = malloc(4 + payload_size); // TODO: Don't use malloc + add check
uint8_t* buffer = malloc(4 + payload_size);
*((uint32_t*)(buffer)) = start_address;
memcpy(buffer + 4, payload, payload_size);
int ret = blisp_send_command(device, 0x31, buffer, payload_size + 4, true);
if (ret < 0) goto exit1;
if (ret < 0)
goto exit1;
ret = blisp_receive_response(device, false);
exit1:
free(buffer);
return ret;
}
int32_t blisp_device_program_check(struct blisp_device* device)
{
int32_t blisp_device_program_check(struct blisp_device* device) {
int ret = blisp_send_command(device, 0x3A, NULL, 0, true);
if (ret < 0) return ret;
if (ret < 0)
return ret;
ret = blisp_receive_response(device, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
return 0;
}
int32_t blisp_device_reset(struct blisp_device* device)
{
int32_t blisp_device_reset(struct blisp_device* device) {
int ret = blisp_send_command(device, 0x21, NULL, 0, true);
if (ret < 0) return ret;
if (ret < 0)
return ret;
ret = blisp_receive_response(device, false);
if (ret < 0) return ret;
if (ret < 0)
return ret;
return 0;
return BLISP_OK;
}
void blisp_device_close(struct blisp_device* device)
{
void blisp_device_close(struct blisp_device* device) {
struct sp_port* serial_port = device->serial_port;
sp_close(serial_port);
}
+345
View File
@@ -0,0 +1,345 @@
// SPDX-License-Identifier: MIT
#include "blisp_easy.h"
#include "blisp_struct.h"
#include "blisp_util.h"
#include <inttypes.h>
#include <string.h>
static int64_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 int64_t blisp_easy_transport_size(struct blisp_easy_transport* transport) {
if (transport->type == 0) {
return transport->data.memory.data_size;
} else {
// TODO: Implement
}
}
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;
uint32_t sent_data = 0;
uint32_t buffer_size = 0;
uint8_t buffer[4092];
blisp_easy_report_progress(progress_callback, 0, segment_size);
while (sent_data < segment_size) {
buffer_size = segment_size - sent_data;
if (buffer_size > 4092) {
buffer_size = 4092;
}
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 0;
}
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;
uint32_t sent_data = 0;
uint32_t buffer_size = 0;
uint8_t buffer[8184];
blisp_easy_report_progress(progress_callback, 0, data_size);
while (sent_data < data_size) {
buffer_size = data_size - sent_data;
if (buffer_size > 2052) {
buffer_size = 2052;
}
blisp_easy_transport_read(data_transport, buffer,
buffer_size); // TODO: Error Handling
ret = blisp_device_flash_write(device, flash_location + sent_data, buffer,
buffer_size);
if (ret < BLISP_OK) {
// TODO: Error logigng: 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;
}
+15 -1
View File
@@ -1,10 +1,24 @@
// SPDX-License-Identifier: MIT
#include <malloc.h>
#include <string.h>
#include "../../data/bl60x_eflash_loader.h"
#include "blisp.h"
int64_t blisp_chip_bl60x_get_eflash_loader(uint8_t clk_type, uint8_t** firmware_buf_ptr)
{
uint8_t* firmware_buf = malloc(sizeof(bl60x_eflash_loader_bin));
memcpy(firmware_buf, bl60x_eflash_loader_bin, sizeof(bl60x_eflash_loader_bin));
*(firmware_buf + 0xE0) = 4; // TODO: 40 MHz clock
*firmware_buf_ptr = firmware_buf;
return sizeof(bl60x_eflash_loader_bin);
}
struct blisp_chip blisp_chip_bl60x = {
.type = BLISP_CHIP_BL60X,
.type_str = "bl60x",
.usb_isp_available = false,
.default_eflash_loader_xtal = "40m",
.default_xtal = "40m",
.handshake_byte_multiplier = 0.006f,
.load_eflash_loader = blisp_chip_bl60x_get_eflash_loader,
.tcm_address = 0x22010000
};
+11
View File
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
#include "blisp.h"
struct blisp_chip blisp_chip_bl61x = {
.type = BLISP_CHIP_BL61X,
.type_str = "bl808",
.usb_isp_available = true,
.default_xtal = "-", // ?
.handshake_byte_multiplier = 0.003f,
.get_eflash_loader = NULL
};
+16 -1
View File
@@ -1,10 +1,25 @@
// SPDX-License-Identifier: MIT
#include <malloc.h>
#include <string.h>
#include "../../data/bl70x_eflash_loader.h"
#include "blisp.h"
int64_t blisp_chip_bl70x_get_eflash_loader(uint8_t clk_type, uint8_t** firmware_buf_ptr)
{
uint8_t* firmware_buf = malloc(sizeof(bl70x_eflash_loader_bin));
memcpy(firmware_buf, bl70x_eflash_loader_bin, sizeof(bl70x_eflash_loader_bin));
*(firmware_buf + 0xE0) = 1; // TODO: 32 MHz clock
*firmware_buf_ptr = firmware_buf;
return sizeof(bl70x_eflash_loader_bin);
}
struct blisp_chip blisp_chip_bl70x = {
.type = BLISP_CHIP_BL70X,
.type_str = "bl70x",
.usb_isp_available = true,
.default_eflash_loader_xtal = "32m",
.default_xtal = "32m",
.handshake_byte_multiplier = 0.003f,
.load_eflash_loader = blisp_chip_bl70x_get_eflash_loader,
.tcm_address = 0x22010000
};
+11
View File
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
#include "blisp.h"
struct blisp_chip blisp_chip_bl808 = {
.type = BLISP_CHIP_BL808,
.type_str = "bl808",
.usb_isp_available = true, // TODO: Only for BL808D :-(
.default_xtal = "-", // ?
.handshake_byte_multiplier = 0.003f,
.get_eflash_loader = NULL
};
+5 -3
View File
@@ -1,6 +1,6 @@
add_subdirectory(${CMAKE_SOURCE_DIR}/vendor/argtable3 ${CMAKE_CURRENT_BINARY_DIR}/argtable3)
add_executable(blisp src/main.c src/cmd/write.c)
add_executable(blisp src/main.c src/cmd/write.c src/util.c src/common.c src/cmd/iot.c)
target_include_directories(blisp PRIVATE
"${CMAKE_SOURCE_DIR}/include"
@@ -10,6 +10,8 @@ target_link_libraries(blisp PRIVATE
argtable3
libblisp_static)
if(WIN32)
if (WIN32)
target_link_libraries(blisp PRIVATE Setupapi.lib)
endif()
elseif (APPLE)
target_link_libraries(blisp PRIVATE "-framework IOKit" "-framework CoreFoundation")
endif ()
+1
View File
@@ -13,5 +13,6 @@ struct cmd {
};
extern struct cmd cmd_write;
extern struct cmd cmd_iot;
#endif // BLISP_CMD_H
+140
View File
@@ -0,0 +1,140 @@
#include <blisp_easy.h>
#include "../cmd.h"
#include "../common.h"
#include <argtable3.h>
#define REG_EXTENDED 1
#define REG_ICASE (REG_EXTENDED << 1)
static struct arg_rex* cmd;
static struct arg_file* single_download;
static struct arg_int* single_download_location;
static struct arg_str *port_name, *chip_type; // TODO: Make this common
static struct arg_lit* reset;
static struct arg_end* end;
static void* cmd_iot_argtable[7];
void blisp_single_download()
{
struct blisp_device device;
int32_t ret;
if (blisp_common_init_device(&device, port_name, chip_type) != 0) {
return;
}
if (blisp_common_prepare_flash(&device) != 0) {
// TODO: Error handling
goto exit1;
}
FILE* data_file = fopen(single_download->filename[0], "rb");
if (data_file == NULL) {
fprintf(stderr, "Failed to open data file \"%s\".\n",
single_download->filename[0]);
goto exit1;
}
fseek(data_file, 0, SEEK_END);
int64_t data_file_size = ftell(data_file);
rewind(data_file);
printf("Erasing the area, this might take a while...\n");
ret =
blisp_device_flash_erase(&device, *single_download_location->ival,
*single_download_location->ival + data_file_size + 1);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to erase.\n");
goto exit2;
}
printf("Writing the data...\n");
struct blisp_easy_transport data_transport =
blisp_easy_transport_new_from_file(data_file);
ret = blisp_easy_flash_write(&device, &data_transport, *single_download_location->ival,
data_file_size,
blisp_common_progress_callback);
if (ret < BLISP_OK) {
fprintf(stderr, "Failed to write data to flash.\n");
goto exit2;
}
printf("Checking program...\n");
ret = blisp_device_program_check(&device);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to check program.\n");
goto exit2;
}
printf("Program OK!\n");
if (reset->count > 0) { // TODO: could be common
blisp_device_reset(&device);
printf("Resetting the chip.\n");
}
printf("Download complete!\n");
exit2:
if (data_file != NULL)
fclose(data_file);
exit1:
blisp_device_close(&device);
}
int8_t cmd_iot_args_init() {
cmd_iot_argtable[0] = cmd =
arg_rex1(NULL, NULL, "iot", NULL, REG_ICASE, NULL);
cmd_iot_argtable[1] = chip_type =
arg_str1("c", "chip", "<chip_type>", "Chip Type");
cmd_iot_argtable[2] = port_name =
arg_str0("p", "port", "<port_name>",
"Name/Path to the Serial Port (empty for search)");
cmd_iot_argtable[3] = reset =
arg_lit0(NULL, "reset", "Reset chip after write");
cmd_iot_argtable[4] = single_download =
arg_file0("s", "single-down", "<file>", "Single download file");
cmd_iot_argtable[5] = single_download_location =
arg_int0("l", "single-down-loc", NULL, "Single download offset");
cmd_iot_argtable[6] = end = arg_end(10);
if (arg_nullcheck(cmd_iot_argtable) != 0) {
fprintf(stderr, "insufficient memory\n");
return -1;
}
return 0;
}
void cmd_iot_args_print_glossary() {
fputs("Usage: blisp", stdout);
arg_print_syntax(stdout, cmd_iot_argtable, "\n");
puts("Flashes firmware as Bouffalo's DevCube");
arg_print_glossary(stdout, cmd_iot_argtable, " %-25s %s\n");
}
uint8_t cmd_iot_parse_exec(int argc, char** argv) {
int errors = arg_parse(argc, argv, cmd_iot_argtable);
if (errors == 0) {
if (single_download->count == 1 && single_download_location->count == 1) {
blisp_single_download();
return 1;
} else {
return 0;
}
} else if (cmd->count == 1) {
cmd_iot_args_print_glossary();
return 1;
}
return 0;
}
void cmd_iot_args_print_syntax() {
arg_print_syntax(stdout, cmd_iot_argtable, "\n");
}
void cmd_iot_free() {
arg_freetable(cmd_iot_argtable,
sizeof(cmd_iot_argtable) / sizeof(cmd_iot_argtable[0]));
}
struct cmd cmd_iot = {"iot", cmd_iot_args_init, cmd_iot_parse_exec,
cmd_iot_args_print_syntax, cmd_iot_free};
+66 -271
View File
@@ -1,77 +1,28 @@
// SPDX-License-Identifier: MIT
#include "../cmd.h"
#include "argtable3.h"
#include <blisp.h>
#include <string.h>
#include <inttypes.h>
#include "blisp_struct.h"
#ifdef __linux__
#include <unistd.h>
#include <linux/limits.h>
#elif defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#include <windows.h>
#define PATH_MAX MAX_PATH
#endif
#include <stdlib.h>
#include <string.h>
#include "../cmd.h"
#include "../common.h"
#include "../util.h"
#include <argtable3.h>
#include <blisp_easy.h>
#include <blisp_struct.h>
#define REG_EXTENDED 1
#define REG_ICASE (REG_EXTENDED << 1)
static struct arg_rex* cmd;
static struct arg_file* binary_to_write;
static struct arg_str* port_name, *chip_type;
static struct arg_str *port_name, *chip_type;
static struct arg_lit* reset;
static struct arg_end* end;
static void* cmd_write_argtable[6];
#ifdef __APPLE__
// Ugh. This stuff is just so messy without C++17 or Qt...
// These are not thread safe, but it doesn't place the responsibility
// to free an allocated buffer on the caller.nn
#include <string.h>
#include <assert.h>
#include <stdlib.h>
void fill_up_boot_header(struct bfl_boot_header* boot_header) {
memcpy(boot_header->magiccode, "BFNP", 4);
static void get_executable_path(char* buffer_out, uint32_t max_size) {
assert (max_size >= PATH_MAX); // n.b. 1024 on MacOS. 4K on most Linux.
char raw_path_name[PATH_MAX]; // $HOME/../../var/tmp/x
char real_path_name[PATH_MAX]; // /var/tmp/x
uint32_t raw_path_size = sizeof(raw_path_name);
if(!_NSGetExecutablePath(raw_path_name, &raw_path_size)) {
realpath(raw_path_name, real_path_name);
}
// *real_path_name is appropriately sized and null terminated.
strcpy(buffer_out, real_path_name);
}
#endif
ssize_t
get_binary_folder(char* buffer, uint32_t buffer_size) {
#ifdef __linux__
if (readlink("/proc/self/exe", buffer, buffer_size) <= 0) {
return -1;
}
char* pos = strrchr(buffer, '/');
#elif defined(__APPLE__)
get_executable_path(buffer, buffer_size);
char* pos = strrchr(buffer, '/');
#else
if (GetModuleFileName(NULL, buffer, buffer_size) <= 0) {
return -1;
}
char* pos = strrchr(buffer, '\\');
#endif
pos[0] = '\0';
return pos - buffer;
}
void fill_up_boot_header(struct bfl_boot_header* boot_header)
{
memcpy(boot_header->magiccode, "BFNP", 4);;
boot_header->revison = 0x01;
memcpy(boot_header->flashCfg.magiccode, "FCFG", 4);
boot_header->flashCfg.cfg.ioMode = 0x11;
@@ -214,168 +165,22 @@ void fill_up_boot_header(struct bfl_boot_header* boot_header)
}
void blisp_flash_firmware() {
FILE* eflash_loader_file = NULL;
if (chip_type->count == 0) {
fprintf(stderr, "Chip type is invalid.\n");
return;
}
struct blisp_chip* chip = NULL;
if (strcmp(chip_type->sval[0], "bl70x") == 0) {
chip = &blisp_chip_bl70x;
} else if (strcmp(chip_type->sval[0], "bl60x") == 0) {
chip = &blisp_chip_bl60x;
} else {
fprintf(stderr, "Chip type is invalid.\n");
return;
}
struct blisp_device device;
int32_t ret;
ret = blisp_device_init(&device, chip);
if (ret != 0) {
fprintf(stderr, "Failed to init device.\n");
if (blisp_common_init_device(&device, port_name, chip_type) != 0) {
return;
}
ret = blisp_device_open(&device, port_name->count == 1 ? port_name->sval[0] : NULL);
if (ret != 0) {
fprintf(stderr, "Failed to open device.\n");
return;
}
printf("Sending a handshake...");
ret = blisp_device_handshake(&device, false);
if (ret != 0) {
fprintf(stderr, "\nFailed to handshake with device.\n");
goto exit1;
}
printf(" OK\nGetting chip info...");
struct blisp_boot_info boot_info;
ret = blisp_device_get_boot_info(&device, &boot_info);
if (ret != 0) {
fprintf(stderr, "\nFailed to get boot info.\n");
if (blisp_common_prepare_flash(&device) != 0) {
// TODO: Error handling
goto exit1;
}
if (boot_info.boot_rom_version[0] == 255 &&
boot_info.boot_rom_version[1] == 255 &&
boot_info.boot_rom_version[2] == 255 &&
boot_info.boot_rom_version[3] == 255) {
printf(" OK\nDevice already in eflash_loader.\n");
goto eflash_loader;
}
printf(" BootROM version %d.%d.%d.%d, ChipID: %02X%02X%02X%02X%02X%02X%02X%02X\n",
boot_info.boot_rom_version[0],
boot_info.boot_rom_version[1],
boot_info.boot_rom_version[2],
boot_info.boot_rom_version[3],
boot_info.chip_id[0],
boot_info.chip_id[1],
boot_info.chip_id[2],
boot_info.chip_id[3],
boot_info.chip_id[4],
boot_info.chip_id[5],
boot_info.chip_id[6],
boot_info.chip_id[7]);
char exe_path[PATH_MAX];
char eflash_loader_path[PATH_MAX];
if (get_binary_folder(exe_path, PATH_MAX) <= 0) {
fprintf(stderr, "Failed to find executable path to search for the "
"eflash loader\n");
goto exit1;
}
snprintf(eflash_loader_path, PATH_MAX, "%s/data/%s/eflash_loader_%s.bin",
exe_path, device.chip->type_str,
device.chip->default_eflash_loader_xtal);
printf("Loading the eflash loader file from disk\n");
eflash_loader_file
= fopen(eflash_loader_path, "rb"); // TODO: Error handling
if (eflash_loader_file == NULL) {
fprintf(stderr,
"Could not open the eflash loader file from disk.\n"
"Does \"%s\" exist?\n",
eflash_loader_path);
goto exit1;
}
uint8_t
eflash_loader_header[176]; // TODO: Remap it to the boot header struct
fread(eflash_loader_header, 176, 1,
eflash_loader_file); // TODO: Error handling
printf("Loading eflash_loader...\n");
ret = blisp_device_load_boot_header(&device, eflash_loader_header);
if (ret != 0) {
fprintf(stderr, "Failed to load boot header.\n");
goto exit1;
}
{
uint32_t sent_data = 0;
uint32_t buffer_size = 0;
uint8_t buffer[4092];
// TODO: Real checking of segments count
for (uint8_t seg_index = 0; seg_index < 1; seg_index++) {
struct blisp_segment_header segment_header = { 0 };
fread(&segment_header, 16, 1,
eflash_loader_file); // TODO: Error handling
ret = blisp_device_load_segment_header(&device, &segment_header);
if (ret != 0) {
fprintf(stderr, "Failed to load segment header.\n");
goto exit1;
}
printf("Flashing %d. segment\n", seg_index + 1);
printf("0b / %" PRIu32 "b (0.00%%)\n", segment_header.length);
while (sent_data < segment_header.length) {
buffer_size = segment_header.length - sent_data;
if (buffer_size > 4092) {
buffer_size = 4092;
}
fread(buffer, buffer_size, 1, eflash_loader_file);
ret = blisp_device_load_segment_data(
&device, buffer, buffer_size); // TODO: Error handling
if (ret < 0) {
fprintf(stderr, "Failed to load segment data. (ret %d)\n", ret);
goto exit1;
}
sent_data += buffer_size;
printf("%" PRIu32 "b / %" PRIu32 "b (%.2f%%)\n", sent_data,
segment_header.length,
(((float)sent_data / (float)segment_header.length)
* 100.0f));
}
}
}
ret = blisp_device_check_image(&device);
if (ret != 0) {
fprintf(stderr, "Failed to check image.\n");
goto exit1;
}
ret = blisp_device_run_image(&device);
if (ret != 0) {
fprintf(stderr, "Failed to run image.\n");
goto exit1;
}
printf("Sending a handshake...");
ret = blisp_device_handshake(&device, true);
if (ret != 0) {
fprintf(stderr, "\nFailed to handshake with device.\n");
goto exit1;
}
printf(" OK\n");
eflash_loader:;
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]);
fprintf(stderr, "Failed to open firmware file \"%s\".\n",
binary_to_write->filename[0]);
goto exit1;
}
fseek(firmware_file, 0, SEEK_END);
@@ -386,57 +191,47 @@ eflash_loader:;
fill_up_boot_header(&boot_header);
const uint32_t firmware_base_address = 0x2000;
printf("Erasing flash, this might take a while...");
ret = blisp_device_flash_erase(&device, firmware_base_address,
firmware_base_address + firmware_file_size
+ 1);
if (ret != 0) {
fprintf(stderr, "\nFailed to erase flash.\n");
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 != 0) {
fprintf(stderr, "\nFailed to erase flash.\n");
ret =
blisp_device_flash_erase(&device, 0x0000, sizeof(struct bfl_boot_header));
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to erase flash.\n");
goto exit2;
}
printf(" OK!\nFlashing boot header...");
ret = blisp_device_flash_write(&device, 0x0000, (uint8_t*)&boot_header, sizeof(struct bfl_boot_header));
if (ret != 0) {
fprintf(stderr, "\nFailed to write boot header.\n");
printf("Flashing boot header...\n");
ret = blisp_device_flash_write(&device, 0x0000, (uint8_t*)&boot_header,
sizeof(struct bfl_boot_header));
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to write boot header.\n");
goto exit2;
}
printf(" OK!\nFlashing the firmware...\n");
{
uint32_t sent_data = 0;
uint32_t buffer_size = 0;
uint8_t buffer[8184];
printf("0b / %ldb (0.00%%)\n", firmware_file_size);
printf("Flashing the firmware...\n");
struct blisp_easy_transport data_transport =
blisp_easy_transport_new_from_file(firmware_file);
while (sent_data < firmware_file_size) {
buffer_size = firmware_file_size - sent_data;
if (buffer_size > 2052) {
buffer_size = 2052;
}
fread(buffer, buffer_size, 1, firmware_file);
ret = blisp_device_flash_write(&device, firmware_base_address + sent_data, buffer, buffer_size); // TODO: Error handling
if (ret < 0) {
fprintf(stderr, "Failed to write firmware! (ret: %d)\n", ret);
ret = blisp_easy_flash_write(&device, &data_transport, firmware_base_address,
firmware_file_size,
blisp_common_progress_callback);
if (ret < BLISP_OK) {
fprintf(stderr, "Failed to write app to flash.\n");
goto exit2;
}
sent_data += buffer_size;
printf("%" PRIu32 "b / %ldb (%.2f%%)\n", sent_data, firmware_file_size,
(((float)sent_data / (float)firmware_file_size) * 100.0f));
}
}
printf("Checking program...");
printf("Checking program...\n");
ret = blisp_device_program_check(&device);
if (ret != 0) {
fprintf(stderr, "\nFailed to check program.\n");
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to check program.\n");
goto exit2;
}
printf("OK\n");
printf("Program OK!\n");
if (reset->count > 0) {
blisp_device_reset(&device);
@@ -447,22 +242,24 @@ eflash_loader:;
printf("Flash complete!\n");
exit2:
if (firmware_file != NULL) fclose(firmware_file);
if (firmware_file != NULL)
fclose(firmware_file);
exit1:
if (eflash_loader_file != NULL) fclose(eflash_loader_file);
blisp_device_close(&device);
}
int8_t
cmd_write_args_init() {
cmd_write_argtable[0] = cmd
= arg_rex1(NULL, NULL, "write", NULL, REG_ICASE, NULL);
cmd_write_argtable[1] = chip_type = arg_str1("c", "chip", "<chip_type>", "Chip Type (bl70x)");
cmd_write_argtable[2] = port_name
= arg_str0("p", "port", "<port_name>", "Name/Path to the Serial Port (empty for search)");
cmd_write_argtable[3] = reset = arg_lit0(NULL, "reset", "Reset chip after write");
cmd_write_argtable[4] = binary_to_write
= arg_file1(NULL, NULL, "<input>", "Binary to write");
int8_t cmd_write_args_init() {
cmd_write_argtable[0] = cmd =
arg_rex1(NULL, NULL, "write", NULL, REG_ICASE, NULL);
cmd_write_argtable[1] = chip_type =
arg_str1("c", "chip", "<chip_type>", "Chip Type");
cmd_write_argtable[2] = port_name =
arg_str0("p", "port", "<port_name>",
"Name/Path to the Serial Port (empty for search)");
cmd_write_argtable[3] = reset =
arg_lit0(NULL, "reset", "Reset chip after write");
cmd_write_argtable[4] = binary_to_write =
arg_file1(NULL, NULL, "<input>", "Binary to write");
cmd_write_argtable[5] = end = arg_end(10);
if (arg_nullcheck(cmd_write_argtable) != 0) {
@@ -474,13 +271,12 @@ cmd_write_args_init() {
void cmd_write_args_print_glossary() {
fputs("Usage: blisp", stdout);
arg_print_syntax(stdout,cmd_write_argtable,"\n");
arg_print_syntax(stdout, cmd_write_argtable, "\n");
puts("Writes firmware to SPI Flash");
arg_print_glossary(stdout,cmd_write_argtable," %-25s %s\n");
arg_print_glossary(stdout, cmd_write_argtable, " %-25s %s\n");
}
uint8_t
cmd_write_parse_exec(int argc, char** argv) {
uint8_t cmd_write_parse_exec(int argc, char** argv) {
int errors = arg_parse(argc, argv, cmd_write_argtable);
if (errors == 0) {
blisp_flash_firmware(); // TODO: Error code?
@@ -493,14 +289,13 @@ cmd_write_parse_exec(int argc, char** argv) {
}
void cmd_write_args_print_syntax() {
arg_print_syntax(stdout,cmd_write_argtable,"\n");
arg_print_syntax(stdout, cmd_write_argtable, "\n");
}
void
cmd_write_free() {
void cmd_write_free() {
arg_freetable(cmd_write_argtable,
sizeof(cmd_write_argtable) / sizeof(cmd_write_argtable[0]));
}
struct cmd cmd_write
= { "write", cmd_write_args_init, cmd_write_parse_exec, cmd_write_args_print_syntax, cmd_write_free };
struct cmd cmd_write = {"write", cmd_write_args_init, cmd_write_parse_exec,
cmd_write_args_print_syntax, cmd_write_free};
+138
View File
@@ -0,0 +1,138 @@
// SPDX-License-Identifier: MIT
#include "common.h"
#include <argtable3.h>
#include <blisp.h>
#include <inttypes.h>
#include <malloc.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "blisp_easy.h"
#include "util.h"
void blisp_common_progress_callback(uint32_t current_value, uint32_t max_value) {
printf("%" PRIu32 "b / %ldb (%.2f%%)\n", current_value, max_value,
(((float)current_value / (float)max_value) * 100.0f));
}
int32_t blisp_common_init_device(struct blisp_device* device, struct arg_str* port_name, struct arg_str* chip_type)
{
if (chip_type->count == 0) {
fprintf(stderr, "Chip type is invalid.\n");
return -1;
}
struct blisp_chip* chip = NULL;
if (strcmp(chip_type->sval[0], "bl70x") == 0) {
chip = &blisp_chip_bl70x;
} else if (strcmp(chip_type->sval[0], "bl60x") == 0) {
chip = &blisp_chip_bl60x;
} else {
fprintf(stderr, "Chip type is invalid.\n");
return -1;
}
int32_t ret;
ret = blisp_device_init(device, chip);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to init device.\n");
return -1;
}
ret = blisp_device_open(device,
port_name->count == 1 ? port_name->sval[0] : NULL);
if (ret != BLISP_OK) {
fprintf(stderr, ret == BLISP_ERR_DEVICE_NOT_FOUND ? "Device not found\n" : "Failed to open device.\n");
return -1;
}
return 0;
}
/**
* Prepares chip to access flash
* this means performing handshake, and loading eflash_loader if needed.
*/
int32_t blisp_common_prepare_flash(struct blisp_device* device) {
int32_t ret = 0;
printf("Sending a handshake...\n");
ret = blisp_device_handshake(device, false);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to handshake with device.\n");
return -1;
}
printf("Handshake successful!\nGetting chip info...\n");
struct blisp_boot_info boot_info;
ret = blisp_device_get_boot_info(device, &boot_info);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to get boot info.\n");
return -1;
}
printf(
"BootROM version %d.%d.%d.%d, ChipID: "
"%02X%02X%02X%02X%02X%02X%02X%02X\n",
boot_info.boot_rom_version[0], boot_info.boot_rom_version[1],
boot_info.boot_rom_version[2], boot_info.boot_rom_version[3],
boot_info.chip_id[0], boot_info.chip_id[1], boot_info.chip_id[2],
boot_info.chip_id[3], boot_info.chip_id[4], boot_info.chip_id[5],
boot_info.chip_id[6], boot_info.chip_id[7]);
if (device->chip->load_eflash_loader == NULL) {
return 0;
}
if (boot_info.boot_rom_version[0] == 255 &&
boot_info.boot_rom_version[1] == 255 &&
boot_info.boot_rom_version[2] == 255 &&
boot_info.boot_rom_version[3] == 255) {
printf("Device already in eflash_loader.\n");
return 0;
}
uint8_t* eflash_loader_buffer = NULL;
// TODO: Error check
int64_t eflash_loader_buffer_length = device->chip->load_eflash_loader(0, &eflash_loader_buffer);
struct blisp_easy_transport eflash_loader_transport =
blisp_easy_transport_new_from_memory(eflash_loader_buffer, eflash_loader_buffer_length);
ret = blisp_easy_load_ram_app(device, &eflash_loader_transport, blisp_common_progress_callback);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to load eflash_loader, ret: %d\n", ret);
ret = -1;
goto exit1;
}
free(eflash_loader_buffer);
eflash_loader_buffer = NULL;
ret = blisp_device_check_image(device);
if (ret != 0) {
fprintf(stderr, "Failed to check image.\n");
ret = -1;
goto exit1;
}
ret = blisp_device_run_image(device);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to run image.\n");
ret = -1;
goto exit1;
}
printf("Sending a handshake...\n");
ret = blisp_device_handshake(device, true);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to handshake with device.\n");
ret = -1;
goto exit1;
}
printf("Handshake with eflash_loader successful.\n");
exit1:
if (eflash_loader_buffer != NULL)
free(eflash_loader_buffer);
return ret;
}
+13
View File
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
#ifndef BLISP_COMMON_H
#define BLISP_COMMON_H
#include <stdint.h>
#include <blisp.h>
#include <argtable3.h>
int32_t blisp_common_prepare_flash(struct blisp_device* device);
void blisp_common_progress_callback(uint32_t current_value, uint32_t max_value);
int32_t blisp_common_init_device(struct blisp_device* device, struct arg_str* port_name, struct arg_str* chip_type);
#endif // BLISP_COMMON_H
+9 -11
View File
@@ -1,13 +1,11 @@
// SPDX-License-Identifier: MIT
#include "argtable3.h"
#include "cmd.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "argtable3.h"
#include "cmd.h"
struct cmd* cmds[] = {
&cmd_write
};
struct cmd* cmds[] = {&cmd_write, &cmd_iot};
static uint8_t cmds_count = sizeof(cmds) / sizeof(cmds[0]);
@@ -18,7 +16,8 @@ static void* argtable[3];
int8_t args_init() {
argtable[0] = help = arg_lit0(NULL, "help", "print this help and exit");
argtable[1] = version = arg_lit0(NULL, "version", "print version information and exit");
argtable[1] = version =
arg_lit0(NULL, "version", "print version information and exit");
argtable[2] = end = arg_end(20);
if (arg_nullcheck(argtable) != 0) {
@@ -36,7 +35,7 @@ void print_help() {
cmds[i]->args_print_syntax();
}
fputs(" blisp", stdout);
arg_print_syntax(stdout, argtable,"\n");
arg_print_syntax(stdout, argtable, "\n");
}
int8_t args_parse_exec(int argc, char** argv) {
@@ -46,8 +45,8 @@ int8_t args_parse_exec(int argc, char** argv) {
print_help();
return 1;
} else if (version->count) {
printf("blisp 1.0.0\n");
printf("Copyright (C) 2022 Marek Kraus and PINE64 Community\n");
printf("blisp 0.0.1\n");
printf("Copyright (C) 2023 Marek Kraus and PINE64 Community\n");
return 1;
}
}
@@ -58,8 +57,7 @@ void args_free() {
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
}
int
main(int argc, char** argv) {
int main(int argc, char** argv) {
int exit_code = 0;
if (args_init() != 0) {
+44
View File
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
#include "util.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#ifdef __APPLE__
// Ugh. This stuff is just so messy without C++17 or Qt...
// These are not thread safe, but it doesn't place the responsibility
// to free an allocated buffer on the caller.nn
static void util_get_executable_path(char* buffer_out, uint32_t max_size) {
assert(max_size >= PATH_MAX); // n.b. 1024 on MacOS. 4K on most Linux.
char raw_path_name[PATH_MAX]; // $HOME/../../var/tmp/x
char real_path_name[PATH_MAX]; // /var/tmp/x
uint32_t raw_path_size = sizeof(raw_path_name);
if (!_NSGetExecutablePath(raw_path_name, &raw_path_size)) {
realpath(raw_path_name, real_path_name);
}
// *real_path_name is appropriately sized and null terminated.
strcpy(buffer_out, real_path_name);
}
#endif
ssize_t util_get_binary_folder(char* buffer, uint32_t buffer_size) {
#ifdef __linux__
if (readlink("/proc/self/exe", buffer, buffer_size) <= 0) {
return -1;
}
char* pos = strrchr(buffer, '/');
#elif defined(__APPLE__)
util_get_executable_path(buffer, buffer_size);
char* pos = strrchr(buffer, '/');
#else
if (GetModuleFileName(NULL, buffer, buffer_size) <= 0) {
return -1;
}
char* pos = strrchr(buffer, '\\');
#endif
pos[0] = '\0';
return pos - buffer;
}
+26
View File
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
#ifndef BLISP_UTIL_H
#define BLISP_UTIL_H
#include <stdint.h>
#ifdef __linux__
#include <unistd.h>
#elif defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#include <windows.h>
#define PATH_MAX MAX_PATH
#elif defined(__APPLE__)
#include <sys/syslimits.h>
#include <assert.h>
#endif
#ifdef __linux__
#include <linux/limits.h>
#endif
ssize_t util_get_binary_folder(char* buffer, uint32_t buffer_size);
#endif