Skip to content

Instantly share code, notes, and snippets.

@RecursiveG
Created January 3, 2024 06:30
Show Gist options
  • Save RecursiveG/f41bf95f913e0bb71cd226dbb62f64fd to your computer and use it in GitHub Desktop.
Save RecursiveG/f41bf95f913e0bb71cd226dbb62f64fd to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
// lrzsz doesn't work for VisionFive2's UART boot for some reason.
// Here's the hacky replacement.
// Usage: picocom -b 115200 -s "./visionfive2-sz" /dev/ttyUSB0
// Ctrl-A Ctrl-S then "recovery.bin"
#include <cinttypes>
#include <cstdio>
#include <unistd.h>
#include <fcntl.h>
#include <boost/crc.hpp>
#define BLOCK_SIZE 128
// 20MB
#define MAX_FILE_SIZE 20 * 1024 * 1024
int main(int argc, char *argv[]) {
if (argc <= 1) {
fprintf(stderr, "missing file\n");
return 1;
}
int fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open() failed");
return 1;
}
uint8_t *data = new uint8_t[MAX_FILE_SIZE];
uint32_t size = 0;
int read_size;
do {
read_size = read(fd, data + size, MAX_FILE_SIZE - size);
if (read_size < 0) {
perror("read() failed");
return 1;
}
size += read_size;
} while (read_size > 0);
if (size >= MAX_FILE_SIZE) {
fprintf(stderr, "file too large\n");
return 1;
}
fprintf(stderr, "\n");
char c = getchar();
while (c != 'C') c = getchar();
uint32_t sent = 0;
while (sent < size) {
boost::crc_optimal<16, 0x1021, 0, 0, false, false> crc;
uint8_t blockid = (sent / BLOCK_SIZE) + 1; // wrap 0xff to 0x00
uint8_t blockid_r = 255 - blockid;
uint32_t to_send = size - sent;
if (to_send > BLOCK_SIZE) to_send = BLOCK_SIZE;
uint32_t padding = BLOCK_SIZE - to_send;
putchar(0x01); // SOH
putchar(blockid);
putchar(blockid_r);
crc.process_bytes(data+sent, to_send);
for (int i = 0; i < to_send; i++) {
putchar(data[sent + i]);
}
for (int i = 0; i < padding; i++) {
crc.process_byte(0x1a);
putchar(0x1a); // CPMEOF
}
uint16_t crc_val = crc.checksum();
putchar(crc_val >> 8); // CRC hi
putchar(crc_val & 0xff); // CRC lo
fflush(stdout);
c = getchar();
while (c == 'C') c = getchar();
if (c == 0x06) {
// ACK
sent += to_send;
fprintf(stderr, "\033[G\033[KSent %d/%d", sent, size);
fflush(stderr);
} else {
// Other error
fprintf(stderr, "\nSend error %d\n", c);
}
}
fprintf(stderr, "\n");
putchar(0x04); // EOT
fflush(stdout);
c = getchar();
while (c == 'C') c = getchar();
if (c == 0x06) {
// ACK
fprintf(stderr, "Transmit success\n");
} else {
// Other error
fprintf(stderr, "Transmit error %d\n", c);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment