parent
027c3b3e1d
commit
39fa664f99
@ -1,248 +0,0 @@ |
||||
#include <stdlib.h> |
||||
#include <sys/types.h> |
||||
#include <stdio.h> |
||||
#include <inttypes.h> |
||||
#include <string.h> |
||||
#include <getopt.h> |
||||
#include <unistd.h> |
||||
#include <sys/time.h> |
||||
#include <sys/stat.h> |
||||
#include "bcmalgo.h" |
||||
|
||||
|
||||
#define UTIL_VERSION "0.1" |
||||
#define ENDIAN_REVERSE_NEEDED |
||||
|
||||
uint32_t reverse_endian32 ( uint32_t data ) |
||||
{ |
||||
#ifdef ENDIAN_REVERSE_NEEDED |
||||
return 0 | ( data & 0x000000ff ) << 24 |
||||
| ( data & 0x0000ff00 ) << 8 |
||||
| ( data & 0x00ff0000 ) >> 8 |
||||
| ( data & 0xff000000 ) >> 24; |
||||
#else |
||||
return data; |
||||
#endif |
||||
} |
||||
|
||||
uint16_t reverse_endian16 ( uint16_t data ) |
||||
{ |
||||
#ifdef ENDIAN_REVERSE_NEEDED |
||||
return 0 | ( data & 0x00ff ) << 8 |
||||
| ( data & 0xff00 ) >> 8; |
||||
#else |
||||
return data; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
|
||||
uint32_t get_buffer_crc ( char* filebuffer,size_t size ) |
||||
{ |
||||
|
||||
long crc=0xffffffffL; |
||||
long crcxor = 0xffffffffL; |
||||
long num4 = 0xffffffffL; |
||||
long num5 = size; |
||||
long num6 = 0x4c11db7L; |
||||
long num7 = 0x80000000L; |
||||
int i; |
||||
long j; |
||||
for ( i = 0; i < ( num5 ); i++ ) |
||||
{ |
||||
long num2 = filebuffer[i]; |
||||
for ( j = 0x80L; j != 0L; j = j >> 1 ) |
||||
{ |
||||
long num3 = crc & num7; |
||||
crc = crc << 1; |
||||
if ( ( num2 & j ) != 0L ) |
||||
{ |
||||
num3 ^= num7; |
||||
} |
||||
if ( num3 != 0L ) |
||||
{ |
||||
crc ^= num6; |
||||
} |
||||
} |
||||
} |
||||
crc ^= crcxor; |
||||
crc &= num4; |
||||
|
||||
uint8_t b1 = ( uint8_t ) ( ( crc & -16777216L ) >> 0x18 ); |
||||
uint8_t b2 = ( uint8_t ) ( ( crc & 0xff0000L ) >> 0x10 ); |
||||
uint8_t b3 = ( uint8_t ) ( ( crc & 0xff00L ) >> 8 ); |
||||
uint8_t b4 = ( uint8_t ) ( crc & 0xffL ); |
||||
int32_t crc_result = ( b1 | b2 << 8| b3 << 16| b4 <<24 ); |
||||
return reverse_endian32 ( crc_result ); |
||||
} |
||||
|
||||
//Thnx to Vector for the algo.
|
||||
uint32_t get_file_crc ( char* filename ) |
||||
{ |
||||
struct stat buf; |
||||
stat ( filename,&buf ); |
||||
char* filebuffer = malloc ( buf.st_size+10 ); |
||||
FILE* fd = fopen ( filename,"r" ); |
||||
fread ( filebuffer, 1, buf.st_size,fd ); |
||||
fclose ( fd ); |
||||
uint32_t crc = get_buffer_crc ( filebuffer,buf.st_size ); |
||||
free ( filebuffer ); |
||||
return crc; |
||||
} |
||||
|
||||
|
||||
|
||||
uint16_t get_hcs ( ldr_header_t* hd ) |
||||
{ |
||||
uint8_t* head = ( uint8_t* ) hd; |
||||
uint8_t hcs_minor; |
||||
uint8_t hcs_major; |
||||
uint16_t n = 0xffff; |
||||
uint16_t m = 0; |
||||
int state = 0; |
||||
int i,j; |
||||
for ( i = 0; i < 0x54; i++ ) |
||||
{ |
||||
uint16_t m = head[i]; |
||||
m = m << 8; |
||||
for ( j = 0; j < 8; j++ ) |
||||
{ |
||||
if ( ( ( n ^ m ) & 0x8000 ) == 0 ) |
||||
{ |
||||
state = 0; |
||||
} |
||||
else |
||||
{ |
||||
state = 1; |
||||
} |
||||
n = n << 1; |
||||
if ( state ) |
||||
{ |
||||
n ^= 0x1021; |
||||
} |
||||
m = m << 1; |
||||
} |
||||
n &= 0xffff; |
||||
} |
||||
n ^= 0xffff; |
||||
hcs_major = ( uint8_t ) ( ( n & 0xff00 ) >> 8 ); |
||||
hcs_minor = ( uint8_t ) ( n & 0xff ); |
||||
uint16_t hcs = hcs_major <<8 | hcs_minor; |
||||
return hcs; |
||||
} |
||||
|
||||
ldr_header_t* construct_header ( 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_data ) |
||||
{ |
||||
ldr_header_t* hd = malloc ( sizeof ( ldr_header_t ) ); |
||||
hd->magic=reverse_endian16 ( magic ); |
||||
hd->control=0; //FixMe: Make use of it once compression is around
|
||||
hd->rev_min = reverse_endian16 ( rev_min ); |
||||
hd->rev_maj = reverse_endian16 ( rev_maj ); |
||||
hd->build_date = reverse_endian32 ( build_date ); |
||||
hd->filelen = reverse_endian32 ( filelen ); |
||||
hd->ldaddress = reverse_endian32 ( ldaddress ); |
||||
printf ( "Creating header for %s...\n", filename ); |
||||
if ( strlen ( filename ) >63 ) |
||||
{ |
||||
printf ( "[!] Filename too long - stripping it to 63 bytes.\n" ); |
||||
strncpy ( ( char* ) &hd->filename, filename, 63 ); |
||||
hd->filename[63]=0x00; |
||||
} |
||||
else |
||||
{ |
||||
strcpy ( ( char* ) &hd->filename, filename ); |
||||
} |
||||
hd->crc=reverse_endian32 ( crc_data ); |
||||
hd->hcs = reverse_endian16 ( get_hcs ( hd ) ); |
||||
return hd; |
||||
} |
||||
|
||||
static char control_unc[] = "Uncompressed"; |
||||
static char control_lz[] = "LZRW1/KH"; |
||||
static char control_mlzo[] = "mini-LZO"; |
||||
static char control_nrv[] = "NRV2D99 [Bootloader?]"; |
||||
static char control_nstdlzma[] = "(non-standard) LZMA"; |
||||
static char control_unk[] = "Unknown"; |
||||
char* get_control_info ( uint16_t control ) |
||||
{ |
||||
control = reverse_endian16 ( control ); |
||||
switch ( control ) |
||||
{ |
||||
case 0: |
||||
return control_unc; |
||||
break; |
||||
case 1: |
||||
return control_lz; |
||||
break; |
||||
case 2: |
||||
return control_mlzo; |
||||
break; |
||||
case 3: |
||||
return control_unc; |
||||
break; |
||||
case 4: |
||||
return control_nrv; |
||||
break; |
||||
case 5: |
||||
return control_nstdlzma; |
||||
break; |
||||
case 6: |
||||
return control_unc; |
||||
break; |
||||
case 7: |
||||
return control_unc; |
||||
break; |
||||
default: |
||||
return control_unk; |
||||
break; |
||||
} |
||||
|
||||
} |
||||
|
||||
int dump_header ( ldr_header_t* hd ) |
||||
{ |
||||
printf ( "=== Header Information ===\n" ); |
||||
printf ( "Header magic:\t0x%04X\n",reverse_endian16 ( hd->magic ) ); |
||||
printf ( "Control:\t0x%04X (%s)\n",reverse_endian16 ( hd->control ), get_control_info ( hd->control ) ); |
||||
printf ( "Major rev. :\t0x%04X\n",reverse_endian16 ( hd->rev_maj ) ); |
||||
printf ( "Minor rev. :\t0x%04X\n",reverse_endian16 ( hd->rev_min ) ); |
||||
printf ( "File name :\t%s\n", ( char* ) &hd->filename ); |
||||
printf ( "File length:\t%d bytes\n", reverse_endian32 ( hd->filelen ) ); |
||||
printf ( "Build time:\t0x%08X //FixMe: print in human-readable form\n", reverse_endian32 ( hd->build_date ) ); //FixMe:
|
||||
printf ( "HCS:\t\t0x%04X ",reverse_endian16 ( hd->hcs ) ); |
||||
uint16_t hcs = get_hcs ( hd ); |
||||
int ret=0; |
||||
if ( hcs ==reverse_endian16 ( hd->hcs ) ) |
||||
{ |
||||
printf ( "(OK!)\n" ); |
||||
} |
||||
else |
||||
{ |
||||
printf ( "(ERROR! expected 0x%04X)\n",hcs ); |
||||
ret=1; |
||||
} |
||||
//printf("HCS:\t0x%02X",reverse_endian32(hd->hcs));
|
||||
printf ( "Load address:\t0x%08X\n", reverse_endian32 ( hd->ldaddress ) ); //FixMe:
|
||||
printf ( "HNW:\t\t0x%04X\n",reverse_endian16 ( hd->her_znaet_chto ) ); //Hell knows what
|
||||
printf ( "CRC:\t\t0x%08X\n",reverse_endian32 ( hd->crc ) ); |
||||
printf ( "=== Binary Header Dump===\n" ); |
||||
int i,j; |
||||
uint8_t* head = ( uint8_t* ) hd; |
||||
for ( i=0;i<=sizeof ( ldr_header_t );i++ ) |
||||
{ |
||||
if ( i % 8==0 ) |
||||
printf ( "\n" ); |
||||
printf ( "0x%02x ",head[i] ); |
||||
} |
||||
printf ( "\n\n== End Of Header dump ==\n" ); |
||||
return ret; |
||||
} |
||||
|
||||
|
||||
void print_copyright() |
||||
{ |
||||
printf ( "Part of bcm-utils package ver. " UTIL_VERSION " \n" ); |
||||
printf ( "Copyright (C) 2009 Andrew 'Necromant' Andrianov\n" |
||||
"This is free software, and you are welcome to redistribute it\n" |
||||
"under certain conditions. See COPYING for details\n" ); |
||||
} |
@ -1,83 +0,0 @@ |
||||
#ifndef bcmutils_H |
||||
#define bcmutils_H |
||||
|
||||
typedef struct |
||||
{ |
||||
uint16_t magic; |
||||
uint16_t control; |
||||
uint16_t rev_maj; |
||||
uint16_t rev_min; |
||||
uint32_t build_date; |
||||
uint32_t filelen; |
||||
uint32_t ldaddress; |
||||
char filename[64]; |
||||
uint16_t hcs; |
||||
uint16_t her_znaet_chto; //v dushe ne ebu
|
||||
uint32_t crc; |
||||
} ldr_header_t; |
||||
|
||||
|
||||
/**
|
||||
* Reverses endianess of a 32bit int, if the ENDIAN_REVERSE_NEEDED defined at compile-time |
||||
* @param data |
||||
* @return |
||||
*/ |
||||
uint32_t reverse_endian32 ( uint32_t data ); |
||||
|
||||
/**
|
||||
* Reverses endianess of a 16bit int, if the ENDIAN_REVERSE_NEEDED defined at compile-time |
||||
* @param data |
||||
* @return |
||||
*/ |
||||
uint16_t reverse_endian16 ( uint16_t data ); |
||||
/**
|
||||
* Calculates the strange crc (used by bcm modems) of the file. Thnx fly out to Vector for the algorithm. |
||||
* @param filename |
||||
* @return |
||||
*/ |
||||
uint32_t get_file_crc ( char* filename ); |
||||
|
||||
/**
|
||||
* Calculates HCS of the header. |
||||
* @param hd |
||||
* @return |
||||
*/ |
||||
uint16_t get_hcs ( ldr_header_t* hd ); |
||||
|
||||
/**
|
||||
* Constructs the header of the image with the information given It also automagically calculates HCS and writes it there. |
||||
* @param magic - magic device bytes |
||||
* @param rev_maj - major revision |
||||
* @param rev_min - minor revision |
||||
* @param build_date - build date (seconds from EPOCH UTC) |
||||
* @param filelen - file length in bytes |
||||
* @param ldaddress - Load adress |
||||
* @param filename - filename |
||||
* @param crc_data - the crc of the data |
||||
* @return |
||||
*/ |
||||
ldr_header_t* construct_header ( 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_data ); |
||||
|
||||
/**
|
||||
* Dumps header information to stdout. |
||||
* @param hd |
||||
*/ |
||||
int dump_header ( ldr_header_t* hd ); |
||||
|
||||
|
||||
/**
|
||||
* Returns a null terminated string describing what the control number meens |
||||
* DO NOT FREE IT!!! |
||||
* @param control |
||||
* @return |
||||
*/ |
||||
char* get_control_info ( uint16_t control ); |
||||
#endif |
||||
|
||||
/**
|
||||
* Calculates bcmCRC of a data buffer. |
||||
* @param filebuffer - pointer to buffer |
||||
* @param size - buffer size |
||||
* @return |
||||
*/ |
||||
uint32_t get_buffer_crc ( char* filebuffer, size_t size ); |
@ -1,181 +0,0 @@ |
||||
#include <stdlib.h> |
||||
#include <sys/types.h> |
||||
#include <stdio.h> |
||||
#include <inttypes.h> |
||||
#include <string.h> |
||||
#include <getopt.h> |
||||
#include <unistd.h> |
||||
#include <sys/time.h> |
||||
#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" ); |
||||
} |
||||
|
||||
|
||||
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; |
||||
} |
||||
struct timeval tm; |
||||
gettimeofday ( &tm,NULL ); |
||||
struct stat buf; |
||||
stat ( input,&buf ); |
||||
ldr_header_t* head = construct_header ( magicnum, (uint16_t) majrev, (uint16_t) minrev, ( uint32_t ) tm.tv_sec, ( uint32_t ) buf.st_size, ldaddress, fname, get_file_crc ( input ) ); |
||||
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 ); |
||||
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); |
||||
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); |
||||
return 0; |
||||
} |
Loading…
Reference in new issue