mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Merge pull request #20 from logicog/installer
WIP: Add initial installer code
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
CODE_LOCATION=0x1000
|
||||
INSTALLER_ADDRESS=0x1100
|
||||
|
||||
CC = sdcc
|
||||
CC_FLAGS = -mmcs51
|
||||
ASM = sdas8051
|
||||
AFLAGS= -plosgff
|
||||
|
||||
SRCS = installer.c
|
||||
OBJS = ${SRCS:.c=.rel}
|
||||
|
||||
all: updatebuilder rtlplayground.bin
|
||||
|
||||
updatebuilder: updatebuilder.c
|
||||
gcc $^ -o $@
|
||||
|
||||
installer.rel: installer.c
|
||||
$(CC) $(CC_FLAGS) --code-loc ${CODE_LOCATION} -c $<
|
||||
|
||||
%.rel: %.asm
|
||||
${ASM} ${AFLAGS} $^
|
||||
|
||||
%.rel: %.c
|
||||
$(CC) $(CC_FLAGS) -c $<
|
||||
|
||||
rtlinstaller.ihx: crtstart.rel $(OBJS)
|
||||
$(CC) $(CC_FLAGS) -Wl-bHOME=${INSTALLER_ADDRESS} -Wl-r -o $@ $^
|
||||
|
||||
rtlplayground.bin: rtlinstaller.ihx ../rtlplayground.bin
|
||||
cp ../rtlplayground.bin .
|
||||
./updatebuilder -i $< rtlplayground.bin
|
||||
|
||||
clean:
|
||||
rm *.ihx *.lst *.rel *.rst *.sym *.lst *.map *.mem *.lk $(OBJS) installer.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
|
||||
@@ -0,0 +1,376 @@
|
||||
#include <8051.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// #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
|
||||
#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;
|
||||
|
||||
// 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
|
||||
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 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;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
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();
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* 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;
|
||||
char line[256];
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
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 + 2 * 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 + 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;
|
||||
}
|
||||
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++;
|
||||
}
|
||||
if (!eof)
|
||||
printf("Something was wrong: EOF not found\n");
|
||||
|
||||
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