From c636ef3b8f060b53ee28b4821cad9a33126ba17b Mon Sep 17 00:00:00 2001 From: logicog Date: Wed, 10 Sep 2025 19:29:27 +0200 Subject: [PATCH 1/2] Add initial installer code --- installer/Makefile | 33 ++++++ installer/installer.c | 122 +++++++++++++++++++++ installer/updatebuilder.c | 215 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 370 insertions(+) create mode 100644 installer/Makefile create mode 100644 installer/installer.c create mode 100644 installer/updatebuilder.c diff --git a/installer/Makefile b/installer/Makefile new file mode 100644 index 0000000..72a2bfe --- /dev/null +++ b/installer/Makefile @@ -0,0 +1,33 @@ +INSTALLER_ADDRESS=0x1016 + +CC = sdcc +CC_FLAGS = -mmcs51 +ASM = sdas8051 +AFLAGS= -plosgff + +SRCS = installer.c +OBJS = ${SRCS:.c=.rel} + +all: updatebuilder rtlinstall.bin + +updatebuilder: updatebuilder.c + gcc $^ -o $@ + +%.rel: %.c + $(CC) $(CC_FLAGS) -–code-loc 0x1000 -c $< + +%.rel: %.asm + ${ASM} ${AFLAGS} $^ + +%.rel: %.c + $(CC) $(CC_FLAGS) -c $< + +rtlinstall.ihx: crtstart.rel $(OBJS) + $(CC) $(CC_FLAGS) -Wl-bHOME=${INSTALLER_ADDRESS} -Wl-r -o $@ $^ + +%.bin: %.ihx + objcopy --input-target=ihex -O binary $< $@ + +clean: + rm *.lst *.rel *.rst *.sym *.lst *.map *.mem *.lk $(OBJS) + diff --git a/installer/installer.c b/installer/installer.c new file mode 100644 index 0000000..c75373f --- /dev/null +++ b/installer/installer.c @@ -0,0 +1,122 @@ +#include <8051.h> +#include + +// #define REGDBG 1 +// #define RXTXDBG 1 + +#include "../rtl837x_sfr.h" + +#define SYS_TICK_HZ 100 +#define SERIAL_BAUD_RATE 57600 +#define CLOCK_HZ 125000000 + +// Derive the divider settings for the internal clock +#if CLOCK_HZ == 20800000 +#define CLOCK_DIV 3 +#elif CLOCK_HZ == 31250000 +#define CLOCK_DIV 2 +#elif CLOCK_HZ == 62500000 +#define CLOCK_DIV 1 +#elif CLOCK_HZ == 125000000 +#define CLOCK_DIV 0 +#endif + +volatile __xdata uint32_t ticks; +volatile __xdata uint8_t sec_counter; +volatile __xdata uint16_t sleep_ticks; + +void isr_timer0(void) __interrupt(1) +{ + TR0 = 0; // Stop timer 0 + TH0 = (0x10000 - (CLOCK_HZ / SYS_TICK_HZ / 32)) >> 8; + TL0 = (0x10000 - (CLOCK_HZ / SYS_TICK_HZ / 32)) % 0xff; + + ticks++; + if (sleep_ticks > 0) + sleep_ticks--; + sec_counter++; + + TR0 = 1; // Re-start timer 0 +} + + +void isr_ext0(void) __interrupt(0) +{ + EX0 = 0; // Disable interrupt for the moment + IT0 = 1; // Trigger on falling edge of external interrupt + EX0 = 1; // Re-enable interrupt +} + + +void isr_ext1(void) __interrupt(2) +{ + EX1 = 0; + EX1 = 1; +} + + +void write_char(char c) +{ + do { + } while (TI == 0); + TI = 0; + if (c =='\n') { + SBUF = '\r'; + do { + } while (TI == 0); + TI = 0; + } + SBUF = c; +} + + +void print_string(__code char *p) +{ + while (*p) + write_char(*p++); +} + + +void setup_serial(void) +{ + IE = 0; + + T2CON = 0x34; // Enable RCLK/TCLK (serial transmit/receive clock for T2), TR2 (Timer 2 RUN), disable CP/RL2 (bit 0) + SCON = 0x50; // Mode = 1: ASYNC 8N1 with T2 as baud-rate generator, REN_0 Receive enable + + // The RCAP2 registers contain the high/low byte that is loaded into + // timer2 when T2 overflows to 0x10000 + RCAP2H = (0x10000 - (CLOCK_HZ / SERIAL_BAUD_RATE / 32)) >> 8; + RCAP2L = (0x10000 - (CLOCK_HZ / SERIAL_BAUD_RATE / 32)) % 0xff; + + PCON |= 0x80; // Double the Baud Rate + + SCON = 0x50; + TI = 1; + RI = 0; + + ES = 1; // Enable serial IRQ +} + + +void installer(void) +{ + + CKCON = 0; // Initial Clock configuration + SFR_97 = 0; // HADDR? + + // Set in managed mode: + SFR_b9 = 0x00; + SFR_ba = 0x80; + + // Disable all interrupts (global and individually) by setting IE register (SFR A8) to 0 + IE = 0; + EIE = 0; // SFR e8: EIE. Disable all external IRQs + + // Disable all interrupts (global interrupt enable bit) + EA = 0; // SFR A8.7 / IE.7 + + setup_serial(); + while (1) + print_string("Image installer running\n"); +} diff --git a/installer/updatebuilder.c b/installer/updatebuilder.c new file mode 100644 index 0000000..a8c14ef --- /dev/null +++ b/installer/updatebuilder.c @@ -0,0 +1,215 @@ +/* + * Adds data files into specified locations of an image, optionally creates + * an index in the form of a header file + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HEADER_LENGTH 0x14 +#define HEADER_MAGIC 0x12345678 +#define HEADER_RESERVED 0x332255ff + +#define SEG_01002_LENGTH 0x2ffe +#define SEG_1C000_LENGTH 0x1000 +#define SEG_1d000_OFFSET 0x3ffe + + +// Use a 4MB buffer, the maximum flash rom size +#define BUFFER_SIZE 0x400000 +uint8_t buffer[BUFFER_SIZE]; +FILE *inptr; +int outptr; + +const char *argp_program_version = "updatebuilder 0.1"; +const char *argp_program_bug_address = ""; +static char doc[] = "Create an update image for RTL837X-based switches"; +static char args_doc[] = "INPUT_IMAGE"; +static struct argp_option options[] = { + { "magic", 'm', "MAGIC", 0, "Magic number"}, + { "reserved", 'r', "MAGIC", 0, "Reserved number"}, + { "installer", 'i', "FILE", 0, "Installer file"}, + { "output", 'o', "FILE", 0, "Output file"}, + { 0 } +}; + + +struct arguments { + uint32_t reserved; + uint32_t magic; + char *installer_file; + char *output_file; +}; + + +static error_t parse_opt(int key, char *arg, struct argp_state *state) +{ + struct arguments *arguments = state->input; + switch (key) { + case 'm': + arguments->magic = arg? strtol(arg, NULL, 16): HEADER_MAGIC; + break; + case 'r': + arguments->reserved = arg? strtol(arg, NULL, 16): HEADER_RESERVED; + break; + case 'i': + arguments->installer_file = arg; + break; + case 'o': + arguments->output_file = arg; + break; + case ARGP_KEY_END: + if(state->arg_num < 1) // Expect 1 command line argument at end + argp_usage(state); + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + + +static struct argp argp = { + options, parse_opt, args_doc, doc, 0, 0, 0 +}; + + +int main(int argc, char **argv) +{ + struct arguments arguments; + int arg_index; + char tmpfilename[] = "image_XXXXXX"; + + arguments.reserved = HEADER_RESERVED; + arguments.magic = HEADER_MAGIC; + arguments.output_file = NULL; + + argp_parse(&argp, argc, argv, 0, &arg_index, &arguments); + + memset(buffer, 0, BUFFER_SIZE); + + size_t filesize = 0; + inptr = fopen(argv[arg_index], "rb"); + if (inptr == NULL) { + printf("Cannot open input file %s\n", argv[arg_index]); + return 5; + } + + fseek(inptr, 0L, SEEK_END); + filesize = ftell(inptr); + rewind(inptr); + printf("Input file size: %ld\n", filesize); + if (filesize > BUFFER_SIZE) { + printf("File too large.\n"); + return 5; + } + size_t bytes_read = fread(buffer + SEG_1d000_OFFSET + HEADER_LENGTH, 1, sizeof(buffer), inptr); + + printf("Bytes read: %ld\n", bytes_read); + + if (bytes_read != filesize) { + printf("Error reading input file.\n"); + return 5; + } + fclose(inptr); + filesize += SEG_1d000_OFFSET + HEADER_LENGTH; + + if (arguments.installer_file) { + inptr = fopen(arguments.installer_file, "rb"); + if (inptr == NULL) { + printf("Cannot open installer file %s\n", arguments.installer_file); + return 5; + } + + fseek(inptr, 0L, SEEK_END); + size_t isize = ftell(inptr); + rewind(inptr); + printf("Installer file size: %ld\n", isize); + if (isize > SEG_01002_LENGTH) { + printf("File too large.\n"); + return 5; + } + size_t bytes_read = fread(buffer + HEADER_LENGTH, 1, sizeof(buffer), inptr); + + printf("Bytes read: %ld\n", bytes_read); + + if (bytes_read != isize) { + printf("Error reading input file.\n"); + return 5; + } + fclose(inptr); + } + + + /* + * Fill in the header with the magic, file-length, header sum, payload sum + * and the reserved bytes + */ + *(uint32_t *)(buffer + 0x00) = htonl(arguments.magic); + *(uint32_t *)(buffer + 0x04) = htonl(filesize - HEADER_LENGTH); + uint32_t sum = 0; +// for (int i = HEADER_LENGTH; i < filesize; i++) +// sum += buffer[i]; + + for (int i = HEADER_LENGTH; i < SEG_01002_LENGTH; i++) + sum += buffer[i]; + printf("Payload sum 1 is: 0x%x\n", sum); + + for (int i = HEADER_LENGTH + SEG_01002_LENGTH; i < SEG_01002_LENGTH + SEG_1C000_LENGTH + HEADER_LENGTH; i++) + sum += buffer[i]; + printf("Payload sum 2 is: 0x%x\n", sum); + + sum += 0xff * HEADER_LENGTH; + printf("Payload sum with header is: 0x%x\n", sum); + + for (int i = 2 * HEADER_LENGTH + SEG_01002_LENGTH + SEG_1C000_LENGTH; i < filesize; i++) + sum += buffer[i]; + printf("Payload sum is: 0x%x\n", sum); + *(uint32_t *)(buffer + 0x0c) = htonl(sum); + + *(uint32_t *)(buffer + 0x10) = htonl(arguments.reserved); + + sum = 0; + for (int i = 0; i < HEADER_LENGTH; i++) + sum += buffer[i]; + printf("Header checksum is: 0x%x\n", sum); + *(uint32_t *)(buffer + 0x08) = htonl(sum); + + // Second header is copy of initial one: + *(uint32_t *)(buffer + 0x00 + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x00); + *(uint32_t *)(buffer + 0x04 + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x04); + *(uint32_t *)(buffer + 0x08 + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x08); + *(uint32_t *)(buffer + 0x0c + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x0c); + *(uint32_t *)(buffer + 0x10 + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x10); + + if (filesize) { + if (arguments.output_file) + outptr = creat(arguments.output_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + else + outptr = mkstemp(tmpfilename); + + if (!outptr) { + printf("Cannot open %s\n", arguments.output_file ? arguments.output_file : tmpfilename); + return 5; + } + size_t written = write(outptr, buffer, filesize); + + if (written != filesize) { + printf("Error writing output file.\n"); + return 5; + } + close(outptr); + + if (!arguments.output_file) + rename(tmpfilename, argv[arg_index]); + } + + return 0; +} From 8aaca9ae104e5ae311b49cd95488a27af3754128 Mon Sep 17 00:00:00 2001 From: logicog Date: Thu, 11 Sep 2025 06:43:30 +0200 Subject: [PATCH 2/2] Add forgotten crtstart.asm --- installer/Makefile | 19 +-- installer/crtstart.asm | 26 ++++ installer/installer.c | 258 +++++++++++++++++++++++++++++++++++++- installer/updatebuilder.c | 90 ++++++++++--- 4 files changed, 365 insertions(+), 28 deletions(-) create mode 100644 installer/crtstart.asm diff --git a/installer/Makefile b/installer/Makefile index 72a2bfe..6e08556 100644 --- a/installer/Makefile +++ b/installer/Makefile @@ -1,4 +1,5 @@ -INSTALLER_ADDRESS=0x1016 +CODE_LOCATION=0x1000 +INSTALLER_ADDRESS=0x1100 CC = sdcc CC_FLAGS = -mmcs51 @@ -8,13 +9,13 @@ AFLAGS= -plosgff SRCS = installer.c OBJS = ${SRCS:.c=.rel} -all: updatebuilder rtlinstall.bin +all: updatebuilder rtlplayground.bin updatebuilder: updatebuilder.c gcc $^ -o $@ -%.rel: %.c - $(CC) $(CC_FLAGS) -–code-loc 0x1000 -c $< +installer.rel: installer.c + $(CC) $(CC_FLAGS) --code-loc ${CODE_LOCATION} -c $< %.rel: %.asm ${ASM} ${AFLAGS} $^ @@ -22,12 +23,12 @@ updatebuilder: updatebuilder.c %.rel: %.c $(CC) $(CC_FLAGS) -c $< -rtlinstall.ihx: crtstart.rel $(OBJS) +rtlinstaller.ihx: crtstart.rel $(OBJS) $(CC) $(CC_FLAGS) -Wl-bHOME=${INSTALLER_ADDRESS} -Wl-r -o $@ $^ -%.bin: %.ihx - objcopy --input-target=ihex -O binary $< $@ +rtlplayground.bin: rtlinstaller.ihx ../rtlplayground.bin + cp ../rtlplayground.bin . + ./updatebuilder -i $< rtlplayground.bin clean: - rm *.lst *.rel *.rst *.sym *.lst *.map *.mem *.lk $(OBJS) - + rm *.ihx *.lst *.rel *.rst *.sym *.lst *.map *.mem *.lk $(OBJS) installer.asm diff --git a/installer/crtstart.asm b/installer/crtstart.asm new file mode 100644 index 0000000..caeb20a --- /dev/null +++ b/installer/crtstart.asm @@ -0,0 +1,26 @@ + .globl __start__stack +;-------------------------------------------------------- +; Stack segment in internal ram +;-------------------------------------------------------- + .area SSEG (DATA) +__start__stack: + .ds 1 + + .area VECTOR (CODE) + .globl __interrupt_vect +__interrupt_vect: + ljmp __sdcc_gsinit_startup + 0x1000 + ljmp _isr_ext0 ; 0x03 + .ds 5 + ljmp _isr_timer0 ; 0x0b + .ds 5 + ljmp _isr_ext1 ; 0x13 + .globl __start__stack + + .area GSINIT0 (CODE) + +__sdcc_gsinit_startup: + mov sp,#__start__stack - 1 + + .area GSFINAL (CODE) + ljmp _installer diff --git a/installer/installer.c b/installer/installer.c index c75373f..c66f06f 100644 --- a/installer/installer.c +++ b/installer/installer.c @@ -4,7 +4,12 @@ // #define REGDBG 1 // #define RXTXDBG 1 +#define UPDATE_LOC 0x0001D000 +#define HEADER_LENGTH 0x14 +#define UPDATE_CODE_LOC (UPDATE_LOC + HEADER_LENGTH) + #include "../rtl837x_sfr.h" +#include "../rtl837x_regs.h" #define SYS_TICK_HZ 100 #define SERIAL_BAUD_RATE 57600 @@ -25,6 +30,12 @@ volatile __xdata uint32_t ticks; volatile __xdata uint8_t sec_counter; volatile __xdata uint16_t sleep_ticks; +// We buffer 1 sector as this is also the erase size +__xdata uint8_t buffer[0x1000]; +__xdata uint8_t dio_enabled; + +__code uint8_t * __code hex = "0123456789abcdef"; + void isr_timer0(void) __interrupt(1) { TR0 = 0; // Stop timer 0 @@ -77,6 +88,20 @@ void print_string(__code char *p) } +void print_byte(uint8_t a) +{ + write_char(hex[(a >> 4) & 0xf]); + write_char(hex[a & 0xf]); +} + +void print_short(uint16_t a) +{ + print_string("0x"); + for (signed char i = 12; i >= 0; i -= 4) { + write_char(hex[(a >> i) & 0xf]); + } +} + void setup_serial(void) { IE = 0; @@ -98,6 +123,214 @@ void setup_serial(void) ES = 1; // Enable serial IRQ } +/* + * Configure Memory Managed IO + */ +void flash_configure_mmio(void) +{ + // Set configuration for MMIO access by controller + if (dio_enabled) { + SFR_FLASH_MODEB = 0x18; + SFR_FLASH_CMD_R = 0xbb; // By default we read with Dual speed + SFR_FLASH_DUMMYCYCLES = 4; + return; + } + + SFR_FLASH_MODEB = 0x0; + SFR_FLASH_CMD_R = 0xb; // By default we read with single speed + SFR_FLASH_DUMMYCYCLES = 8; +} + + +/* + * Initializes the flash controller for programmed control + * The configuration options are not really understood, the SPI speed + * seems to be directly linked to the CPU frequency + * This configures fast single IO at 20.8 MHz when the CPU clock is at 20.8MHz + * and 62.5MHz when the CPU clock is configured at 125MHz + */ +void flash_init(uint8_t enable_dio) +{ + if (enable_dio) { + // Configure fast DIO via divider/DIO/SIOconfig = 4 and read-cmd being 0xbb (for mmio) + SFR_FLASH_CONFIG = 9; // There may be a chip-select in here + SFR_FLASH_CONF_RCMD = 0xbb; + SFR_FLASH_CONF_DIV = 4; + } else { + // Configure fast read via divider = 8 and read-cmd being 0xb (for mmio) + SFR_FLASH_CONFIG = 9; + SFR_FLASH_CONF_RCMD = 0xb; + SFR_FLASH_CONF_DIV = 8; + } + // Test Controller Busy + while(SFR_FLASH_EXEC_BUSY); + + // Write 0 to status register + SFR_FLASH_DUMMYCYCLES = 8; + SFR_FLASH_MODEB = 0; + SFR_FLASH_TCONF = 0x19; + SFR_FLASH_CMD = 1; + SFR_FLASH_DATA0 = 0; + SFR_FLASH_EXEC_GO = 1; + while(SFR_FLASH_EXEC_BUSY); + + dio_enabled = enable_dio; + flash_configure_mmio(); +} + + +uint8_t flash_read_status(void) +{ + // Test Controller Busy (we might call this directly after executing a command) + while(SFR_FLASH_EXEC_BUSY); + + // setup status read command + SFR_FLASH_TCONF = 0x11; + SFR_FLASH_CMD_R = 5; + + // execute and wait for controller done + SFR_FLASH_EXEC_GO = 1; + while(SFR_FLASH_EXEC_BUSY); + + return SFR_FLASH_DATA0; +} + + +/* + * Reads bulk data of length len from the flash memory starging at address src + * and writes the data into a buffer pointed to by dst in XMEM + */ +void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len) +{ + short status; + do { + status = flash_read_status(); + } while (status & 0x1); + + // Set fast read mode + if (dio_enabled) { + SFR_FLASH_MODEB = 0x18; + SFR_FLASH_CMD_R = 0xbb; + SFR_FLASH_DUMMYCYCLES = 4; + } else { + SFR_FLASH_MODEB = 0x0; + SFR_FLASH_CMD_R = 0xb; // Fast read + SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read? + } + // Read 4 bytes + SFR_FLASH_TCONF = 4; + while (len) { + SFR_FLASH_ADDR16 = src >> 16; + SFR_FLASH_ADDR8 = src >> 8; + SFR_FLASH_ADDR0 = src; + src += 4; + + SFR_FLASH_EXEC_GO = 1; + while(SFR_FLASH_EXEC_BUSY); + + *dst++ = SFR_FLASH_DATA0; + if (len == 1) + return; + *dst++ = SFR_FLASH_DATA8; + if (len == 2) + return; + *dst++ = SFR_FLASH_DATA16; + if (len == 3) + return; + *dst++ = SFR_FLASH_DATA24; + + len -= 4; + } +} + + +void flash_write_enable(void) +{ + short status; + + // Wait until busy bit clear + do { + status = flash_read_status(); + } while (status & 0x1); +// while (flash_read_status() & 0x1); + + SFR_FLASH_TCONF = 0x18; + SFR_FLASH_CMD = 6; +// The following is explicitly set for SIO, is this necessary?: + SFR_FLASH_DUMMYCYCLES = 0; + SFR_FLASH_MODEB = 0; + + SFR_FLASH_EXEC_GO = 1; + // Wait for write status enabled + do { + status = flash_read_status(); + } while (!(status & 0x2)); +} + + +// Erases the 4k sector in which the address lies +void flash_sector_erase(uint32_t addr) +{ + flash_write_enable(); + SFR_FLASH_TCONF = 8; + SFR_FLASH_CMD = 0x20; + + SFR_FLASH_ADDR16 = addr >> 16; + SFR_FLASH_ADDR8 = addr >> 8; + SFR_FLASH_ADDR0 = addr; + + SFR_FLASH_EXEC_GO = 1; + while (flash_read_status() & 0x1); + + flash_configure_mmio(); + +} + + +void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len) +{ + uint8_t exit_loop = 0; + + while(1) { + flash_write_enable(); + SFR_FLASH_CMD = 2; + SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is 4, 8 enables write, 0x40 is unknown + // Last transfer? + if (len < 5) { + SFR_FLASH_TCONF = 8 | len; + exit_loop = 1; + } + + SFR_FLASH_ADDR16 = addr >> 16; + SFR_FLASH_ADDR8 = addr >> 8; + SFR_FLASH_ADDR0 = addr; + SFR_FLASH_DATA0 = *ptr++; + SFR_FLASH_DATA8 = *ptr++; + SFR_FLASH_DATA16 = *ptr++; + SFR_FLASH_DATA24 = *ptr++; + + // Execute transfer, we wait for completion at top of loop + SFR_FLASH_EXEC_GO = 1; + if (exit_loop) + break; + len -= 4; + addr += 4; + } + + while (flash_read_status() & 0x1); + flash_configure_mmio(); +} + + +void reg_write(uint16_t reg_addr) +{ + /* Data to write must be in SFR A4, A5, A6, A7 */ + SFR_REG_ADDR_U16 = reg_addr; + SFR_EXEC_GO = SFR_EXEC_WRITE_REG; + do { + } while (SFR_EXEC_STATUS != 0); +} + void installer(void) { @@ -117,6 +350,27 @@ void installer(void) EA = 0; // SFR A8.7 / IE.7 setup_serial(); - while (1) - print_string("Image installer running\n"); + print_string("\nRTLPlayground installer starting...\n"); + + // Initialize flash functions with disable DIO because writing does not work otherwise + flash_init(0); + + __xdata uint32_t dest = 0x0; + __xdata uint32_t source = UPDATE_CODE_LOC; + // A 512kByte = 4MBit Flash has 128 sectors, we copy only 120 + for (uint8_t i=0; i < 120; i++) { + print_string("Moving block\n"); + flash_read_bulk(buffer, source, 0x1000); + for (uint8_t j = 0; j < 32; j++) { + write_char(' '); print_byte(buffer[j]); + } + write_char('\n'); + flash_sector_erase(dest); + flash_write_bytes(dest, buffer, 0x1000); + dest += 0x1000; + source += 0x1000; + } + print_string("Done.\n"); + print_string("Reseting now\n"); + REG_SET(RTL837X_REG_RESET, 1); } diff --git a/installer/updatebuilder.c b/installer/updatebuilder.c index a8c14ef..1ec6a15 100644 --- a/installer/updatebuilder.c +++ b/installer/updatebuilder.c @@ -27,6 +27,7 @@ uint8_t buffer[BUFFER_SIZE]; FILE *inptr; int outptr; +char line[256]; const char *argp_program_version = "updatebuilder 0.1"; const char *argp_program_bug_address = ""; @@ -49,6 +50,32 @@ struct arguments { }; +int get_byte(int pos) +{ + int c1 = line[pos]; + if (c1 >= '0' && c1 <= '9') + c1 -= '0'; + else if (c1 >= 'a' && c1 <= 'f') + c1 = c1 - 'a' + 10; + else if (c1 >= 'A' && c1 <= 'F') + c1 = c1 - 'A' + 10; + else + return -1; + + int c2 = line[pos + 1]; + if (c2 >= '0' && c2 <= '9') + c2 -= '0'; + else if (c2 >= 'a' && c2 <= 'f') + c2 = c2 - 'a' + 10; + else if (c2 >= 'A' && c2 <= 'F') + c2 = c2 - 'A' + 10; + else + return -1; + + return c1 << 4 | c2; +} + + static error_t parse_opt(int key, char *arg, struct argp_state *state) { struct arguments *arguments = state->input; @@ -110,7 +137,7 @@ int main(int argc, char **argv) printf("File too large.\n"); return 5; } - size_t bytes_read = fread(buffer + SEG_1d000_OFFSET + HEADER_LENGTH, 1, sizeof(buffer), inptr); + size_t bytes_read = fread(buffer + SEG_1d000_OFFSET + 2 * HEADER_LENGTH, 1, sizeof(buffer), inptr); printf("Bytes read: %ld\n", bytes_read); @@ -119,31 +146,60 @@ int main(int argc, char **argv) return 5; } fclose(inptr); - filesize += SEG_1d000_OFFSET + HEADER_LENGTH; + filesize += SEG_1d000_OFFSET + 2 * HEADER_LENGTH; + // Read the installer file, which is in Intel Hex format if (arguments.installer_file) { inptr = fopen(arguments.installer_file, "rb"); if (inptr == NULL) { printf("Cannot open installer file %s\n", arguments.installer_file); return 5; } - - fseek(inptr, 0L, SEEK_END); - size_t isize = ftell(inptr); - rewind(inptr); - printf("Installer file size: %ld\n", isize); - if (isize > SEG_01002_LENGTH) { - printf("File too large.\n"); - return 5; + int line_num = 1; + int address_high = 0; + bool eof = false; + while(fgets(line, 255, inptr)) { + if (line[0] != ':') { + printf("Unknwon installer file format for %s\n", arguments.installer_file); + return 5; + } + int bytes = get_byte(1); + if (bytes < 0 || bytes > 200) { + printf("Error in %s, line %d, incorrect byte number\n", arguments.installer_file, line_num); + return 5; + } + int address = (get_byte(3) *256) + get_byte(5); + if (address < 0) { + printf("Error in %s, line %d, not an address\n", arguments.installer_file, line_num); + return 5; + } + int type = get_byte(7); + if (type < 0 || type > 5) { + printf("Error in %s, line %d incorrect type\n", arguments.installer_file, line_num); + return 5; + } + if (type == 0) { + for (int i = 0; i < bytes; i++) { + int data = get_byte(9 + 2 * i); + if (data < 0) { + printf("Error in %s, line %d, illegal data byte\n", arguments.installer_file, line_num); + return 5; + } else { + address = address > 0x1000 ? address - 0x1000 : address; + buffer[address + HEADER_LENGTH + i] = data; + } + } + } else if (type == 1) { + eof = true; + printf("EOF\n"); + } else { + printf("UNKNOWN type, line %d\n", line_num); + } + line_num++; } - size_t bytes_read = fread(buffer + HEADER_LENGTH, 1, sizeof(buffer), inptr); + if (!eof) + printf("Something was wrong: EOF not found\n"); - printf("Bytes read: %ld\n", bytes_read); - - if (bytes_read != isize) { - printf("Error reading input file.\n"); - return 5; - } fclose(inptr); }