From c636ef3b8f060b53ee28b4821cad9a33126ba17b Mon Sep 17 00:00:00 2001 From: logicog Date: Wed, 10 Sep 2025 19:29:27 +0200 Subject: [PATCH] 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; +}