@ -55,6 +55,7 @@ typedef enum {
} op_mode ;
static firmware_type FIRMWARE_TYPES [ ] = {
{ 0x00 , " combo " } , /* Used for new capwap-included style header */
{ 0x01 , " bootloader " } ,
{ 0x02 , " kernel " } ,
{ 0x03 , " kernelapp " } ,
@ -70,6 +71,21 @@ static firmware_type FIRMWARE_TYPES[] = {
{ 0x0c , " langpack (D-Link) " }
} ;
# define MOD_DEFAULT 0x616C6C00
# define SKU_DEFAULT 0x0
# define DATECODE_NONE 0xFFFFFFFF
# define FIRMWARE_TYPE_NONE 0xFF
struct capwap_header {
uint32_t mod ;
uint32_t sku ;
uint32_t firmware_ver [ 3 ] ;
uint32_t datecode ;
uint32_t capwap_ver [ 3 ] ;
uint32_t model_size ;
uint8_t model [ ] ;
} ;
static long get_file_size ( const char * filename )
{
FILE * fp_file ;
@ -84,15 +100,14 @@ static long get_file_size(const char *filename)
return result ;
}
static int header_checksum ( void * data , in t len )
static int header_checksum ( void * data , size_ t len )
{
int i ;
int sum ;
int sum = 0 ; /* shouldn't this be unsigned ? */
size_t i ;
sum = 0 ;
if ( data ! = NULL & & len > = 0 ) {
if ( data ! = NULL & & len > 0 ) {
for ( i = 0 ; i < len ; + + i )
sum + = * ( unsigned char * ) ( data + i ) ;
sum + = ( ( unsigned char * ) data ) [ i ] ;
return sum ;
}
@ -124,18 +139,20 @@ static int md5_file(const char *filename, uint8_t *dst)
}
static int encode_image ( const char * input_file_name ,
const char * output_file_name , img_header * header , int block_size )
const char * output_file_name , img_header * header ,
struct capwap_header * cw_header , int block_size )
{
char buf [ BUF_SIZE ] ;
size_t bytes_read ;
size_t pad_len = 0 ;
size_t bytes_avail ;
size_t bytes_read ;
FILE * fp_input ;
FILE * fp_output ;
FILE * fp_input ;
int i ;
int model_s ize ;
long magic ;
size_t i ;
fp_input = fopen ( input_file_name , " r+b " ) ;
if ( ! fp_input ) {
@ -172,6 +189,11 @@ static int encode_image(const char *input_file_name,
}
header - > zero = 0 ;
header - > chksum = header_checksum ( header , HDR_LEN ) ;
if ( cw_header ) {
header - > chksum + = header_checksum ( cw_header ,
sizeof ( struct capwap_header ) + cw_header - > model_size ) ;
}
header - > head = htonl ( header - > head ) ;
header - > vendor_id = htonl ( header - > vendor_id ) ;
header - > product_id = htonl ( header - > product_id ) ;
@ -183,6 +205,22 @@ static int encode_image(const char *input_file_name,
fwrite ( header , HDR_LEN , 1 , fp_output ) ;
if ( cw_header ) {
model_size = cw_header - > model_size ;
cw_header - > mod = htonl ( cw_header - > mod ) ;
cw_header - > sku = htonl ( cw_header - > sku ) ;
cw_header - > firmware_ver [ 0 ] = htonl ( cw_header - > firmware_ver [ 0 ] ) ;
cw_header - > firmware_ver [ 1 ] = htonl ( cw_header - > firmware_ver [ 1 ] ) ;
cw_header - > firmware_ver [ 2 ] = htonl ( cw_header - > firmware_ver [ 2 ] ) ;
cw_header - > datecode = htonl ( cw_header - > datecode ) ;
cw_header - > capwap_ver [ 0 ] = htonl ( cw_header - > capwap_ver [ 0 ] ) ;
cw_header - > capwap_ver [ 1 ] = htonl ( cw_header - > capwap_ver [ 1 ] ) ;
cw_header - > capwap_ver [ 2 ] = htonl ( cw_header - > capwap_ver [ 2 ] ) ;
cw_header - > model_size = htonl ( cw_header - > model_size ) ;
fwrite ( cw_header , sizeof ( struct capwap_header ) + model_size , 1 ,
fp_output ) ;
}
while ( ! feof ( fp_input ) | | pad_len > 0 ) {
if ( ! feof ( fp_input ) )
@ -212,32 +250,33 @@ static int encode_image(const char *input_file_name,
int decode_image ( const char * input_file_name , const char * output_file_name )
{
img_header header ;
struct capwap_header cw_ header;
char buf [ BUF_SIZE ] ;
img_header header ;
char * pmodel = NULL ;
FILE * fp_input ;
FILE * fp_output ;
unsigned int i ;
size_t bytes_read ;
size_t bytes_written ;
unsigned int i ;
fp_input = fopen ( input_file_name , " r+b " ) ;
if ( ! fp_input ) {
fprintf ( stderr , " Cannot open %s !! \n " , input_file_name ) ;
fclose ( fp_input ) ;
return - 1 ;
}
fp_output = fopen ( output_file_name , " w+b " ) ;
if ( ! fp_output ) {
fprintf ( stderr , " Cannot open %s !! \n " , output_file_name ) ;
fclose ( fp_out put ) ;
fclose ( fp_in put ) ;
return - 1 ;
}
if ( fread ( & header , 1 , HDR_LEN , fp_input ) ! = HDR_LEN ) {
fprintf ( stderr , " Incorrect header size!! " ) ;
fprintf ( stderr , " Incorrect header size reading base header !! " ) ;
fclose ( fp_input ) ;
fclose ( fp_output ) ;
return - 1 ;
@ -251,6 +290,44 @@ int decode_image(const char *input_file_name, const char *output_file_name)
header . chksum = ntohl ( header . chksum ) ;
header . magic = ntohl ( header . magic ) ;
/* read capwap header if firmware_type is zero */
if ( header . firmware_type = = 0 ) {
if ( fread ( & cw_header , 1 , sizeof ( struct capwap_header ) ,
fp_input ) ! = sizeof ( struct capwap_header ) ) {
fprintf ( stderr , " Incorrect header size reading capwap_header!! " ) ;
fclose ( fp_input ) ;
fclose ( fp_output ) ;
return - 1 ;
}
cw_header . mod = ntohl ( cw_header . mod ) ;
cw_header . sku = ntohl ( cw_header . sku ) ;
cw_header . firmware_ver [ 0 ] = ntohl ( cw_header . firmware_ver [ 0 ] ) ;
cw_header . firmware_ver [ 1 ] = ntohl ( cw_header . firmware_ver [ 1 ] ) ;
cw_header . firmware_ver [ 2 ] = ntohl ( cw_header . firmware_ver [ 2 ] ) ;
cw_header . datecode = ntohl ( cw_header . datecode ) ;
cw_header . capwap_ver [ 0 ] = ntohl ( cw_header . capwap_ver [ 0 ] ) ;
cw_header . capwap_ver [ 1 ] = ntohl ( cw_header . capwap_ver [ 1 ] ) ;
cw_header . capwap_ver [ 2 ] = ntohl ( cw_header . capwap_ver [ 2 ] ) ;
cw_header . model_size = ntohl ( cw_header . model_size ) ;
pmodel = malloc ( cw_header . model_size + 1 ) ;
if ( pmodel ) {
pmodel [ cw_header . model_size ] = ' \0 ' ;
if ( fread ( pmodel , 1 , cw_header . model_size , fp_input ) ! =
cw_header . model_size ) {
fprintf ( stderr , " Incorrect header size reading model name!! " ) ;
fclose ( fp_input ) ;
fclose ( fp_output ) ;
return - 1 ;
}
} else {
fprintf ( stderr , " Incorrect header size reading model name!! " ) ;
fclose ( fp_input ) ;
fclose ( fp_output ) ;
return - 1 ;
}
}
bytes_written = 0 ;
while ( ! feof ( fp_input ) ) {
@ -281,7 +358,7 @@ int decode_image(const char *input_file_name, const char *output_file_name)
static void usage ( const char * progname , int status )
{
FILE * stream = ( status ! = EXIT_SUCCESS ) ? stderr : stdout ;
in t i ;
size_ t i ;
fprintf ( stream , " Usage: %s [OPTIONS...] \n " , progname ) ;
fprintf ( stream , " \n "
@ -301,28 +378,47 @@ static void usage(const char *progname, int status)
" -m <magic> set encoding magic <magic> \n "
" -z enable image padding to <blocksize> \n "
" -b <blocksize> set image <blocksize>, defaults to %u \n "
" -c <datecode> add capwap header with <datecode> (e.g. 171101) \n "
" -w <fw_ver> firmware version for capwap header (e.g. 3.0.1) \n "
" -x <cw_ver> capwap firmware version for capwap header (e.g. 1.8.53) \n "
" -n <name> model name for capwap header (e.g. ENS620EXT) \n "
" -h show this screen \n " , DEFAULT_BLOCK_SIZE ) ;
exit ( status ) ;
}
int main ( int argc , char * argv [ ] )
{
int opt ;
char * input_file , * output_file , * progname = NULL ;
static const char period [ 2 ] = " . " ;
struct capwap_header cw_header ;
img_header header ;
struct capwap_header * pcw_header = NULL ;
char * output_file = NULL ;
char * input_file = NULL ;
char * progname = NULL ;
char * mod_name = NULL ;
char * token ;
op_mode mode = NONE ;
int tmp , i , pad = 0 ;
int tmp , pad = 0 ;
int block_size ;
img_header header ;
size_t i ;
int opt ;
block_size = DEFAULT_BLOCK_SIZE ;
progname = basename ( argv [ 0 ] ) ;
memset ( & header , 0 , sizeof ( img_header ) ) ;
memset ( & header , 0 , sizeof ( img_header ) ) ;
header . magic = DEFAULT_MAGIC ;
header . head = DEFAULT_HEAD_VALUE ;
header . firmware_type = FIRMWARE_TYPE_NONE ;
memset ( & cw_header , 0 , sizeof ( struct capwap_header ) ) ;
cw_header . mod = MOD_DEFAULT ;
cw_header . sku = SKU_DEFAULT ;
cw_header . datecode = DATECODE_NONE ;
strncpy ( ( char * ) & header . version , DEFAULT_VERSION , VERSION_SIZE - 1 ) ;
while ( ( opt = getopt ( argc , argv , " :o:e:d:t:v:r:p:m:b:h?z " ) ) ! = - 1 ) {
while ( ( opt = getopt ( argc , argv , " :o:e:d:t:v:r:p:m:b:c:w:x:n: h?z " ) ) ! = - 1 ) {
switch ( opt ) {
case ' e ' :
input_file = optarg ;
@ -344,7 +440,7 @@ int main(int argc, char *argv[])
break ;
}
}
if ( header . firmware_type = = 0 ) {
if ( header . firmware_type = = FIRMWARE_TYPE_NONE ) {
fprintf ( stderr , " Invalid firmware type \" 0 \" ! \n " ) ;
usage ( progname , EXIT_FAILURE ) ;
}
@ -368,6 +464,31 @@ int main(int argc, char *argv[])
case ' b ' :
block_size = strtol ( optarg , 0 , 10 ) ;
break ;
case ' c ' :
cw_header . datecode = strtoul ( optarg , 0 , 10 ) ;
break ;
case ' w ' :
token = strtok ( optarg , period ) ;
i = 0 ;
while ( token & & ( i < 3 ) ) {
cw_header . firmware_ver [ i + + ] =
strtoul ( token , 0 , 10 ) ;
token = strtok ( NULL , period ) ;
}
break ;
case ' x ' :
token = strtok ( optarg , period ) ;
i = 0 ;
while ( token & & ( i < 3 ) ) {
cw_header . capwap_ver [ i + + ] =
strtoul ( token , 0 , 10 ) ;
token = strtok ( NULL , period ) ;
}
break ;
case ' n ' :
mod_name = optarg ;
cw_header . model_size = strlen ( mod_name ) ;
break ;
case ' h ' :
usage ( progname , EXIT_SUCCESS ) ;
break ;
@ -403,17 +524,46 @@ int main(int argc, char *argv[])
return EXIT_SUCCESS ;
}
if ( header . firmware_type = = 0 ) {
fprintf ( stderr , " Firmware type must be defined \n " ) ;
if ( ( header . firmware_type = = 0 ) & &
( cw_header . datecode = = DATECODE_NONE ) ) {
fprintf ( stderr , " Firmware type must be non-zero for non-capwap images \n " ) ;
usage ( progname , EXIT_FAILURE ) ;
}
if ( header . vendor_id = = 0 | | header . product_id = = 0 ) {
fprintf ( stderr , " Vendor ID and Product ID must be defined and non-zero \n " ) ;
fprintf ( stderr , " Vendor ID and Product ID must be defined and non-zero \n " ) ;
usage ( progname , EXIT_FAILURE ) ;
}
if ( encode_image ( input_file , output_file , & header , pad ? block_size : 0 ) < 0 )
/* Check capwap header specific arguments */
if ( cw_header . datecode ! = DATECODE_NONE ) {
if ( ! mod_name ) {
fprintf ( stderr , " Capwap header specified: model name must be specified \n " ) ;
usage ( progname , EXIT_FAILURE ) ;
}
if ( ! cw_header . firmware_ver [ 0 ] & & ! cw_header . firmware_ver [ 1 ] & &
! cw_header . firmware_ver [ 2 ] ) {
fprintf ( stderr , " Capwap header specified, fw_ver must be non-zero \n " ) ;
}
if ( ! cw_header . capwap_ver [ 0 ] & & ! cw_header . capwap_ver [ 1 ] & &
! cw_header . capwap_ver [ 2 ] ) {
fprintf ( stderr , " Capwap header specified, cw_ver must be non-zero \n " ) ;
}
pcw_header = malloc ( sizeof ( struct capwap_header ) +
cw_header . model_size ) ;
if ( pcw_header ) {
memcpy ( pcw_header , & cw_header ,
sizeof ( struct capwap_header ) ) ;
memcpy ( & ( pcw_header - > model ) , mod_name ,
cw_header . model_size ) ;
} else {
fprintf ( stderr , " Failed to allocate memory \n " ) ;
return EXIT_FAILURE ;
}
}
if ( encode_image ( input_file , output_file , & header , pcw_header ,
pad ? block_size : 0 ) < 0 )
return EXIT_FAILURE ;
return EXIT_SUCCESS ;