Skip to content

Commit

Permalink
[image] Simplify image management
Browse files Browse the repository at this point in the history
Refactor the {load,exec} image operations as {probe,exec}.  This makes
the probe mechanism cleaner, eliminates some forward declarations,
avoids holding magic state in image->priv, eliminates the possibility
of screwing up between the "load" and "exec" stages, and makes the
documentation simpler since the concept of "loading" (as distinct from
"executing") no longer needs to be explained.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Mar 7, 2011
1 parent 530a01e commit 34b6ecb
Show file tree
Hide file tree
Showing 20 changed files with 414 additions and 501 deletions.
70 changes: 30 additions & 40 deletions src/arch/i386/image/bzimage.c
Expand Up @@ -41,8 +41,6 @@ FILE_LICENCE ( GPL2_OR_LATER );

FEATURE ( FEATURE_IMAGE, "bzImage", DHCP_EB_FEATURE_BZIMAGE, 1 );

struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );

/**
* bzImage context
*/
Expand Down Expand Up @@ -111,8 +109,8 @@ static int bzimage_parse_header ( struct image *image,
sizeof ( bzimg->bzhdr ) );

/* Calculate size of real-mode portion */
bzimg->rm_filesz =
( ( bzimg->bzhdr.setup_sects ? bzimg->bzhdr.setup_sects : 4 ) + 1 ) << 9;
bzimg->rm_filesz = ( ( ( bzimg->bzhdr.setup_sects ?
bzimg->bzhdr.setup_sects : 4 ) + 1 ) << 9 );
if ( bzimg->rm_filesz > image->len ) {
DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
image, bzimg->rm_filesz );
Expand Down Expand Up @@ -455,11 +453,33 @@ static int bzimage_exec ( struct image *image ) {
const char *cmdline = ( image->cmdline ? image->cmdline : "" );
int rc;

/* Read and parse header from loaded kernel */
/* Read and parse header from image */
if ( ( rc = bzimage_parse_header ( image, &bzimg,
image->priv.user ) ) != 0 )
image->data ) ) != 0 )
return rc;

/* Prepare segments */
if ( ( rc = prep_segment ( bzimg.rm_kernel, bzimg.rm_filesz,
bzimg.rm_memsz ) ) != 0 ) {
DBGC ( image, "bzImage %p could not prepare RM segment: %s\n",
image, strerror ( rc ) );
return rc;
}
if ( ( rc = prep_segment ( bzimg.pm_kernel, bzimg.pm_sz,
bzimg.pm_sz ) ) != 0 ) {
DBGC ( image, "bzImage %p could not prepare PM segment: %s\n",
image, strerror ( rc ) );
return rc;
assert ( bzimg.rm_kernel == image->priv.user );
}

/* Load segments */
memcpy_user ( bzimg.rm_kernel, 0, image->data,
0, bzimg.rm_filesz );
memcpy_user ( bzimg.pm_kernel, 0, image->data,
bzimg.rm_filesz, bzimg.pm_sz );

/* Update and write out header */
bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );

/* Parse command line for bootloader parameters */
if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
Expand Down Expand Up @@ -506,12 +526,12 @@ static int bzimage_exec ( struct image *image ) {
}

/**
* Load bzImage image into memory
* Probe bzImage image
*
* @v image bzImage file
* @ret rc Return status code
*/
int bzimage_load ( struct image *image ) {
int bzimage_probe ( struct image *image ) {
struct bzimage_context bzimg;
int rc;

Expand All @@ -520,42 +540,12 @@ int bzimage_load ( struct image *image ) {
image->data ) ) != 0 )
return rc;

/* This is a bzImage image, valid or otherwise */
if ( ! image->type )
image->type = &bzimage_image_type;

/* Prepare segments */
if ( ( rc = prep_segment ( bzimg.rm_kernel, bzimg.rm_filesz,
bzimg.rm_memsz ) ) != 0 ) {
DBGC ( image, "bzImage %p could not prepare RM segment: %s\n",
image, strerror ( rc ) );
return rc;
}
if ( ( rc = prep_segment ( bzimg.pm_kernel, bzimg.pm_sz,
bzimg.pm_sz ) ) != 0 ) {
DBGC ( image, "bzImage %p could not prepare PM segment: %s\n",
image, strerror ( rc ) );
return rc;
}

