blob: af279d548548097af1c5214b4e23703ac284f764 [file] [log] [blame]
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <libgen.h>
#include <getopt.h>
#define NETX_IDENTIFICATION 0x5854454E /* Valid signature 'N' 'E' 'T' 'X' */
#define MAGICCOOKIE_8BIT 0xF8BEAF08 /* Cookie used for 8Bit Flashes */
#define MAGICCOOKIE_16BIT 0xF8BEAF16 /* Cookie used for 16Bit Flashes */
#define MAGICCOOKIE_32BIT 0xF8BEAF32 /* Cookie used for 32Bit Flashes */
struct netx_block_normal {
uint32_t sdram_general_ctrl; /* SDRam General control value */
uint32_t sdram_timing_ctrl; /* SDRam Timing control register value */
uint32_t reserved[3];
};
struct netx_block_expbus {
uint32_t exp_bus_reg; /* Expension bus register value (EXPBus Bootmode) */
uint32_t io_reg_mode0; /* IORegmode0 register value (EXPBus Bootmode) */
uint32_t io_reg_mode1; /* IORegmode1 register value (EXPBus Bootmode) */
uint32_t if_conf1; /* IfConfig1 register value (EXPBus Bootmode) */
uint32_t if_conf2; /* IfConfig2 register value (EXPBus Bootmode) */
};
struct netx_bootblock {
uint32_t cookie; /* Cookie identifying bus width and valid bootblock */
union {
uint32_t mem_ctrl; /* Parallel/Serial Flash Mode for setting up timing parameters */
uint32_t speed; /* I2C/SPI Mode for identifying speed of device */
uint32_t reserved; /* PCI/DPM mode */
} ctrl;
uint32_t appl_entrypoint; /* Entrypoint to application after relocation */
uint32_t appl_checksum; /* Checksum of application (DWORD sum over application) */
uint32_t appl_size; /* size of application in DWORDs */
uint32_t appl_start_addr; /* Relocation address of application */
uint32_t signature; /* Bootblock signature ('NETX') */
union {
struct netx_block_normal normal;
struct netx_block_expbus expbus;
} config;
uint32_t misc_asic_ctrl; /* ASIC CTRL register value */
uint32_t reserved[2];
uint32_t boot_checksum; /* Bootblock checksum (complement of DWORD sum over bootblock) */
};
void print_usage(char *prg)
{
fprintf(stderr, "Usage: %s [Options]\n"
"Options:\n"
" -i, --infile=FILE input file\n"
" -o --outfile=FILE outputfile\n"
" -m --memctrl=REG Memory Control register value\n"
" -s, --sdramctrl=REG SDRAM Control regster value\n"
" -t, --sdramtimctrl=REG SDRAM Timing Control regster value\n"
" -e, --entrypoint=ADR Application entrypoint\n"
" -c, --cookie=BITS Cookie to use (8|16|32)\n"
" -h, --help this help\n",
prg);
}
int main(int argc, char *argv[])
{
struct netx_bootblock *nb;
int fd;
struct stat s;
int opt;
unsigned char *buf;
int bytes, err, barebox_size, ofs, i;
uint32_t *ptr;
uint32_t checksum = 0;
uint32_t memctrl = 0, sdramctrl = 0, sdramtimctrl = 0, entrypoint = 0, cookie = 0;
char *infile = NULL, *outfile = NULL;
struct option long_options[] = {
{ "help", no_argument, 0, 'h' },
{ "infile", required_argument, 0, 'i'},
{ "outfile", required_argument, 0, 'o'},
{ "memctrl", required_argument, 0, 'm'},
{ "sdramctrl", required_argument, 0, 's' },
{ "sdramtimctrl", required_argument, 0, 't' },
{ "entrypoint", required_argument, 0, 'e' },
{ "cookie", required_argument, 0 , 'c' },
{ 0, 0, 0, 0},
};
while ((opt = getopt_long(argc, argv, "hi:o:m:s:t:e:c:", long_options, NULL)) != -1) {
switch (opt) {
case 'h':
print_usage(basename(argv[0]));
exit(0);
case 'i':
infile = optarg;
break;
case 'o':
outfile = optarg;
break;
case 'm':
memctrl = strtoul(optarg, NULL, 0);
break;
case 's':
sdramctrl = strtoul(optarg, NULL, 0);
break;
case 't':
sdramtimctrl = strtoul(optarg, NULL, 0);
break;
case 'e':
entrypoint = strtoul(optarg, NULL, 0);
break;
case 'c':
cookie = strtoul(optarg, NULL, 0);
break;
}
}
if(!infile) {
printf("no input filename supplied\n");
exit(1);
}
if(!outfile) {
printf("no outpu filename supplied\n");
exit(1);
}
switch (cookie) {
case 8:
cookie = MAGICCOOKIE_8BIT;
break;
case 16:
cookie = MAGICCOOKIE_16BIT;
break;
case 32:
cookie = MAGICCOOKIE_32BIT;
break;
default:
fprintf(stderr, "invalid coookie size %d\n",cookie);
}
fd = open(infile,O_RDONLY);
if(fd < 0) {
perror("open");
exit(1);
}
if( fstat(fd, &s) < 0) {
perror("fstat");
exit(1);
}
barebox_size = s.st_size;
printf("found barebox image. size: %d bytes. Using entrypoint 0x%08x\n",barebox_size,entrypoint);
buf = malloc(barebox_size + sizeof(struct netx_bootblock) + 4);
if(!buf) {
perror("malloc");
exit(1);
}
memset(buf, 0, barebox_size + sizeof(struct netx_bootblock) + 4);
nb = (struct netx_bootblock *)buf;
nb->cookie = cookie;
nb->ctrl.mem_ctrl = memctrl;
nb->appl_entrypoint = entrypoint;
nb->appl_size = (barebox_size >> 2);
nb->appl_start_addr = entrypoint;
nb->signature = NETX_IDENTIFICATION;
nb->config.normal.sdram_general_ctrl = sdramctrl;
nb->config.normal.sdram_timing_ctrl = sdramtimctrl;
ofs = sizeof(struct netx_bootblock);
bytes = barebox_size;
while(bytes) {
err = read(fd, buf + ofs, bytes);
if( err < 0 ) {
perror("read");
exit(1);
}
bytes -= err;
ofs += err;
}
close(fd);
/* calculate application checksum */
ptr = (uint32_t *)(buf + sizeof(struct netx_bootblock));
checksum = 0;
for( i = 0; i < nb->appl_size; i++) {
checksum += *ptr++;
}
nb->appl_checksum = checksum;
printf("application checksum: 0x%08x\n",nb->appl_checksum);
/* calculate bootblock checksum */
ptr = (uint32_t *)buf;
checksum = 0;
for( i = 0; i < (sizeof(struct netx_bootblock) >> 2); i++)
checksum += *ptr++;
nb->boot_checksum = -1 * checksum;
fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if(fd < 0) {
perror("open");
exit(1);
}
bytes = barebox_size + sizeof(struct netx_bootblock);
ofs = 0;
while(bytes) {
err = write(fd, buf + ofs, bytes);
if( err < 0) {
perror("write");
exit(1);
}
bytes -= err;
ofs += err;
}
close(fd);
free(buf);
return 0;
}