2006-10-13 19:07:01 +04:00
/*
* Makes a tree bootable image for IBM Evaluation boards .
* Basically , just take a zImage , skip the ELF header , and stuff
* a 32 byte header on the front .
*
* We use htonl , which is a network macro , to make sure we ' re doing
* The Right Thing on an LE machine . It ' s non - obvious , but it should
* work on anything BSD ' ish .
*/
# include <fcntl.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/stat.h>
# include <unistd.h>
# include <netinet/in.h>
# ifdef __sun__
# include <inttypes.h>
# else
# include <stdint.h>
# endif
/* This gets tacked on the front of the image. There are also a few
* bytes allocated after the _start label used by the boot rom ( see
* head . S for details ) .
*/
typedef struct boot_block {
uint32_t bb_magic ; /* 0x0052504F */
uint32_t bb_dest ; /* Target address of the image */
uint32_t bb_num_512blocks ; /* Size, rounded-up, in 512 byte blks */
uint32_t bb_debug_flag ; /* Run debugger or image after load */
uint32_t bb_entry_point ; /* The image address to start */
uint32_t bb_checksum ; /* 32 bit checksum including header */
uint32_t reserved [ 2 ] ;
} boot_block_t ;
# define IMGBLK 512
2009-08-10 21:14:55 +04:00
unsigned int tmpbuf [ IMGBLK / sizeof ( unsigned int ) ] ;
2006-10-13 19:07:01 +04:00
int main ( int argc , char * argv [ ] )
{
int in_fd , out_fd ;
int nblks , i ;
2009-04-30 22:16:44 +04:00
unsigned int cksum , * cp ;
2006-10-13 19:07:01 +04:00
struct stat st ;
boot_block_t bt ;
2007-05-08 08:10:01 +04:00
if ( argc < 5 ) {
fprintf ( stderr , " usage: %s <zImage-file> <boot-image> <load address> <entry point> \n " , argv [ 0 ] ) ;
2006-10-13 19:07:01 +04:00
exit ( 1 ) ;
}
if ( stat ( argv [ 1 ] , & st ) < 0 ) {
perror ( " stat " ) ;
exit ( 2 ) ;
}
nblks = ( st . st_size + IMGBLK ) / IMGBLK ;
bt . bb_magic = htonl ( 0x0052504F ) ;
/* If we have the optional entry point parameter, use it */
2007-05-08 08:10:01 +04:00
bt . bb_dest = htonl ( strtoul ( argv [ 3 ] , NULL , 0 ) ) ;
bt . bb_entry_point = htonl ( strtoul ( argv [ 4 ] , NULL , 0 ) ) ;
2006-10-13 19:07:01 +04:00
/* We know these from the linker command.
* . . . and then move it up into memory a little more so the
* relocation can happen .
*/
bt . bb_num_512blocks = htonl ( nblks ) ;
bt . bb_debug_flag = 0 ;
bt . bb_checksum = 0 ;
/* To be neat and tidy :-).
*/
bt . reserved [ 0 ] = 0 ;
bt . reserved [ 1 ] = 0 ;
if ( ( in_fd = open ( argv [ 1 ] , O_RDONLY ) ) < 0 ) {
perror ( " zImage open " ) ;
exit ( 3 ) ;
}
if ( ( out_fd = open ( argv [ 2 ] , ( O_RDWR | O_CREAT | O_TRUNC ) , 0666 ) ) < 0 ) {
perror ( " bootfile open " ) ;
exit ( 3 ) ;
}
cksum = 0 ;
cp = ( void * ) & bt ;
2009-04-30 22:16:44 +04:00
for ( i = 0 ; i < sizeof ( bt ) / sizeof ( unsigned int ) ; i + + )
2006-10-13 19:07:01 +04:00
cksum + = * cp + + ;
/* Assume zImage is an ELF file, and skip the 64K header.
*/
2009-08-10 21:14:55 +04:00
if ( read ( in_fd , tmpbuf , sizeof ( tmpbuf ) ) ! = sizeof ( tmpbuf ) ) {
2006-10-13 19:07:01 +04:00
fprintf ( stderr , " %s is too small to be an ELF image \n " ,
argv [ 1 ] ) ;
exit ( 4 ) ;
}
2009-08-10 21:14:55 +04:00
if ( tmpbuf [ 0 ] ! = htonl ( 0x7f454c46 ) ) {
2006-10-13 19:07:01 +04:00
fprintf ( stderr , " %s is not an ELF image \n " , argv [ 1 ] ) ;
exit ( 4 ) ;
}
if ( lseek ( in_fd , ( 64 * 1024 ) , SEEK_SET ) < 0 ) {
fprintf ( stderr , " %s failed to seek in ELF image \n " , argv [ 1 ] ) ;
exit ( 4 ) ;
}
nblks - = ( 64 * 1024 ) / IMGBLK ;
/* And away we go......
*/
if ( write ( out_fd , & bt , sizeof ( bt ) ) ! = sizeof ( bt ) ) {
perror ( " boot-image write " ) ;
exit ( 5 ) ;
}
while ( nblks - - > 0 ) {
2009-08-10 21:14:55 +04:00
if ( read ( in_fd , tmpbuf , sizeof ( tmpbuf ) ) < 0 ) {
2006-10-13 19:07:01 +04:00
perror ( " zImage read " ) ;
exit ( 5 ) ;
}
2009-08-10 21:14:55 +04:00
cp = tmpbuf ;
2009-04-30 22:16:44 +04:00
for ( i = 0 ; i < sizeof ( tmpbuf ) / sizeof ( unsigned int ) ; i + + )
2006-10-13 19:07:01 +04:00
cksum + = * cp + + ;
if ( write ( out_fd , tmpbuf , sizeof ( tmpbuf ) ) ! = sizeof ( tmpbuf ) ) {
perror ( " boot-image write " ) ;
exit ( 5 ) ;
}
}
/* rewrite the header with the computed checksum.
*/
bt . bb_checksum = htonl ( cksum ) ;
if ( lseek ( out_fd , 0 , SEEK_SET ) < 0 ) {
perror ( " rewrite seek " ) ;
exit ( 1 ) ;
}
if ( write ( out_fd , & bt , sizeof ( bt ) ) ! = sizeof ( bt ) ) {
perror ( " boot-image rewrite " ) ;
exit ( 1 ) ;
}
exit ( 0 ) ;
}