/* Load segments */
memcpy_user ( bzimg.rm_kernel, 0, image->data,
0, bzimg.rm_filesz );
memcpy_user ( bzimg.pm_kernel, 0, image->data,
bzimg.rm_filesz, bzimg.pm_sz );

/* Update and write out header */
bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );

/* Record real-mode segment in image private data field */
image->priv.user = bzimg.rm_kernel;

return 0;
}

/** Linux bzImage image type */
struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ) = {
.name = "bzImage",
.load = bzimage_load,
.probe = bzimage_probe,
.exec = bzimage_exec,
};
35 changes: 20 additions & 15 deletions src/arch/i386/image/com32.c
Expand Up @@ -40,8 +40,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/init.h>
#include <ipxe/io.h>

struct image_type com32_image_type __image_type ( PROBE_NORMAL );

struct idt_register com32_external_idtr = {
.limit = COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) - 1,
.base = COM32_IDT
Expand All @@ -55,7 +53,7 @@ struct idt_register com32_internal_idtr;
* @v image COM32 image
* @ret rc Return status code
*/
static int com32_exec ( struct image *image ) {
static int com32_exec_loop ( struct image *image ) {
struct memory_map memmap;
unsigned int i;
int state;
Expand Down Expand Up @@ -137,7 +135,6 @@ static int com32_exec ( struct image *image ) {
image, comboot_replacement_image );
image->replacement = comboot_replacement_image;
comboot_replacement_image = NULL;
image_autoload ( image->replacement );
break;

case COMBOOT_EXIT_COMMAND:
Expand Down Expand Up @@ -207,7 +204,7 @@ static int com32_identify ( struct image *image ) {
* @v image COM32 image
* @ret rc Return status code
*/
static int comboot_load_image ( struct image *image ) {
static int com32_load_image ( struct image *image ) {
physaddr_t com32_irq_wrapper_phys;
struct idt_descriptor *idt;
struct ijb_entry *ijb;
Expand Down Expand Up @@ -262,7 +259,7 @@ static int comboot_load_image ( struct image *image ) {
* @v image COM32 image
* @ret rc Return status code
*/
static int comboot_prepare_bounce_buffer ( struct image * image ) {
static int com32_prepare_bounce_buffer ( struct image * image ) {
unsigned int seg;
userptr_t seg_userptr;
size_t filesz, memsz;
Expand All @@ -286,12 +283,12 @@ static int comboot_prepare_bounce_buffer ( struct image * image ) {
}

/**
* Load COM32 image into memory
* Probe COM32 image
*
* @v image COM32 image
* @ret rc Return status code
*/
static int com32_load ( struct image *image ) {
static int com32_probe ( struct image *image ) {
int rc;

DBGC ( image, "COM32 %p: name '%s', cmdline '%s'\n",
Expand All @@ -302,26 +299,34 @@ static int com32_load ( struct image *image ) {
return rc;
}

/* This is a COM32 image, valid or otherwise */
if ( ! image->type )
image->type = &com32_image_type;
return 0;
}

/**
* Execute COMBOOT image
*
* @v image COM32 image
* @ret rc Return status code
*/
static int com32_exec ( struct image *image ) {
int rc;

/* Load image */
if ( ( rc = comboot_load_image ( image ) ) != 0 ) {
if ( ( rc = com32_load_image ( image ) ) != 0 ) {
return rc;
}

/* Prepare bounce buffer segment */
if ( ( rc = comboot_prepare_bounce_buffer ( image ) ) != 0 ) {
if ( ( rc = com32_prepare_bounce_buffer ( image ) ) != 0 ) {
return rc;
}

return 0;
return com32_exec_loop ( image );
}

/** SYSLINUX COM32 image type */
struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = {
.name = "COM32",
.load = com32_load,
.probe = com32_probe,
.exec = com32_exec,
};
27 changes: 16 additions & 11 deletions src/arch/i386/image/comboot.c
Expand Up @@ -42,8 +42,6 @@ FILE_LICENCE ( GPL2_OR_LATER );

FEATURE ( FEATURE_IMAGE, "COMBOOT", DHCP_EB_FEATURE_COMBOOT, 1 );

struct image_type comboot_image_type __image_type ( PROBE_NORMAL );

/**
* COMBOOT PSP, copied to offset 0 of code segment
*/
Expand Down Expand Up @@ -131,7 +129,7 @@ static void comboot_init_psp ( struct image * image, userptr_t seg_userptr ) {
* @v image COMBOOT image
* @ret rc Return status code
*/
static int comboot_exec ( struct image *image ) {
static int comboot_exec_loop ( struct image *image ) {
userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
int state;

Expand Down Expand Up @@ -194,7 +192,6 @@ static int comboot_exec ( struct image *image ) {
image, comboot_replacement_image );
image->replacement = comboot_replacement_image;
comboot_replacement_image = NULL;
image_autoload ( image->replacement );
break;

case COMBOOT_EXIT_COMMAND:
Expand Down Expand Up @@ -278,12 +275,12 @@ static int comboot_prepare_segment ( struct image *image )
}

/**
* Load COMBOOT image into memory
* Probe COMBOOT image
*
* @v image COMBOOT image
* @ret rc Return status code
*/
static int comboot_load ( struct image *image ) {
static int comboot_probe ( struct image *image ) {
int rc;

DBGC ( image, "COMBOOT %p: name '%s'\n",
Expand All @@ -295,9 +292,17 @@ static int comboot_load ( struct image *image ) {
return rc;
}

/* This is a 16-bit COMBOOT image, valid or otherwise */
if ( ! image->type )
image->type = &comboot_image_type;
return 0;
}

/**
* Execute COMBOOT image
*
* @v image COMBOOT image
* @ret rc Return status code
*/
static int comboot_exec ( struct image *image ) {
int rc;

/* Sanity check for filesize */
if( image->len >= 0xFF00 ) {
Expand All @@ -311,12 +316,12 @@ static int comboot_load ( struct image *image ) {
return rc;
}

return 0;
return comboot_exec_loop ( image );
}

/** SYSLINUX COMBOOT (16-bit) image type */
struct image_type comboot_image_type __image_type ( PROBE_NORMAL ) = {
.name = "COMBOOT",
.load = comboot_load,
.probe = comboot_probe,
.exec = comboot_exec,
};
30 changes: 12 additions & 18 deletions src/arch/i386/image/elfboot.c
Expand Up @@ -34,16 +34,22 @@ FILE_LICENCE ( GPL2_OR_LATER );

FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 );

struct image_type elfboot_image_type __image_type ( PROBE_NORMAL );

/**
* Execute ELF image
*
* @v image ELF image
* @ret rc Return status code
*/
static int elfboot_exec ( struct image *image ) {
physaddr_t entry = image->priv.phys;
physaddr_t entry;
int rc;

/* Load the image using core ELF support */
if ( ( rc = elf_load ( image, &entry ) ) != 0 ) {
DBGC ( image, "ELF %p could not load: %s\n",
image, strerror ( rc ) );
return rc;
}

/* An ELF image has no callback interface, so we need to shut
* down before invoking it.
Expand All @@ -66,12 +72,12 @@ static int elfboot_exec ( struct image *image ) {
}

/**
* Load ELF image into memory
* Probe ELF image
*
* @v image ELF file
* @ret rc Return status code
*/
static int elfboot_load ( struct image *image ) {
static int elfboot_probe ( struct image *image ) {
Elf32_Ehdr ehdr;
static const uint8_t e_ident[] = {
[EI_MAG0] = ELFMAG0,
Expand All @@ -82,7 +88,6 @@ static int elfboot_load ( struct image *image ) {
[EI_DATA] = ELFDATA2LSB,
[EI_VERSION] = EV_CURRENT,
};
int rc;

/* Read ELF header */
copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
Expand All @@ -91,23 +96,12 @@ static int elfboot_load ( struct image *image ) {
return -ENOEXEC;
}

/* This is an ELF image, valid or otherwise */
if ( ! image->type )
image->type = &elfboot_image_type;

/* Load the image using core ELF support */
if ( ( rc = elf_load ( image ) ) != 0 ) {
DBGC ( image, "ELF %p could not load: %s\n",
image, strerror ( rc ) );
return rc;
}

return 0;
}

/** ELF image type */
struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = {
.name = "ELF",
.load = elfboot_load,
.probe = elfboot_probe,
.exec = elfboot_exec,
};

0 comments on commit 34b6ecb

Please sign in to comment.