@ -89,21 +89,8 @@ static void build_command_line(char *command_line, int auto_boot)
printf ( " Kernel command line: \" %s \" \n " , command_line ) ;
}
void * load_zimage ( char * image , unsigned long kernel_size ,
unsigned long initrd_addr , unsigned long initrd_size ,
int auto_boot , void * * load_address )
static int kernel_magic_ok ( struct setup_header * hdr )
{
struct boot_params * setup_base ;
int setup_size ;
int bootproto ;
int big_image ;
struct boot_params * params = ( struct boot_params * ) image ;
struct setup_header * hdr = & params - > hdr ;
/* base address for real-mode segment */
setup_base = ( struct boot_params * ) DEFAULT_SETUP_BASE ;
if ( KERNEL_MAGIC ! = hdr - > boot_flag ) {
printf ( " Error: Invalid Boot Flag "
" (found 0x%04x, expected 0x%04x) \n " ,
@ -111,18 +98,38 @@ void *load_zimage(char *image, unsigned long kernel_size,
return 0 ;
} else {
printf ( " Valid Boot Flag \n " ) ;
return 1 ;
}
}
/* determine boot protocol version */
if ( KERNEL_V2_MAGIC = = hdr - > header ) {
static int get_boot_protocol ( struct setup_header * hdr )
{
if ( hdr - > header = = KERNEL_V2_MAGIC ) {
printf ( " Magic signature found \n " ) ;
bootproto = hdr - > version ;
return hdr - > version ;
} else {
/* Very old kernel */
printf ( " Magic signature not found \n " ) ;
bootproto = 0x0100 ;
return 0x0100 ;
}
}
struct boot_params * load_zimage ( char * image , unsigned long kernel_size ,
void * * load_address )
{
struct boot_params * setup_base ;
int setup_size ;
int bootproto ;
int big_image ;
struct boot_params * params = ( struct boot_params * ) image ;
struct setup_header * hdr = & params - > hdr ;
/* base address for real-mode segment */
setup_base = ( struct boot_params * ) DEFAULT_SETUP_BASE ;
if ( ! kernel_magic_ok ( hdr ) )
return 0 ;
/* determine size of setup */
if ( 0 = = hdr - > setup_sects ) {
@ -137,6 +144,23 @@ void *load_zimage(char *image, unsigned long kernel_size,
if ( setup_size > SETUP_MAX_SIZE )
printf ( " Error: Setup is too large (%d bytes) \n " , setup_size ) ;
/* determine boot protocol version */
bootproto = get_boot_protocol ( hdr ) ;
printf ( " Using boot protocol version %x.%02x \n " ,
( bootproto & 0xff00 ) > > 8 , bootproto & 0xff ) ;
if ( bootproto > = 0x0200 ) {
if ( hdr - > setup_sects > = 15 ) {
printf ( " Linux kernel version %s \n " ,
( char * ) params +
hdr - > kernel_version + 0x200 ) ;
} else {
printf ( " Setup Sectors < 15 - "
" Cannot print kernel version. \n " ) ;
}
}
/* Determine image type */
big_image = ( bootproto > = 0x0200 ) & &
( hdr - > loadflags & BIG_KERNEL_FLAG ) ;
@ -151,9 +175,6 @@ void *load_zimage(char *image, unsigned long kernel_size,
printf ( " Building boot_params at 0x%8.8lx \n " , ( ulong ) setup_base ) ;
memset ( setup_base , 0 , sizeof ( * setup_base ) ) ;
setup_base - > hdr = params - > hdr ;
setup_base - > e820_entries = install_e820_map (
ARRAY_SIZE ( setup_base - > e820_map ) , setup_base - > e820_map ) ;
# else
/* load setup */
printf ( " Moving Real-Mode Code to 0x%8.8lx (%d bytes) \n " ,
@ -161,13 +182,12 @@ void *load_zimage(char *image, unsigned long kernel_size,
memmove ( setup_base , image , setup_size ) ;
# endif
printf ( " Using boot protocol version %x.%02x \n " ,
( bootproto & 0xff00 ) > > 8 , bootproto & 0xff ) ;
if ( bootproto > = 0x0204 )
kernel_size = hdr - > syssize * 16 ;
else
kernel_size - = setup_size ;
if ( bootproto = = 0x0100 ) {
setup_base - > screen_info . cl_magic = COMMAND_LINE_MAGIC ;
setup_base - > screen_info . cl_offset = COMMAND_LINE_OFFSET ;
/*
* A very old kernel MUST have its real - mode code
* loaded at 0x90000
@ -190,21 +210,45 @@ void *load_zimage(char *image, unsigned long kernel_size,
SETUP_MAX_SIZE - setup_size ) ;
}
/* We are now setting up the real-mode version of the header */
hdr = & setup_base - > hdr ;
if ( big_image ) {
if ( kernel_size > BZIMAGE_MAX_SIZE ) {
printf ( " Error: bzImage kernel too big! "
" (size: %ld, max: %d) \n " ,
kernel_size , BZIMAGE_MAX_SIZE ) ;
return 0 ;
}
} else if ( ( kernel_size ) > ZIMAGE_MAX_SIZE ) {
printf ( " Error: zImage kernel too big! (size: %ld, max: %d) \n " ,
kernel_size , ZIMAGE_MAX_SIZE ) ;
return 0 ;
}
printf ( " Loading %s at address %p (%ld bytes) \n " ,
big_image ? " bzImage " : " zImage " , * load_address , kernel_size ) ;
memmove ( * load_address , image + setup_size , kernel_size ) ;
return setup_base ;
}
int setup_zimage ( struct boot_params * setup_base , char * cmd_line , int auto_boot ,
unsigned long initrd_addr , unsigned long initrd_size )
{
struct setup_header * hdr = & setup_base - > hdr ;
int bootproto = get_boot_protocol ( hdr ) ;
# if defined CONFIG_ZBOOT_32
setup_base - > e820_entries = install_e820_map (
ARRAY_SIZE ( setup_base - > e820_map ) , setup_base - > e820_map ) ;
# endif
if ( bootproto = = 0x0100 ) {
setup_base - > screen_info . cl_magic = COMMAND_LINE_MAGIC ;
setup_base - > screen_info . cl_offset = COMMAND_LINE_OFFSET ;
}
if ( bootproto > = 0x0200 ) {
hdr - > type_of_loader = 8 ;
if ( hdr - > setup_sects > = 15 ) {
printf ( " Linux kernel version %s \n " ,
( char * ) params +
hdr - > kernel_version + 0x200 ) ;
} else {
printf ( " Setup Sectors < 15 - "
" Cannot print kernel version. \n " ) ;
}
if ( initrd_addr ) {
printf ( " Initial RAM disk at linear address "
" 0x%08lx, size %ld bytes \n " ,
@ -221,44 +265,18 @@ void *load_zimage(char *image, unsigned long kernel_size,
}
if ( bootproto > = 0x0202 ) {
hdr - > cmd_line_ptr =
( uintptr_t ) setup_base + COMMAND_LINE_OFFSET ;
hdr - > cmd_line_ptr = ( uintptr_t ) cmd_line ;
} else if ( bootproto > = 0x0200 ) {
setup_base - > screen_info . cl_magic = COMMAND_LINE_MAGIC ;
setup_base - > screen_info . cl_offset = COMMAND_LINE_OFFSET ;
setup_base - > screen_info . cl_offset =
( uintptr_t ) cmd_line - ( uintptr_t ) setup_base ;
hdr - > setup_move_size = 0x9100 ;
}
if ( bootproto > = 0x0204 )
kernel_size = hdr - > syssize * 16 ;
else
kernel_size - = setup_size ;
if ( big_image ) {
if ( ( kernel_size ) > BZIMAGE_MAX_SIZE ) {
printf ( " Error: bzImage kernel too big! "
" (size: %ld, max: %d) \n " ,
kernel_size , BZIMAGE_MAX_SIZE ) ;
return 0 ;
}
} else if ( ( kernel_size ) > ZIMAGE_MAX_SIZE ) {
printf ( " Error: zImage kernel too big! (size: %ld, max: %d) \n " ,
kernel_size , ZIMAGE_MAX_SIZE ) ;
return 0 ;
}
/* build command line at COMMAND_LINE_OFFSET */
build_command_line ( ( char * ) setup_base + COMMAND_LINE_OFFSET , auto_boot ) ;
printf ( " Loading %czImage at address 0x%08x (%ld bytes) \n " ,
big_image ? ' b ' : ' ' , ( u32 ) * load_address , kernel_size ) ;
memmove ( * load_address , image + setup_size , kernel_size ) ;
/* ready for booting */
return setup_base ;
build_command_line ( cmd_line , auto_boot ) ;
return 0 ;
}
void boot_zimage ( void * setup_base , void * load_address )
@ -298,7 +316,7 @@ void boot_zimage(void *setup_base, void *load_address)
int do_zboot ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
void * base_ptr ;
struct boot_params * base_ptr ;
void * bzImage_addr = NULL ;
void * load_address ;
char * s ;
@ -324,20 +342,25 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
bzImage_size = simple_strtoul ( argv [ 2 ] , NULL , 16 ) ;
/* Lets look for */
base_ptr = load_zimage ( bzImage_addr , bzImage_size , 0 , 0 , 0 ,
& load_address ) ;
base_ptr = load_zimage ( bzImage_addr , bzImage_size , & load_address ) ;
if ( ! base_ptr ) {
printf ( " ## Kernel loading failed ... \n " ) ;
} else {
printf ( " ## Transferring control to Linux "
" (at address %08x) ... \n " ,
( u32 ) base_ptr ) ;
/* we assume that the kernel is in place */
boot_zimage ( base_ptr , load_address ) ;
/* does not return */
return - 1 ;
}
if ( setup_zimage ( base_ptr , ( char * ) base_ptr + COMMAND_LINE_OFFSET ,
0 , 0 , 0 ) ) {
printf ( " Setting up boot parameters failed ... \n " ) ;
return - 1 ;
}
printf ( " ## Transferring control to Linux "
" (at address %08x) ... \n " ,
( u32 ) base_ptr ) ;
/* we assume that the kernel is in place */
boot_zimage ( base_ptr , load_address ) ;
/* does not return */
return - 1 ;
}