2005-04-17 02:20:36 +04:00
/*
* addinitrd - program to add a initrd image to an ecoff kernel
*
* ( C ) 1999 Thomas Bogendoerfer
* minor modifications , cleanup : Guido Guenther < agx @ sigxcpu . org >
* further cleanup : Maciej W . Rozycki
*/
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
# include <stdio.h>
# include <netinet/in.h>
# include "ecoff.h"
# define MIPS_PAGE_SIZE 4096
# define MIPS_PAGE_MASK (MIPS_PAGE_SIZE-1)
# define swab16(x) \
( ( unsigned short ) ( \
( ( ( unsigned short ) ( x ) & ( unsigned short ) 0x00ffU ) < < 8 ) | \
( ( ( unsigned short ) ( x ) & ( unsigned short ) 0xff00U ) > > 8 ) ) )
# define swab32(x) \
( ( unsigned int ) ( \
( ( ( unsigned int ) ( x ) & ( unsigned int ) 0x000000ffUL ) < < 24 ) | \
( ( ( unsigned int ) ( x ) & ( unsigned int ) 0x0000ff00UL ) < < 8 ) | \
( ( ( unsigned int ) ( x ) & ( unsigned int ) 0x00ff0000UL ) > > 8 ) | \
( ( ( unsigned int ) ( x ) & ( unsigned int ) 0xff000000UL ) > > 24 ) ) )
# define SWAB(a) (swab ? swab32(a) : (a))
2007-10-12 02:46:15 +04:00
void die ( char * s )
2005-04-17 02:20:36 +04:00
{
2007-10-12 02:46:15 +04:00
perror ( s ) ;
exit ( 1 ) ;
2005-04-17 02:20:36 +04:00
}
2007-10-12 02:46:15 +04:00
int main ( int argc , char * argv [ ] )
2005-04-17 02:20:36 +04:00
{
2007-10-12 02:46:15 +04:00
int fd_vmlinux , fd_initrd , fd_outfile ;
2005-04-17 02:20:36 +04:00
FILHDR efile ;
AOUTHDR eaout ;
SCNHDR esecs [ 3 ] ;
struct stat st ;
char buf [ 1024 ] ;
unsigned long loadaddr ;
unsigned long initrd_header [ 2 ] ;
2007-10-12 02:46:15 +04:00
int i , cnt ;
2005-04-17 02:20:36 +04:00
int swab = 0 ;
if ( argc ! = 4 ) {
2007-10-12 02:46:15 +04:00
printf ( " Usage: %s <vmlinux> <initrd> <outfile> \n " , argv [ 0 ] ) ;
2007-10-12 02:46:15 +04:00
exit ( 1 ) ;
2005-04-17 02:20:36 +04:00
}
2007-10-12 02:46:15 +04:00
if ( ( fd_vmlinux = open ( argv [ 1 ] , O_RDONLY ) ) < 0 )
2007-10-12 02:46:15 +04:00
die ( " open vmlinux " ) ;
2005-04-17 02:20:36 +04:00
if ( read ( fd_vmlinux , & efile , sizeof efile ) ! = sizeof efile )
2007-10-12 02:46:15 +04:00
die ( " read file header " ) ;
2005-04-17 02:20:36 +04:00
if ( read ( fd_vmlinux , & eaout , sizeof eaout ) ! = sizeof eaout )
2007-10-12 02:46:15 +04:00
die ( " read aout header " ) ;
2005-04-17 02:20:36 +04:00
if ( read ( fd_vmlinux , esecs , sizeof esecs ) ! = sizeof esecs )
2007-10-12 02:46:15 +04:00
die ( " read section headers " ) ;
2005-04-17 02:20:36 +04:00
/*
* check whether the file is good for us
*/
/* TBD */
/*
* check , if we have to swab words
*/
if ( ntohs ( 0xaa55 ) = = 0xaa55 ) {
if ( efile . f_magic = = swab16 ( MIPSELMAGIC ) )
swab = 1 ;
} else {
if ( efile . f_magic = = swab16 ( MIPSEBMAGIC ) )
swab = 1 ;
}
/* make sure we have an empty data segment for the initrd */
if ( eaout . dsize | | esecs [ 1 ] . s_size ) {
2007-10-12 02:46:15 +04:00
fprintf ( stderr , " Data segment not empty. Giving up! \n " ) ;
exit ( 1 ) ;
2005-04-17 02:20:36 +04:00
}
if ( ( fd_initrd = open ( argv [ 2 ] , O_RDONLY ) ) < 0 )
2007-10-12 02:46:15 +04:00
die ( " open initrd " ) ;
2005-04-17 02:20:36 +04:00
if ( fstat ( fd_initrd , & st ) < 0 )
2007-10-12 02:46:15 +04:00
die ( " fstat initrd " ) ;
2005-04-17 02:20:36 +04:00
loadaddr = ( ( SWAB ( esecs [ 2 ] . s_vaddr ) + SWAB ( esecs [ 2 ] . s_size )
+ MIPS_PAGE_SIZE - 1 ) & ~ MIPS_PAGE_MASK ) - 8 ;
if ( loadaddr < ( SWAB ( esecs [ 2 ] . s_vaddr ) + SWAB ( esecs [ 2 ] . s_size ) ) )
loadaddr + = MIPS_PAGE_SIZE ;
initrd_header [ 0 ] = SWAB ( 0x494E5244 ) ;
initrd_header [ 1 ] = SWAB ( st . st_size ) ;
eaout . dsize = esecs [ 1 ] . s_size = initrd_header [ 1 ] = SWAB ( st . st_size + 8 ) ;
eaout . data_start = esecs [ 1 ] . s_vaddr = esecs [ 1 ] . s_paddr = SWAB ( loadaddr ) ;
2007-10-12 02:46:15 +04:00
if ( ( fd_outfile = open ( argv [ 3 ] , O_RDWR | O_CREAT | O_TRUNC , 0666 ) ) < 0 )
2007-10-12 02:46:15 +04:00
die ( " open outfile " ) ;
2005-04-17 02:20:36 +04:00
if ( write ( fd_outfile , & efile , sizeof efile ) ! = sizeof efile )
2007-10-12 02:46:15 +04:00
die ( " write file header " ) ;
2005-04-17 02:20:36 +04:00
if ( write ( fd_outfile , & eaout , sizeof eaout ) ! = sizeof eaout )
2007-10-12 02:46:15 +04:00
die ( " write aout header " ) ;
2005-04-17 02:20:36 +04:00
if ( write ( fd_outfile , esecs , sizeof esecs ) ! = sizeof esecs )
2007-10-12 02:46:15 +04:00
die ( " write section headers " ) ;
2005-04-17 02:20:36 +04:00
/* skip padding */
if ( lseek ( fd_vmlinux , SWAB ( esecs [ 0 ] . s_scnptr ) , SEEK_SET ) = = ( off_t ) - 1 )
2007-10-12 02:46:15 +04:00
die ( " lseek vmlinux " ) ;
2005-04-17 02:20:36 +04:00
if ( lseek ( fd_outfile , SWAB ( esecs [ 0 ] . s_scnptr ) , SEEK_SET ) = = ( off_t ) - 1 )
2007-10-12 02:46:15 +04:00
die ( " lseek outfile " ) ;
2005-04-17 02:20:36 +04:00
/* copy text segment */
cnt = SWAB ( eaout . tsize ) ;
while ( cnt ) {
if ( ( i = read ( fd_vmlinux , buf , sizeof buf ) ) < = 0 )
2007-10-12 02:46:15 +04:00
die ( " read vmlinux " ) ;
2005-04-17 02:20:36 +04:00
if ( write ( fd_outfile , buf , i ) ! = i )
2007-10-12 02:46:15 +04:00
die ( " write vmlinux " ) ;
2005-04-17 02:20:36 +04:00
cnt - = i ;
}
if ( write ( fd_outfile , initrd_header , sizeof initrd_header ) ! = sizeof initrd_header )
2007-10-12 02:46:15 +04:00
die ( " write initrd header " ) ;
2005-04-17 02:20:36 +04:00
while ( ( i = read ( fd_initrd , buf , sizeof buf ) ) > 0 )
if ( write ( fd_outfile , buf , i ) ! = i )
2007-10-12 02:46:15 +04:00
die ( " write initrd " ) ;
close ( fd_vmlinux ) ;
close ( fd_initrd ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}