@ -1,4 +1,6 @@
/*
* ( C ) Copyright 2008 Semihalf
*
* ( C ) Copyright 2000 - 2004
* DENX Software Engineering
* Wolfgang Denk , wd @ denx . de
@ -32,6 +34,8 @@ extern int errno;
extern unsigned long crc32 ( unsigned long crc , const char * buf , unsigned int len ) ;
static void copy_file ( int , const char * , int ) ;
static void usage ( void ) ;
static void image_verify_header ( char * , int ) ;
static void fit_handle_file ( void ) ;
char * datafile ;
char * imagefile ;
@ -39,6 +43,7 @@ char *cmdname;
int dflag = 0 ;
int eflag = 0 ;
int fflag = 0 ;
int lflag = 0 ;
int vflag = 0 ;
int xflag = 0 ;
@ -46,6 +51,7 @@ int opt_os = IH_OS_LINUX;
int opt_arch = IH_ARCH_PPC ;
int opt_type = IH_TYPE_KERNEL ;
int opt_comp = IH_COMP_GZIP ;
char * opt_dtc = MKIMAGE_DEFAULT_DTC_OPTIONS ;
image_header_t header ;
image_header_t * hdr = & header ;
@ -53,7 +59,7 @@ image_header_t *hdr = &header;
int
main ( int argc , char * * argv )
{
int ifd ;
int ifd = - 1 ;
uint32_t checksum ;
uint32_t addr ;
uint32_t ep ;
@ -81,6 +87,12 @@ main (int argc, char **argv)
( opt_comp = genimg_get_comp_id ( * + + argv ) ) < 0 )
usage ( ) ;
goto NXTARG ;
case ' D ' :
if ( - - argc < = 0 )
usage ( ) ;
opt_dtc = * + + argv ;
goto NXTARG ;
case ' O ' :
if ( ( - - argc < = 0 ) | |
( opt_os = genimg_get_os_id ( * + + argv ) ) < 0 )
@ -121,6 +133,12 @@ main (int argc, char **argv)
}
eflag = 1 ;
goto NXTARG ;
case ' f ' :
if ( - - argc < = 0 )
usage ( ) ;
datafile = * + + argv ;
fflag = 1 ;
goto NXTARG ;
case ' n ' :
if ( - - argc < = 0 )
usage ( ) ;
@ -139,7 +157,10 @@ main (int argc, char **argv)
NXTARG : ;
}
if ( ( argc ! = 1 ) | | ( ( lflag ^ dflag ) = = 0 ) )
if ( ( argc ! = 1 ) | |
( dflag & & ( fflag | | lflag ) ) | |
( fflag & & ( dflag | | lflag ) ) | |
( lflag & & ( dflag | | fflag ) ) )
usage ( ) ;
if ( ! eflag ) {
@ -165,21 +186,22 @@ NXTARG: ;
imagefile = * argv ;
if ( lflag ) {
ifd = open ( imagefile , O_RDONLY | O_BINARY ) ;
} else {
ifd = open ( imagefile , O_RDWR | O_CREAT | O_TRUNC | O_BINARY , 0666 ) ;
}
if ( ! fflag ) {
if ( lflag ) {
ifd = open ( imagefile , O_RDONLY | O_BINARY ) ;
} else {
ifd = open ( imagefile ,
O_RDWR | O_CREAT | O_TRUNC | O_BINARY , 0666 ) ;
}
if ( ifd < 0 ) {
fprintf ( stderr , " %s: Can't open %s: %s \n " ,
cmdname , imagefile , strerror ( errno ) ) ;
exit ( EXIT_FAILURE ) ;
if ( ifd < 0 ) {
fprintf ( stderr , " %s: Can't open %s: %s \n " ,
cmdname , imagefile , strerror ( errno ) ) ;
exit ( EXIT_FAILURE ) ;
}
}
if ( lflag ) {
int len ;
char * data ;
/*
* list header information of existing image
*/
@ -204,44 +226,24 @@ NXTARG: ;
exit ( EXIT_FAILURE ) ;
}
/*
* image_check_hcrc ( ) creates copy of header so that
* we can blank out the checksum field for checking -
* this can ' t be done on the PROT_READ mapped data .
*/
hdr = ( image_header_t * ) ptr ;
if ( ! image_check_magic ( hdr ) ) {
fprintf ( stderr ,
" %s: Bad Magic Number: \" %s \" is no valid image \n " ,
cmdname , imagefile ) ;
exit ( EXIT_FAILURE ) ;
}
if ( ! image_check_hcrc ( hdr ) ) {
fprintf ( stderr ,
" %s: ERROR: \" %s \" has bad header checksum! \n " ,
cmdname , imagefile ) ;
exit ( EXIT_FAILURE ) ;
if ( fdt_check_header ( ptr ) ) {
/* old-style image */
image_verify_header ( ( char * ) ptr , sbuf . st_size ) ;
image_print_contents_noindent ( ( image_header_t * ) ptr ) ;
} else {
/* FIT image */
fit_print_contents_noindent ( ptr ) ;
}
data = ( char * ) image_get_data ( hdr ) ;
len = sbuf . st_size - image_get_header_size ( ) ;
if ( crc32 ( 0 , data , len ) ! = image_get_dcrc ( hdr ) ) {
fprintf ( stderr ,
" %s: ERROR: \" %s \" has corrupted data! \n " ,
cmdname , imagefile ) ;
exit ( EXIT_FAILURE ) ;
}
/* for multi-file images we need the data part, too */
image_print_contents_noindent ( ( image_header_t * ) ptr ) ;
( void ) munmap ( ( void * ) ptr , sbuf . st_size ) ;
( void ) close ( ifd ) ;
exit ( EXIT_SUCCESS ) ;
} else if ( fflag ) {
/* Flattened Image Tree (FIT) format handling */
debug ( " FIT format handling \n " ) ;
fit_handle_file ( ) ;
exit ( EXIT_SUCCESS ) ;
}
/*
@ -467,11 +469,11 @@ void
usage ( )
{
fprintf ( stderr , " Usage: %s -l image \n "
" -l ==> list image header information \n "
" %s [-x] -A arch -O os -T type -C comp "
" -a addr -e ep -n name -d data_file[:data_file...] image \n " ,
cmdname , cmdname ) ;
fprintf ( stderr , " -A ==> set architecture to 'arch' \n "
" -l ==> list image header information \n " ,
cmdname ) ;
fprintf ( stderr , " %s [-x] -A arch -O os -T type -C comp "
" -a addr -e ep -n name -d data_file[:data_file...] image \n "
" -A ==> set architecture to 'arch' \n "
" -O ==> set operating system to 'os' \n "
" -T ==> set image type to 'type' \n "
" -C ==> set compression type 'comp' \n "
@ -479,7 +481,158 @@ usage ()
" -e ==> set entry point to 'ep' (hex) \n "
" -n ==> set image name to 'name' \n "
" -d ==> use image data from 'datafile' \n "
" -x ==> set XIP (execute in place) \n "
) ;
" -x ==> set XIP (execute in place) \n " ,
cmdname ) ;
fprintf ( stderr , " %s [-D dtc_options] -f fit-image.its fit-image \n " ,
cmdname ) ;
exit ( EXIT_FAILURE ) ;
}
static void
image_verify_header ( char * ptr , int image_size )
{
int len ;
char * data ;
uint32_t checksum ;
image_header_t header ;
image_header_t * hdr = & header ;
/*
* create copy of header so that we can blank out the
* checksum field for checking - this can ' t be done
* on the PROT_READ mapped data .
*/
memcpy ( hdr , ptr , sizeof ( image_header_t ) ) ;
if ( ntohl ( hdr - > ih_magic ) ! = IH_MAGIC ) {
fprintf ( stderr ,
" %s: Bad Magic Number: \" %s \" is no valid image \n " ,
cmdname , imagefile ) ;
exit ( EXIT_FAILURE ) ;
}
data = ( char * ) hdr ;
len = sizeof ( image_header_t ) ;
checksum = ntohl ( hdr - > ih_hcrc ) ;
hdr - > ih_hcrc = htonl ( 0 ) ; /* clear for re-calculation */
if ( crc32 ( 0 , data , len ) ! = checksum ) {
fprintf ( stderr ,
" %s: ERROR: \" %s \" has bad header checksum! \n " ,
cmdname , imagefile ) ;
exit ( EXIT_FAILURE ) ;
}
data = ptr + sizeof ( image_header_t ) ;
len = image_size - sizeof ( image_header_t ) ;
if ( crc32 ( 0 , data , len ) ! = ntohl ( hdr - > ih_dcrc ) ) {
fprintf ( stderr ,
" %s: ERROR: \" %s \" has corrupted data! \n " ,
cmdname , imagefile ) ;
exit ( EXIT_FAILURE ) ;
}
}
/**
* fit_handle_file - main FIT file processing function
*
* fit_handle_file ( ) runs dtc to convert . its to . itb , includes
* binary data , updates timestamp property and calculates hashes .
*
* datafile - . its file
* imagefile - . itb file
*
* returns :
* only on success , otherwise calls exit ( EXIT_FAILURE ) ;
*/
static void fit_handle_file ( void )
{
char tmpfile [ MKIMAGE_MAX_TMPFILE_LEN ] ;
char cmd [ MKIMAGE_MAX_DTC_CMDLINE_LEN ] ;
int tfd ;
struct stat sbuf ;
unsigned char * ptr ;
/* call dtc to include binary properties into the tmp file */
if ( strlen ( imagefile ) + strlen ( MKIMAGE_TMPFILE_SUFFIX ) + 1 >
sizeof ( tmpfile ) ) {
fprintf ( stderr , " %s: Image file name (%s) too long, "
" can't create tmpfile " ,
imagefile , cmdname ) ;
exit ( EXIT_FAILURE ) ;
}
sprintf ( tmpfile , " %s%s " , imagefile , MKIMAGE_TMPFILE_SUFFIX ) ;
/* dtc -I dts -O -p 200 datafile > tmpfile */
sprintf ( cmd , " %s %s %s > %s " ,
MKIMAGE_DTC , opt_dtc , datafile , tmpfile ) ;
debug ( " Trying to execute \" %s \" \n " , cmd ) ;
if ( system ( cmd ) = = - 1 ) {
fprintf ( stderr , " %s: system(%s) failed: %s \n " ,
cmdname , cmd , strerror ( errno ) ) ;
unlink ( tmpfile ) ;
exit ( EXIT_FAILURE ) ;
}
/* load FIT blob into memory */
tfd = open ( tmpfile , O_RDWR | O_BINARY ) ;
if ( tfd < 0 ) {
fprintf ( stderr , " %s: Can't open %s: %s \n " ,
cmdname , tmpfile , strerror ( errno ) ) ;
unlink ( tmpfile ) ;
exit ( EXIT_FAILURE ) ;
}
if ( fstat ( tfd , & sbuf ) < 0 ) {
fprintf ( stderr , " %s: Can't stat %s: %s \n " ,
cmdname , tmpfile , strerror ( errno ) ) ;
unlink ( tmpfile ) ;
exit ( EXIT_FAILURE ) ;
}
ptr = ( unsigned char * ) mmap ( 0 , sbuf . st_size ,
PROT_READ | PROT_WRITE , MAP_SHARED , tfd , 0 ) ;
if ( ( caddr_t ) ptr = = ( caddr_t ) - 1 ) {
fprintf ( stderr , " %s: Can't read %s: %s \n " ,
cmdname , tmpfile , strerror ( errno ) ) ;
unlink ( tmpfile ) ;
exit ( EXIT_FAILURE ) ;
}
/* check if ptr has a valid blob */
if ( fdt_check_header ( ptr ) ) {
fprintf ( stderr , " %s: Invalid FIT blob \n " , cmdname ) ;
unlink ( tmpfile ) ;
exit ( EXIT_FAILURE ) ;
}
/* set hashes for images in the blob */
if ( fit_set_hashes ( ptr ) ) {
fprintf ( stderr , " %s Can't add hashes to FIT blob " , cmdname ) ;
unlink ( tmpfile ) ;
exit ( EXIT_FAILURE ) ;
}
/* add a timestamp at offset 0 i.e., root */
if ( fit_set_timestamp ( ptr , 0 , sbuf . st_mtime ) ) {
fprintf ( stderr , " %s: Can't add image timestamp \n " , cmdname ) ;
unlink ( tmpfile ) ;
exit ( EXIT_FAILURE ) ;
}
debug ( " Added timestamp successfully \n " ) ;
munmap ( ( void * ) ptr , sbuf . st_size ) ;
close ( tfd ) ;
if ( rename ( tmpfile , imagefile ) = = - 1 ) {
fprintf ( stderr , " %s: Can't rename %s to %s: %s \n " ,
cmdname , tmpfile , imagefile , strerror ( errno ) ) ;
unlink ( tmpfile ) ;
unlink ( imagefile ) ;
exit ( EXIT_FAILURE ) ;
}
}