forked from len0rd/rockbox
		
	gigabeat_s_code() to actually return an error code if it fails git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21084 a1c6a512-1295-4272-9138-f99709370657
		
			
				
	
	
		
			134 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /***************************************************************************
 | |
|  *             __________               __   ___.
 | |
|  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 | |
|  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 | |
|  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 | |
|  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 | |
|  *                     \/            \/     \/    \/            \/
 | |
|  * $Id$
 | |
|  *
 | |
|  * Copyright (C) 2007 by Will Robertson
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License
 | |
|  * as published by the Free Software Foundation; either version 2
 | |
|  * of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 | |
|  * KIND, either express or implied.
 | |
|  *
 | |
|  ****************************************************************************/
 | |
| 
 | |
| #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 )
 | |
| {
 | |
|     FILE * F = fopen( filename, "rb" );
 | |
|     if( F == NULL )
 | |
|     {
 | |
|         fprintf( stderr, "Couldn't open input file %s\n", filename );
 | |
|         perror( "Error was " );
 | |
|         exit( -1 );
 | |
|     };
 | |
|     return F;
 | |
| }
 | |
| 
 | |
| static FILE * openoutfile( const char * filename )
 | |
| {
 | |
|     FILE * F = fopen( filename, "wb" );
 | |
|     if( F == NULL )
 | |
|     {
 | |
|         fprintf( stderr, "Couldn't open output file %s\n", filename );
 | |
|         perror( "Error was " );
 | |
|         exit( -1 );
 | |
|     };
 | |
|     return F;
 | |
| }
 | |
| 
 | |
| static uint32_t calc_csum(const unsigned char* pb, int cb)
 | |
| {
 | |
|     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 int size;
 | |
|     unsigned int newsize;
 | |
|     unsigned char* buf;
 | |
|     size_t rc;
 | |
| 
 | |
|     in = openinfile(infile);
 | |
|     out = openoutfile(outfile);
 | |
| 
 | |
|     /* Step 1: Load the binary file into memory */
 | |
|     fseek(in, 0, SEEK_END);
 | |
|     size = ftell(in);
 | |
| 
 | |
|     /* 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 operation. Aborting.\n" );
 | |
|         return 1;
 | |
|     }
 | |
|     fseek(in, 0, SEEK_SET);
 | |
|     rc = fread(buf + 43, 1, size, in);
 | |
|     fclose(in);
 | |
| 
 | |
|     if(rc != size) {
 | |
|         /* failed to read the wanted amount */
 | |
|         fprintf(stderr, "Failed reading from %s.\n", infile);
 | |
|         return 2;
 | |
|     }
 | |
|     /* Step 2: Create the file header */
 | |
|     sprintf((char *)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" );
 | |
| 
 | |
|     return(0);
 | |
| }
 |