summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/gigabeats.c158
1 files changed, 56 insertions, 102 deletions
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 <stdio.h>
#include <stdlib.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+
+/* 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...
- */
-
- 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;
-
- /*First record*/
- record[0] = 0x88200000;
- record[1] = 4;
- record[2] = 0x1eb;
- record[3] = 0xEA0003FE;
- fwrite(record, sizeof(record), 1, out);
-
- /*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);
-
- /*Third record*/
- record[0] = 0x88200048;
- record[1] = 4;
- record[2] = 0x231;
- record[3] = 0x00CBF274;
- fwrite(record, sizeof(record), 1, out);
-
- /*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);
+ fseek(in, 0, SEEK_SET);
+ fread(buf + 43, size, 1, in);
+ fclose(in);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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);
}