2013-06-06 22:21:52 +00:00
# include <stdlib.h>
# include <sys/types.h>
# include <stdio.h>
# include <inttypes.h>
# include <string.h>
# include <getopt.h>
# include <unistd.h>
2017-06-18 02:21:21 +02:00
# include <errno.h>
# include <time.h>
2013-06-06 22:21:52 +00:00
# include <sys/stat.h>
# include <libgen.h>
# include "bcmalgo.h"
int flag_print_version ;
int flag_print_help ;
int flag_compress ;
uint16_t sa2100_magic = 0x2100 ;
uint16_t sa3349_magic = 0x3349 ;
uint32_t default_date = 0x00000000 ; //A long time ago in a galaxy far far away....
uint32_t default_load_address = 0x80010000 ; //The default load_address for the firmware image
static void print_help ( const char * ename )
{
printf ( " Firmware image packer and calculator for broadcom-based modems. \n " ) ;
printf ( " Part of bcm-utils package. \n " ) ;
printf ( " (c) 2009 Necromant (http://necromant.ath.cx). Thanks to Luke-jr for his initial work. \n " ) ;
printf ( " usage: %s [options] \n " , ename ) ;
printf ( " Valid options are: \n " ) ;
printf ( " --magic_bytes=value \t - specify magic bytes at the beginning of the image. default - 3349 \n " ) ;
printf ( " \t \t \t these can be sa2100 (for DPC2100 modem), \n \t \t \t sa3349 (haxorware guys use this one for some reason), \n \t \t \t or a custom hex value e.g. 0xFFFF \n " ) ;
printf ( " --compress \t \t - Make use of LZMA (weird!) compression (Doesn't work yet). \n " ) ;
printf ( " --rev_maj=value \t \t - major revision number. default 0 \n " ) ;
printf ( " --rev_min=value \t \t - minor revision number default 0 \n " ) ;
printf ( " --filename=value \t - use this filename in header instead of default (input filename) \n " ) ;
printf ( " --ldaddress=value \t - hex value of the target load address. defaults to 0x80010000 \n " ) ;
printf ( " --input_file=value \t - What file are we packing? \n " ) ;
printf ( " --output_file=value \t - What file shall we write? (default: image.bin) \n " ) ;
# ifdef _HAX0RSTYLE
printf ( " --credz \t - Give some credz! \n " ) ;
# endif
printf ( " \n " ) ;
}
2017-06-18 02:21:21 +02:00
static time_t source_date_epoch = - 1 ;
static void set_source_date_epoch ( ) {
char * env = getenv ( " SOURCE_DATE_EPOCH " ) ;
char * endptr = env ;
errno = 0 ;
if ( env & & * env ) {
source_date_epoch = strtoull ( env , & endptr , 10 ) ;
if ( errno | | ( endptr & & * endptr ! = ' \0 ' ) ) {
fprintf ( stderr , " Invalid SOURCE_DATE_EPOCH " ) ;
exit ( 1 ) ;
}
}
}
2013-06-06 22:21:52 +00:00
int main ( int argc , char * * argv )
{
if ( argc < 2 )
{
print_help ( argv [ 0 ] ) ;
}
static struct option long_options [ ] =
{
{ " magic_bytes " , required_argument , 0 , ' m ' } ,
{ " rev_maj " , required_argument , 0 , ' j ' } ,
{ " rev_min " , required_argument , 0 , ' n ' } ,
{ " ldaddress " , required_argument , 0 , ' l ' } ,
{ " filename " , required_argument , 0 , ' f ' } ,
{ " input_file " , required_argument , 0 , ' i ' } ,
{ " output_file " , required_argument , 0 , ' o ' } ,
{ " compress " , no_argument , & flag_compress , ' c ' } ,
{ " version " , no_argument , & flag_print_version , ' v ' } ,
{ " help " , no_argument , & flag_print_help , ' h ' } ,
{ 0 , 0 , 0 , 0 }
} ;
int option_index = 0 ;
int opt_result = 0 ;
char * filename = NULL ;
char * input = NULL ;
char * magic = NULL ;
char * major = NULL ;
char * minor = NULL ;
char * ldaddr = NULL ;
char * output = NULL ;
while ( opt_result > = 0 )
{
opt_result = getopt_long ( argc , argv , " m:j:n:f:i:o:vh " , long_options , & option_index ) ;
switch ( opt_result )
{
case 0 :
printf ( " o! \n " ) ;
break ;
case ' h ' :
print_help ( argv [ 0 ] ) ;
break ;
case ' l ' :
ldaddr = optarg ;
break ;
case ' f ' :
filename = optarg ;
break ;
case ' i ' :
input = optarg ;
break ;
case ' o ' :
output = optarg ;
break ;
case ' m ' :
magic = optarg ;
break ;
case ' j ' :
major = optarg ;
break ;
case ' n ' :
minor = optarg ;
break ;
}
}
if ( input = = NULL )
{
printf ( " Telepaths are still on holidays. I guess you should tell me what file should I process. \n \n " ) ;
exit ( 1 ) ;
}
if ( access ( input , R_OK ) ! = 0 )
{
printf ( " I cannot access the file %s. Is it there? Am I allowed? \n \n " , input ) ;
exit ( 1 ) ;
}
uint32_t magicnum = sa2100_magic ;
if ( magic )
{
if ( strcmp ( magic , " sa2100 " ) = = 0 ) magicnum = sa2100_magic ; else
if ( strcmp ( magic , " sa3349 " ) = = 0 ) magicnum = sa3349_magic ; else
{
sscanf ( magic , " 0x%04X " , & magicnum ) ;
}
}
unsigned int majrev = 0 ;
if ( major )
{
sscanf ( major , " %d " , & majrev ) ;
}
unsigned int minrev = 0 ;
if ( minor )
{
sscanf ( minor , " %d " , & minrev ) ;
}
uint32_t ldaddress = default_load_address ;
if ( ldaddr )
{
sscanf ( ldaddr , " 0x%08X " , & ldaddress ) ;
}
char * dupe = strdup ( input ) ;
char * fname = basename ( dupe ) ;
if ( filename )
{
fname = filename ;
}
2017-06-18 02:21:21 +02:00
time_t t = - 1 ;
set_source_date_epoch ( ) ;
if ( source_date_epoch ! = - 1 ) {
t = source_date_epoch ;
} else if ( ( time ( & t ) = = ( time_t ) ( - 1 ) ) ) {
fprintf ( stderr , " time call failed \n " ) ;
return EXIT_FAILURE ;
}
2013-06-06 22:21:52 +00:00
struct stat buf ;
stat ( input , & buf ) ;
2017-06-18 02:21:21 +02:00
ldr_header_t * head = construct_header ( magicnum , ( uint16_t ) majrev , ( uint16_t ) minrev , ( uint32_t ) t , ( uint32_t ) buf . st_size , ldaddress , fname , get_file_crc ( input ) ) ;
2013-06-06 22:21:52 +00:00
free ( dupe ) ;
//uint32_t magic, uint16_t rev_maj,uint16_t rev_min, uint32_t build_date, uint32_t filelen, uint32_t ldaddress, const char* filename, uint32_t crc
//FILE* fd = fopen ("/tftpboot/haxorware11rev32.bin","r");
//fread(head,sizeof(ldr_header_t),1,fd);
char * filebuffer = malloc ( buf . st_size + 10 ) ;
FILE * fd = fopen ( input , " r " ) ;
fread ( filebuffer , 1 , buf . st_size , fd ) ;
2020-01-11 22:57:58 +01:00
fclose ( fd ) ;
2013-06-06 22:21:52 +00:00
if ( ! output )
{
output = malloc ( strlen ( input + 5 ) ) ;
strcpy ( output , input ) ;
strcat ( output , " .bin " ) ;
}
dump_header ( head ) ;
FILE * fd_out = fopen ( output , " w+ " ) ;
if ( ! fd_out )
{
fprintf ( stderr , " Failed to open output file: %s \n " , output ) ;
2020-01-11 22:57:58 +01:00
free ( filebuffer ) ;
2013-06-06 22:21:52 +00:00
exit ( 1 ) ;
}
fwrite ( head , 1 , sizeof ( ldr_header_t ) , fd_out ) ;
fwrite ( filebuffer , 1 , buf . st_size , fd_out ) ;
printf ( " Firmware image %s is ready \n " , output ) ;
2020-01-11 22:57:58 +01:00
free ( filebuffer ) ;
fclose ( fd_out ) ;
2013-06-06 22:21:52 +00:00
return 0 ;
}