mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Add initial installer code
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
#include <8051.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// #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");
|
||||
}
|
||||
@@ -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 <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <argp.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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 = "<git@logicog.de>";
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user