diff --git a/tools/gigabeats.c b/tools/gigabeats.c index 0d60eae781..c109d6ad1c 100644 --- a/tools/gigabeats.c +++ b/tools/gigabeats.c @@ -19,6 +19,12 @@ #include #include +#include +#include + +/* Entry point (and load address) for the main Rockbox bootloader */ +#define BL_ENTRY_POINT 0x8a000000 + static FILE * openinfile( const char * filename ) { @@ -44,128 +50,76 @@ static FILE * openoutfile( const char * filename ) return F; }; -unsigned long calc_csum(const unsigned char* pb, int cb) +static uint32_t calc_csum(const unsigned char* pb, int cb) { - unsigned long l = 0; + uint32_t l = 0; while (cb--) l += *pb++; return l; } +static void put_uint32le(uint32_t x, unsigned char* p) +{ + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} + int gigabeat_s_code(char *infile, char *outfile) { FILE *in, *out; - unsigned long size = 0; - unsigned long data; - int imagelength; + unsigned int size; + unsigned int newsize; + unsigned char* buf; in = openinfile(infile); out = openoutfile(outfile); + /* Step 1: Load the binary file into memory */ fseek(in, 0, SEEK_END); size = ftell(in); - fseek(in, 0, SEEK_SET); - unsigned long *binptr = malloc(size); - if(binptr == NULL) { + + /* 15 bytes for header, 16 for signature bypass, + * 12 for record header, 12 for footer */ + newsize = 15 + 16 + 12 + size + 12; + buf = malloc(newsize); + if(buf == NULL) { fprintf(stderr, "Not enough memory to perform the requested operation. Aborting.\n" ); return 0; } - fread(binptr, size/4, 4, in); - /* 15 bytes for header, three 12 byte headers, the data for the first three - * records, 12 byte header for code, code and the 12 byte footer - * However, the original nk.bin's length doesn't correspond with - * the length of the file, so I don't know what's up... - */ + fseek(in, 0, SEEK_SET); + fread(buf + 43, size, 1, in); + fclose(in); - unsigned long header[2]; - header[0] = 0x88200000; - /* header[1] = 15 + 12 + 4 + 12 + 8 + 12 + 4 + 12 + size + 12; */ - header[1] = 0xCC0CD8; /* The bootloader checks this value and compares */ - fwrite("B000FF\n", 7, 1, out); - fwrite(header, sizeof(header), 1, out); - - unsigned long record[4]; - unsigned long extra; + /* Step 2: Create the file header */ + sprintf(buf, "B000FF\n"); + put_uint32le(0x88200000, buf+7); + /* If the value below is too small, the update will attempt to flash. + * Be careful when changing this (leaving it as is won't cause issues) */ + put_uint32le(0xCC0CD8, buf+11); - /*First record*/ - record[0] = 0x88200000; - record[1] = 4; - record[2] = 0x1eb; - record[3] = 0xEA0003FE; - fwrite(record, sizeof(record), 1, out); + /* Step 3: Add the signature bypass record */ + put_uint32le(0x88065A10, buf+15); + put_uint32le(4, buf+19); + put_uint32le(0xE3A00001, buf+27); + put_uint32le(calc_csum(buf+27,4), buf+23); - /*Second record*/ - record[0] = 0x88200040; - record[1] = 8; - record[2] = 0x3e9; - record[3] = 0x43454345; - extra = 0x88EBF274; - fwrite(record, sizeof(record), 1, out); - fwrite(&extra, sizeof(extra), 1, out); + /* Step 4: Create a record for the actual code */ + put_uint32le(BL_ENTRY_POINT, buf+31); + put_uint32le(size, buf+35); + put_uint32le(calc_csum(buf + 43, size), buf+39); - /*Third record*/ - record[0] = 0x88200048; - record[1] = 4; - record[2] = 0x231; - record[3] = 0x00CBF274; - fwrite(record, sizeof(record), 1, out); + /* Step 5: Write the footer */ + put_uint32le(0, buf+newsize-12); + put_uint32le(BL_ENTRY_POINT, buf+newsize-8); + put_uint32le(0, buf+newsize-4); - /*Signature bypass record*/ - unsigned long magic = 0xE3A00001; - record[0] = 0x88065A10; - record[1] = 4; - record[2] = calc_csum((unsigned char*)&magic,4); - record[3] = magic; - fwrite(record, sizeof(record), 1, out); - - /*The actual code*/ - header[0] = 0x88201000; - header[1] = size; - extra = calc_csum((unsigned char*)binptr, size); - fwrite(header, sizeof(header), 1, out); - fwrite(&extra, sizeof(extra), 1, out); - fwrite(binptr, size, 1, out); - - /* Table of contents. It's a start, but it still won't boot. - * Looks like it needs the file/module info as well... */ - binptr[0] = 0x02000000; - binptr[1] = 0x02000000; - binptr[2] = 0x88040000; - binptr[3] = 0x88076338; - binptr[4] = 0x1; - binptr[5] = 0x88080000; - binptr[6] = 0x8809C000; - binptr[7] = 0x88100000; - binptr[8] = 0x0; - binptr[9] = 0x0; - binptr[10] = 0x0; - binptr[11] = 0x0; - binptr[12] = 0x0; - binptr[13] = 0x0; - binptr[14] = 0x80808080; - binptr[15] = 0x0; - binptr[16] = 0x0; - binptr[17] = 0x201C2; - binptr[18] = 0x88050940; - binptr[19] = 0x0; - binptr[20] = 0x0; - header[0] = 0x88EBF274; - header[1] = 0x54; - extra = calc_csum((unsigned char*)binptr, 84); - fwrite(header, sizeof(header), 1, out); - fwrite(&extra, sizeof(extra), 1, out); - fwrite(binptr, 84, 1, out); - - /*The footer*/ - header[0] = 0; - header[1] = 0x88201000; - extra = 0; - fwrite(header, sizeof(header), 1, out); - fwrite(&extra, sizeof(extra), 1, out); + /* Step 6: Write the resulting file */ + fwrite(buf, newsize, 1, out); + fclose(out); fprintf(stderr, "File processed successfully\n" ); - fclose(in); - fclose(out); return(0); }