summaryrefslogtreecommitdiffstats
path: root/src/arch/x86/image
diff options
context:
space:
mode:
authorSimon Rettberg2026-01-28 12:53:53 +0100
committerSimon Rettberg2026-01-28 12:53:53 +0100
commit8e82785c584dc13e20f9229decb95bd17bbe9cd1 (patch)
treea8b359e59196be5b2e3862bed189107f4bc9975f /src/arch/x86/image
parentMerge branch 'master' into openslx (diff)
parent[prefix] Make unlzma.S compatible with 386 class CPUs (diff)
downloadipxe-openslx.tar.gz
ipxe-openslx.tar.xz
ipxe-openslx.zip
Merge branch 'master' into openslxopenslx
Diffstat (limited to 'src/arch/x86/image')
-rw-r--r--src/arch/x86/image/bzimage.c360
-rw-r--r--src/arch/x86/image/com32.c90
-rw-r--r--src/arch/x86/image/comboot.c93
-rw-r--r--src/arch/x86/image/elfboot.c35
-rw-r--r--src/arch/x86/image/initrd.c306
-rw-r--r--src/arch/x86/image/multiboot.c234
-rw-r--r--src/arch/x86/image/nbi.c117
-rw-r--r--src/arch/x86/image/pxe_image.c26
-rw-r--r--src/arch/x86/image/sdi.c75
-rw-r--r--src/arch/x86/image/ucode.c231
10 files changed, 561 insertions, 1006 deletions
diff --git a/src/arch/x86/image/bzimage.c b/src/arch/x86/image/bzimage.c
index 2c776147d..16a47fc57 100644
--- a/src/arch/x86/image/bzimage.c
+++ b/src/arch/x86/image/bzimage.c
@@ -32,12 +32,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <realmode.h>
#include <bzimage.h>
-#include <initrd.h>
+#include <ipxe/initrd.h>
#include <ipxe/uaccess.h>
#include <ipxe/image.h>
#include <ipxe/segment.h>
@@ -56,7 +57,7 @@ struct bzimage_context {
/** Real-mode kernel portion load segment address */
unsigned int rm_kernel_seg;
/** Real-mode kernel portion load address */
- userptr_t rm_kernel;
+ void *rm_kernel;
/** Real-mode kernel portion file size */
size_t rm_filesz;
/** Real-mode heap top (offset from rm_kernel) */
@@ -68,7 +69,7 @@ struct bzimage_context {
/** Real-mode kernel portion total memory size */
size_t rm_memsz;
/** Non-real-mode kernel portion load address */
- userptr_t pm_kernel;
+ void *pm_kernel;
/** Non-real-mode kernel portion file and memory size */
size_t pm_sz;
/** Video mode */
@@ -76,14 +77,9 @@ struct bzimage_context {
/** Memory limit */
uint64_t mem_limit;
/** Initrd address */
- physaddr_t ramdisk_image;
+ void *initrd;
/** Initrd size */
- physaddr_t ramdisk_size;
-
- /** Command line magic block */
- struct bzimage_cmdline cmdline_magic;
- /** bzImage header */
- struct bzimage_header bzhdr;
+ physaddr_t initrd_size;
};
/**
@@ -91,35 +87,31 @@ struct bzimage_context {
*
* @v image bzImage file
* @v bzimg bzImage context
- * @v src bzImage to parse
* @ret rc Return status code
*/
static int bzimage_parse_header ( struct image *image,
- struct bzimage_context *bzimg,
- userptr_t src ) {
+ struct bzimage_context *bzimg ) {
+ const struct bzimage_header *bzhdr;
unsigned int syssize;
int is_bzimage;
+ /* Initialise context */
+ memset ( bzimg, 0, sizeof ( *bzimg ) );
+
/* Sanity check */
- if ( image->len < ( BZI_HDR_OFFSET + sizeof ( bzimg->bzhdr ) ) ) {
- DBGC ( image, "bzImage %p too short for kernel header\n",
- image );
+ if ( image->len < ( BZI_HDR_OFFSET + sizeof ( *bzhdr ) ) ) {
+ DBGC ( image, "bzImage %s too short for kernel header\n",
+ image->name );
return -ENOEXEC;
}
-
- /* Read in header structures */
- memset ( bzimg, 0, sizeof ( *bzimg ) );
- copy_from_user ( &bzimg->cmdline_magic, src, BZI_CMDLINE_OFFSET,
- sizeof ( bzimg->cmdline_magic ) );
- copy_from_user ( &bzimg->bzhdr, src, BZI_HDR_OFFSET,
- sizeof ( bzimg->bzhdr ) );
+ bzhdr = ( image->data + BZI_HDR_OFFSET );
/* Calculate size of real-mode portion */
- bzimg->rm_filesz = ( ( ( bzimg->bzhdr.setup_sects ?
- bzimg->bzhdr.setup_sects : 4 ) + 1 ) << 9 );
+ bzimg->rm_filesz = ( ( ( bzhdr->setup_sects ?
+ 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 );
+ DBGC ( image, "bzImage %s too short for %zd byte of setup\n",
+ image->name, bzimg->rm_filesz );
return -ENOEXEC;
}
bzimg->rm_memsz = BZI_ASSUMED_RM_SIZE;
@@ -129,13 +121,14 @@ static int bzimage_parse_header ( struct image *image,
syssize = ( ( bzimg->pm_sz + 15 ) / 16 );
/* Check for signatures and determine version */
- if ( bzimg->bzhdr.boot_flag != BZI_BOOT_FLAG ) {
- DBGC ( image, "bzImage %p missing 55AA signature\n", image );
+ if ( bzhdr->boot_flag != BZI_BOOT_FLAG ) {
+ DBGC ( image, "bzImage %s missing 55AA signature\n",
+ image->name );
return -ENOEXEC;
}
- if ( bzimg->bzhdr.header == BZI_SIGNATURE ) {
+ if ( bzhdr->header == BZI_SIGNATURE ) {
/* 2.00+ */
- bzimg->version = bzimg->bzhdr.version;
+ bzimg->version = bzhdr->version;
} else {
/* Pre-2.00. Check that the syssize field is correct,
* as a guard against accepting arbitrary binary data,
@@ -145,20 +138,21 @@ static int bzimage_parse_header ( struct image *image,
* check this field.
*/
bzimg->version = 0x0100;
- if ( bzimg->bzhdr.syssize != syssize ) {
- DBGC ( image, "bzImage %p bad syssize %x (expected "
- "%x)\n", image, bzimg->bzhdr.syssize, syssize );
+ if ( bzhdr->syssize != syssize ) {
+ DBGC ( image, "bzImage %s bad syssize %x (expected "
+ "%x)\n", image->name, bzhdr->syssize,
+ syssize );
return -ENOEXEC;
}
}
/* Determine image type */
is_bzimage = ( ( bzimg->version >= 0x0200 ) ?
- ( bzimg->bzhdr.loadflags & BZI_LOAD_HIGH ) : 0 );
+ ( bzhdr->loadflags & BZI_LOAD_HIGH ) : 0 );
/* Calculate load address of real-mode portion */
bzimg->rm_kernel_seg = ( is_bzimage ? 0x1000 : 0x9000 );
- bzimg->rm_kernel = real_to_user ( bzimg->rm_kernel_seg, 0 );
+ bzimg->rm_kernel = real_to_virt ( bzimg->rm_kernel_seg, 0 );
/* Allow space for the stack and heap */
bzimg->rm_memsz += BZI_STACK_SIZE;
@@ -169,24 +163,24 @@ static int bzimage_parse_header ( struct image *image,
bzimg->rm_memsz += BZI_CMDLINE_SIZE;
/* Calculate load address of protected-mode portion */
- bzimg->pm_kernel = phys_to_user ( is_bzimage ? BZI_LOAD_HIGH_ADDR
+ bzimg->pm_kernel = phys_to_virt ( is_bzimage ? BZI_LOAD_HIGH_ADDR
: BZI_LOAD_LOW_ADDR );
/* Extract video mode */
- bzimg->vid_mode = bzimg->bzhdr.vid_mode;
+ bzimg->vid_mode = bzhdr->vid_mode;
/* Extract memory limit */
bzimg->mem_limit = ( ( bzimg->version >= 0x0203 ) ?
- bzimg->bzhdr.initrd_addr_max : BZI_INITRD_MAX );
+ bzhdr->initrd_addr_max : BZI_INITRD_MAX );
/* Extract command line size */
bzimg->cmdline_size = ( ( bzimg->version >= 0x0206 ) ?
- bzimg->bzhdr.cmdline_size : BZI_CMDLINE_SIZE );
+ bzhdr->cmdline_size : BZI_CMDLINE_SIZE );
- DBGC ( image, "bzImage %p version %04x RM %#lx+%#zx PM %#lx+%#zx "
- "cmdlen %zd\n", image, bzimg->version,
- user_to_phys ( bzimg->rm_kernel, 0 ), bzimg->rm_filesz,
- user_to_phys ( bzimg->pm_kernel, 0 ), bzimg->pm_sz,
+ DBGC ( image, "bzImage %s version %04x RM %#lx+%#zx PM %#lx+%#zx "
+ "cmdlen %zd\n", image->name, bzimg->version,
+ virt_to_phys ( bzimg->rm_kernel ), bzimg->rm_filesz,
+ virt_to_phys ( bzimg->pm_kernel ), bzimg->pm_sz,
bzimg->cmdline_size );
return 0;
@@ -197,49 +191,44 @@ static int bzimage_parse_header ( struct image *image,
*
* @v image bzImage file
* @v bzimg bzImage context
- * @v dst bzImage to update
*/
static void bzimage_update_header ( struct image *image,
- struct bzimage_context *bzimg,
- userptr_t dst ) {
+ struct bzimage_context *bzimg ) {
+ struct bzimage_header *bzhdr = ( bzimg->rm_kernel + BZI_HDR_OFFSET );
+ struct bzimage_cmdline *cmdline;
/* Set loader type */
if ( bzimg->version >= 0x0200 )
- bzimg->bzhdr.type_of_loader = BZI_LOADER_TYPE_IPXE;
+ bzhdr->type_of_loader = BZI_LOADER_TYPE_IPXE;
/* Set heap end pointer */
if ( bzimg->version >= 0x0201 ) {
- bzimg->bzhdr.heap_end_ptr = ( bzimg->rm_heap - 0x200 );
- bzimg->bzhdr.loadflags |= BZI_CAN_USE_HEAP;
+ bzhdr->heap_end_ptr = ( bzimg->rm_heap - 0x200 );
+ bzhdr->loadflags |= BZI_CAN_USE_HEAP;
}
/* Set command line */
if ( bzimg->version >= 0x0202 ) {
- bzimg->bzhdr.cmd_line_ptr = user_to_phys ( bzimg->rm_kernel,
- bzimg->rm_cmdline );
+ bzhdr->cmd_line_ptr = ( virt_to_phys ( bzimg->rm_kernel )
+ + bzimg->rm_cmdline );
} else {
- bzimg->cmdline_magic.magic = BZI_CMDLINE_MAGIC;
- bzimg->cmdline_magic.offset = bzimg->rm_cmdline;
+ cmdline = ( bzimg->rm_kernel + BZI_CMDLINE_OFFSET );
+ cmdline->magic = BZI_CMDLINE_MAGIC;
+ cmdline->offset = bzimg->rm_cmdline;
if ( bzimg->version >= 0x0200 )
- bzimg->bzhdr.setup_move_size = bzimg->rm_memsz;
+ bzhdr->setup_move_size = bzimg->rm_memsz;
}
/* Set video mode */
- bzimg->bzhdr.vid_mode = bzimg->vid_mode;
+ bzhdr->vid_mode = bzimg->vid_mode;
+ DBGC ( image, "bzImage %s vidmode %d\n",
+ image->name, bzhdr->vid_mode );
/* Set initrd address */
if ( bzimg->version >= 0x0200 ) {
- bzimg->bzhdr.ramdisk_image = bzimg->ramdisk_image;
- bzimg->bzhdr.ramdisk_size = bzimg->ramdisk_size;
+ bzhdr->ramdisk_image = virt_to_phys ( bzimg->initrd );
+ bzhdr->ramdisk_size = bzimg->initrd_size;
}
-
- /* Write out header structures */
- copy_to_user ( dst, BZI_CMDLINE_OFFSET, &bzimg->cmdline_magic,
- sizeof ( bzimg->cmdline_magic ) );
- copy_to_user ( dst, BZI_HDR_OFFSET, &bzimg->bzhdr,
- sizeof ( bzimg->bzhdr ) );
-
- DBGC ( image, "bzImage %p vidmode %d\n", image, bzimg->vid_mode );
}
/**
@@ -270,8 +259,9 @@ static int bzimage_parse_cmdline ( struct image *image,
} else {
bzimg->vid_mode = strtoul ( vga, &end, 0 );
if ( *end ) {
- DBGC ( image, "bzImage %p strange \"vga=\" "
- "terminator '%c'\n", image, *end );
+ DBGC ( image, "bzImage %s strange \"vga=\" "
+ "terminator '%c'\n",
+ image->name, *end );
}
}
if ( sep )
@@ -298,8 +288,8 @@ static int bzimage_parse_cmdline ( struct image *image,
case ' ':
break;
default:
- DBGC ( image, "bzImage %p strange \"mem=\" "
- "terminator '%c'\n", image, *end );
+ DBGC ( image, "bzImage %s strange \"mem=\" "
+ "terminator '%c'\n", image->name, *end );
break;
}
bzimg->mem_limit -= 1;
@@ -317,76 +307,13 @@ static int bzimage_parse_cmdline ( struct image *image,
static void bzimage_set_cmdline ( struct image *image,
struct bzimage_context *bzimg ) {
const char *cmdline = ( image->cmdline ? image->cmdline : "" );
- size_t cmdline_len;
+ char *rm_cmdline;
/* Copy command line down to real-mode portion */
- cmdline_len = ( strlen ( cmdline ) + 1 );
- if ( cmdline_len > bzimg->cmdline_size )
- cmdline_len = bzimg->cmdline_size;
- copy_to_user ( bzimg->rm_kernel, bzimg->rm_cmdline,
- cmdline, cmdline_len );
- DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline );
-}
-
-/**
- * Align initrd length
- *
- * @v len Length
- * @ret len Length rounded up to INITRD_ALIGN
- */
-static inline size_t bzimage_align ( size_t len ) {
-
- return ( ( len + INITRD_ALIGN - 1 ) & ~( INITRD_ALIGN - 1 ) );
-}
-
-/**
- * Load initrd
- *
- * @v image bzImage image
- * @v initrd initrd image
- * @v address Address at which to load, or UNULL
- * @ret len Length of loaded image, excluding zero-padding
- */
-static size_t bzimage_load_initrd ( struct image *image,
- struct image *initrd,
- userptr_t address ) {
- const char *filename = cpio_name ( initrd );
- struct cpio_header cpio;
- size_t offset;
- size_t pad_len;
-
- /* Skip hidden images */
- if ( initrd->flags & IMAGE_HIDDEN )
- return 0;
-
- /* Create cpio header for non-prebuilt images */
- offset = cpio_header ( initrd, &cpio );
-
- /* Copy in initrd image body (and cpio header if applicable) */
- if ( address ) {
- memmove_user ( address, offset, initrd->data, 0, initrd->len );
- if ( offset ) {
- memset_user ( address, 0, 0, offset );
- copy_to_user ( address, 0, &cpio, sizeof ( cpio ) );
- copy_to_user ( address, sizeof ( cpio ), filename,
- cpio_name_len ( initrd ) );
- }
- DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)"
- "%s%s\n", image, initrd, user_to_phys ( address, 0 ),
- user_to_phys ( address, offset ),
- user_to_phys ( address, ( offset + initrd->len ) ),
- ( filename ? " " : "" ), ( filename ? filename : "" ) );
- DBGC2_MD5A ( image, user_to_phys ( address, offset ),
- user_to_virt ( address, offset ), initrd->len );
- }
- offset += initrd->len;
-
- /* Zero-pad to next INITRD_ALIGN boundary */
- pad_len = ( ( -offset ) & ( INITRD_ALIGN - 1 ) );
- if ( address )
- memset_user ( address, offset, 0, pad_len );
-
- return offset;
+ rm_cmdline = ( bzimg->rm_kernel + bzimg->rm_cmdline );
+ snprintf ( rm_cmdline, bzimg->cmdline_size, "%s", cmdline );
+ DBGC ( image, "bzImage %s command line \"%s\"\n",
+ image->name, rm_cmdline );
}
/**
@@ -398,48 +325,52 @@ static size_t bzimage_load_initrd ( struct image *image,
*/
static int bzimage_check_initrds ( struct image *image,
struct bzimage_context *bzimg ) {
- struct image *initrd;
- userptr_t bottom;
- size_t len = 0;
+ struct memmap_region region;
+ physaddr_t min;
+ physaddr_t max;
+ physaddr_t dest;
int rc;
/* Calculate total loaded length of initrds */
- for_each_image ( initrd ) {
-
- /* Calculate length */
- len += bzimage_load_initrd ( image, initrd, UNULL );
- len = bzimage_align ( len );
-
- DBGC ( image, "bzImage %p initrd %p from [%#08lx,%#08lx)%s%s\n",
- image, initrd, user_to_phys ( initrd->data, 0 ),
- user_to_phys ( initrd->data, initrd->len ),
- ( initrd->cmdline ? " " : "" ),
- ( initrd->cmdline ? initrd->cmdline : "" ) );
- DBGC2_MD5A ( image, user_to_phys ( initrd->data, 0 ),
- user_to_virt ( initrd->data, 0 ), initrd->len );
- }
+ bzimg->initrd_size = initrd_len();
- /* Calculate lowest usable address */
- bottom = userptr_add ( bzimg->pm_kernel, bzimg->pm_sz );
+ /* Succeed if there are no initrds */
+ if ( ! bzimg->initrd_size )
+ return 0;
- /* Check that total length fits within space available for
- * reshuffling. This is a conservative check, since CPIO
- * headers are not present during reshuffling, but this
- * doesn't hurt and keeps the code simple.
- */
- if ( ( rc = initrd_reshuffle_check ( len, bottom ) ) != 0 ) {
- DBGC ( image, "bzImage %p failed reshuffle check: %s\n",
- image, strerror ( rc ) );
+ /* Calculate available load region after reshuffling */
+ if ( ( rc = initrd_region ( bzimg->initrd_size, &region ) ) != 0 ) {
+ DBGC ( image, "bzImage %s no region for initrds: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
- /* Check that total length fits within kernel's memory limit */
- if ( user_to_phys ( bottom, len ) > bzimg->mem_limit ) {
- DBGC ( image, "bzImage %p not enough space for initrds\n",
- image );
+ /* Limit region to avoiding kernel itself */
+ min = virt_to_phys ( bzimg->pm_kernel + bzimg->pm_sz );
+ if ( min < region.min )
+ min = region.min;
+
+ /* Limit region to kernel's memory limit */
+ max = region.max;
+ if ( max > bzimg->mem_limit )
+ max = bzimg->mem_limit;
+
+ /* Calculate installation address */
+ if ( max < ( bzimg->initrd_size - 1 ) ) {
+ DBGC ( image, "bzImage %s not enough space for initrds\n",
+ image->name );
+ return -ENOBUFS;
+ }
+ dest = ( ( max + 1 - bzimg->initrd_size ) & ~( INITRD_ALIGN - 1 ) );
+ if ( dest < min ) {
+ DBGC ( image, "bzImage %s not enough space for initrds\n",
+ image->name );
return -ENOBUFS;
}
+ bzimg->initrd = phys_to_virt ( dest );
+ DBGC ( image, "bzImage %s loading initrds from %#08lx downwards\n",
+ image->name, max );
return 0;
}
@@ -451,65 +382,21 @@ static int bzimage_check_initrds ( struct image *image,
*/
static void bzimage_load_initrds ( struct image *image,
struct bzimage_context *bzimg ) {
- struct image *initrd;
- struct image *highest = NULL;
- struct image *other;
- userptr_t top;
- userptr_t dest;
- size_t offset;
size_t len;
- /* Reshuffle initrds into desired order */
- initrd_reshuffle ( userptr_add ( bzimg->pm_kernel, bzimg->pm_sz ) );
-
- /* Find highest initrd */
- for_each_image ( initrd ) {
- if ( ( highest == NULL ) ||
- ( userptr_sub ( initrd->data, highest->data ) > 0 ) ) {
- highest = initrd;
- }
- }
-
/* Do nothing if there are no initrds */
- if ( ! highest )
+ if ( ! bzimg->initrd )
return;
- /* Find highest usable address */
- top = userptr_add ( highest->data, bzimage_align ( highest->len ) );
- if ( user_to_phys ( top, -1 ) > bzimg->mem_limit ) {
- top = phys_to_user ( ( bzimg->mem_limit + 1 ) &
- ~( INITRD_ALIGN - 1 ) );
- }
- DBGC ( image, "bzImage %p loading initrds from %#08lx downwards\n",
- image, user_to_phys ( top, -1 ) );
-
- /* Load initrds in order */
- for_each_image ( initrd ) {
-
- /* Calculate cumulative length of following
- * initrds (including padding).
- */
- offset = 0;
- for_each_image ( other ) {
- if ( other == initrd )
- offset = 0;
- offset += bzimage_load_initrd ( image, other, UNULL );
- offset = bzimage_align ( offset );
- }
-
- /* Load initrd at this address */
- dest = userptr_add ( top, -offset );
- len = bzimage_load_initrd ( image, initrd, dest );
-
- /* Record initrd location */
- if ( ! bzimg->ramdisk_image )
- bzimg->ramdisk_image = user_to_phys ( dest, 0 );
- bzimg->ramdisk_size = ( user_to_phys ( dest, len ) -
- bzimg->ramdisk_image );
- }
- DBGC ( image, "bzImage %p initrds at [%#08lx,%#08lx)\n",
- image, bzimg->ramdisk_image,
- ( bzimg->ramdisk_image + bzimg->ramdisk_size ) );
+ /* Reshuffle initrds into desired order */
+ initrd_reshuffle();
+
+ /* Load initrds */
+ DBGC ( image, "bzImage %s initrds at [%#08lx,%#08lx)\n",
+ image->name, virt_to_phys ( bzimg->initrd ),
+ ( virt_to_phys ( bzimg->initrd ) + bzimg->initrd_size ) );
+ len = initrd_load_all ( bzimg->initrd );
+ assert ( len == bzimg->initrd_size );
}
/**
@@ -523,21 +410,20 @@ static int bzimage_exec ( struct image *image ) {
int rc;
/* Read and parse header from image */
- if ( ( rc = bzimage_parse_header ( image, &bzimg,
- image->data ) ) != 0 )
+ if ( ( rc = bzimage_parse_header ( image, &bzimg ) ) != 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 ) );
+ DBGC ( image, "bzImage %s could not prepare RM segment: %s\n",
+ image->name, 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 ) );
+ DBGC ( image, "bzImage %s could not prepare PM segment: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
@@ -553,10 +439,9 @@ static int bzimage_exec ( struct image *image ) {
unregister_image ( image_get ( image ) );
/* 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 );
+ memcpy ( bzimg.rm_kernel, image->data, bzimg.rm_filesz );
+ memcpy ( bzimg.pm_kernel, ( image->data + bzimg.rm_filesz ),
+ bzimg.pm_sz );
/* Store command line */
bzimage_set_cmdline ( image, &bzimg );
@@ -570,10 +455,10 @@ static int bzimage_exec ( struct image *image ) {
bzimage_load_initrds ( image, &bzimg );
/* Update kernel header */
- bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
+ bzimage_update_header ( image, &bzimg );
- DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
- "(stack %04x:%04zx)\n", image, ( bzimg.rm_kernel_seg + 0x20 ),
+ DBGC ( image, "bzImage %s jumping to RM kernel at %04x:0000 (stack "
+ "%04x:%04zx)\n", image->name, ( bzimg.rm_kernel_seg + 0x20 ),
bzimg.rm_kernel_seg, bzimg.rm_heap );
/* Jump to the kernel */
@@ -609,8 +494,7 @@ int bzimage_probe ( struct image *image ) {
int rc;
/* Read and parse header from image */
- if ( ( rc = bzimage_parse_header ( image, &bzimg,
- image->data ) ) != 0 )
+ if ( ( rc = bzimage_parse_header ( image, &bzimg ) ) != 0 )
return rc;
return 0;
diff --git a/src/arch/x86/image/com32.c b/src/arch/x86/image/com32.c
index 6f0e66041..2b31fb2e5 100644
--- a/src/arch/x86/image/com32.c
+++ b/src/arch/x86/image/com32.c
@@ -39,7 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/image.h>
#include <ipxe/segment.h>
#include <ipxe/init.h>
-#include <ipxe/io.h>
+#include <ipxe/memmap.h>
#include <ipxe/console.h>
/**
@@ -49,8 +49,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
* @ret rc Return status code
*/
static int com32_exec_loop ( struct image *image ) {
- struct memory_map memmap;
- unsigned int i;
+ struct memmap_region region;
int state;
uint32_t avail_mem_top;
@@ -59,21 +58,12 @@ static int com32_exec_loop ( struct image *image ) {
switch ( state ) {
case 0: /* First time through; invoke COM32 program */
- /* Get memory map */
- get_memmap ( &memmap );
-
/* Find end of block covering COM32 image loading area */
- for ( i = 0, avail_mem_top = 0 ; i < memmap.count ; i++ ) {
- if ( (memmap.regions[i].start <= COM32_START_PHYS) &&
- (memmap.regions[i].end > COM32_START_PHYS + image->len) ) {
- avail_mem_top = memmap.regions[i].end;
- break;
- }
- }
-
- DBGC ( image, "COM32 %p: available memory top = 0x%x\n",
- image, avail_mem_top );
-
+ memmap_describe ( COM32_START_PHYS, 1, &region );
+ assert ( memmap_is_usable ( &region ) );
+ avail_mem_top = ( COM32_START_PHYS + memmap_size ( &region ) );
+ DBGC ( image, "COM32 %s: available memory top = 0x%x\n",
+ image->name, avail_mem_top );
assert ( avail_mem_top != 0 );
/* Hook COMBOOT API interrupts */
@@ -114,32 +104,32 @@ static int com32_exec_loop ( struct image *image ) {
/* Restore registers */
"popal\n\t" )
:
- : "r" ( avail_mem_top ),
- "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
- "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
- "r" ( get_fbms() * 1024 - ( COM32_BOUNCE_SEG << 4 ) ),
+ : "R" ( avail_mem_top ),
+ "R" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
+ "R" ( virt_to_phys ( com32_farcall_wrapper ) ),
+ "R" ( get_fbms() * 1024 - ( COM32_BOUNCE_SEG << 4 ) ),
"i" ( COM32_BOUNCE_SEG << 4 ),
- "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
- "r" ( virt_to_phys ( image->cmdline ?
+ "R" ( virt_to_phys ( com32_intcall_wrapper ) ),
+ "R" ( virt_to_phys ( image->cmdline ?
image->cmdline : "" ) ),
"i" ( COM32_START_PHYS )
: "memory" );
- DBGC ( image, "COM32 %p: returned\n", image );
+ DBGC ( image, "COM32 %s: returned\n", image->name );
break;
case COMBOOT_EXIT:
- DBGC ( image, "COM32 %p: exited\n", image );
+ DBGC ( image, "COM32 %s: exited\n", image->name );
break;
case COMBOOT_EXIT_RUN_KERNEL:
assert ( image->replacement );
- DBGC ( image, "COM32 %p: exited to run kernel %s\n",
- image, image->replacement->name );
+ DBGC ( image, "COM32 %s: exited to run kernel %s\n",
+ image->name, image->replacement->name );
break;
case COMBOOT_EXIT_COMMAND:
- DBGC ( image, "COM32 %p: exited after executing command\n",
- image );
+ DBGC ( image, "COM32 %s: exited after executing command\n",
+ image->name );
break;
default:
@@ -162,17 +152,15 @@ static int com32_exec_loop ( struct image *image ) {
static int com32_identify ( struct image *image ) {
const char *ext;
static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 };
- uint8_t buf[5];
- if ( image->len >= 5 ) {
+ if ( image->len >= sizeof ( magic ) ) {
/* Check for magic number
* mov eax,21cd4cffh
* B8 FF 4C CD 21
*/
- copy_from_user ( buf, image->data, 0, sizeof(buf) );
- if ( ! memcmp ( buf, magic, sizeof(buf) ) ) {
- DBGC ( image, "COM32 %p: found magic number\n",
- image );
+ if ( memcmp ( image->data, magic, sizeof ( magic) ) == 0 ) {
+ DBGC ( image, "COM32 %s: found magic number\n",
+ image->name );
return 0;
}
}
@@ -182,16 +170,16 @@ static int com32_identify ( struct image *image ) {
ext = strrchr( image->name, '.' );
if ( ! ext ) {
- DBGC ( image, "COM32 %p: no extension\n",
- image );
+ DBGC ( image, "COM32 %s: no extension\n",
+ image->name );
return -ENOEXEC;
}
++ext;
if ( strcasecmp( ext, "c32" ) ) {
- DBGC ( image, "COM32 %p: unrecognized extension %s\n",
- image, ext );
+ DBGC ( image, "COM32 %s: unrecognized extension %s\n",
+ image->name, ext );
return -ENOEXEC;
}
@@ -206,20 +194,20 @@ static int com32_identify ( struct image *image ) {
*/
static int com32_load_image ( struct image *image ) {
size_t filesz, memsz;
- userptr_t buffer;
+ void *buffer;
int rc;
filesz = image->len;
memsz = filesz;
- buffer = phys_to_user ( COM32_START_PHYS );
+ buffer = phys_to_virt ( COM32_START_PHYS );
if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
- DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
- image, strerror ( rc ) );
+ DBGC ( image, "COM32 %s: could not prepare segment: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
/* Copy image to segment */
- memcpy_user ( buffer, 0, image->data, 0, filesz );
+ memcpy ( buffer, image->data, filesz );
return 0;
}
@@ -230,22 +218,20 @@ static int com32_load_image ( struct image *image ) {
* @ret rc Return status code
*/
static int com32_prepare_bounce_buffer ( struct image * image ) {
- unsigned int seg;
- userptr_t seg_userptr;
+ void *seg;
size_t filesz, memsz;
int rc;
- seg = COM32_BOUNCE_SEG;
- seg_userptr = real_to_user ( seg, 0 );
+ seg = real_to_virt ( COM32_BOUNCE_SEG, 0 );
/* Ensure the entire 64k segment is free */
memsz = 0xFFFF;
filesz = 0;
/* Prepare, verify, and load the real-mode segment */
- if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) {
- DBGC ( image, "COM32 %p: could not prepare bounce buffer segment: %s\n",
- image, strerror ( rc ) );
+ if ( ( rc = prep_segment ( seg, filesz, memsz ) ) != 0 ) {
+ DBGC ( image, "COM32 %s: could not prepare bounce buffer segment: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
@@ -261,8 +247,6 @@ static int com32_prepare_bounce_buffer ( struct image * image ) {
static int com32_probe ( struct image *image ) {
int rc;
- DBGC ( image, "COM32 %p: name '%s'\n", image, image->name );
-
/* Check if this is a COMBOOT image */
if ( ( rc = com32_identify ( image ) ) != 0 ) {
return rc;
diff --git a/src/arch/x86/image/comboot.c b/src/arch/x86/image/comboot.c
index 9a847f0ff..6eba027c6 100644
--- a/src/arch/x86/image/comboot.c
+++ b/src/arch/x86/image/comboot.c
@@ -35,7 +35,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <realmode.h>
#include <basemem.h>
#include <comboot.h>
-#include <ipxe/uaccess.h>
#include <ipxe/image.h>
#include <ipxe/segment.h>
#include <ipxe/init.h>
@@ -67,62 +66,53 @@ struct comboot_psp {
*
* @v image COMBOOT image
*/
-static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr ) {
+static void comboot_copy_cmdline ( struct image * image, void *seg ) {
const char *cmdline = ( image->cmdline ? image->cmdline : "" );
int cmdline_len = strlen ( cmdline );
+ uint8_t *psp_cmdline;
+
+ /* Limit length of command line */
if( cmdline_len > COMBOOT_MAX_CMDLINE_LEN )
cmdline_len = COMBOOT_MAX_CMDLINE_LEN;
- uint8_t len_byte = cmdline_len;
- char spc = ' ', cr = '\r';
/* Copy length to byte before command line */
- copy_to_user ( seg_userptr, COMBOOT_PSP_CMDLINE_OFFSET - 1,
- &len_byte, 1 );
+ psp_cmdline = ( seg + COMBOOT_PSP_CMDLINE_OFFSET );
+ psp_cmdline[-1] = cmdline_len;
/* Command line starts with space */
- copy_to_user ( seg_userptr,
- COMBOOT_PSP_CMDLINE_OFFSET,
- &spc, 1 );
+ psp_cmdline[0] = ' ';
/* Copy command line */
- copy_to_user ( seg_userptr,
- COMBOOT_PSP_CMDLINE_OFFSET + 1,
- cmdline, cmdline_len );
+ memcpy ( &psp_cmdline[1], cmdline, cmdline_len );
/* Command line ends with CR */
- copy_to_user ( seg_userptr,
- COMBOOT_PSP_CMDLINE_OFFSET + cmdline_len + 1,
- &cr, 1 );
+ psp_cmdline[ 1 + cmdline_len ] = '\r';
}
/**
* Initialize PSP
*
* @v image COMBOOT image
- * @v seg_userptr segment to initialize
+ * @v seg segment to initialize
*/
-static void comboot_init_psp ( struct image * image, userptr_t seg_userptr ) {
- struct comboot_psp psp;
+static void comboot_init_psp ( struct image * image, void *seg ) {
+ struct comboot_psp *psp;
/* Fill PSP */
+ psp = seg;
/* INT 20h instruction, byte order reversed */
- psp.int20 = 0x20CD;
+ psp->int20 = 0x20CD;
/* get_fbms() returns BIOS free base memory counter, which is in
* kilobytes; x * 1024 / 16 == x * 64 == x << 6 */
- psp.first_non_free_para = get_fbms() << 6;
-
- DBGC ( image, "COMBOOT %p: first non-free paragraph = 0x%x\n",
- image, psp.first_non_free_para );
+ psp->first_non_free_para = get_fbms() << 6;
- /* Copy the PSP to offset 0 of segment.
- * The rest of the PSP was already zeroed by
- * comboot_prepare_segment. */
- copy_to_user ( seg_userptr, 0, &psp, sizeof( psp ) );
+ DBGC ( image, "COMBOOT %s: first non-free paragraph = 0x%x\n",
+ image->name, psp->first_non_free_para );
/* Copy the command line to the PSP */
- comboot_copy_cmdline ( image, seg_userptr );
+ comboot_copy_cmdline ( image, seg );
}
/**
@@ -132,7 +122,7 @@ static void comboot_init_psp ( struct image * image, userptr_t seg_userptr ) {
* @ret rc Return status code
*/
static int comboot_exec_loop ( struct image *image ) {
- userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
+ void *seg = real_to_virt ( COMBOOT_PSP_SEG, 0 );
int state;
state = rmsetjmp ( comboot_return );
@@ -141,7 +131,7 @@ static int comboot_exec_loop ( struct image *image ) {
case 0: /* First time through; invoke COMBOOT program */
/* Initialize PSP */
- comboot_init_psp ( image, seg_userptr );
+ comboot_init_psp ( image, seg );
/* Hook COMBOOT API interrupts */
hook_comboot_interrupts();
@@ -181,23 +171,23 @@ static int comboot_exec_loop ( struct image *image ) {
"xorw %%di, %%di\n\t"
"xorw %%bp, %%bp\n\t"
"lret\n\t" )
- : : "r" ( COMBOOT_PSP_SEG ) : "eax" );
- DBGC ( image, "COMBOOT %p: returned\n", image );
+ : : "R" ( COMBOOT_PSP_SEG ) : "eax" );
+ DBGC ( image, "COMBOOT %s: returned\n", image->name );
break;
case COMBOOT_EXIT:
- DBGC ( image, "COMBOOT %p: exited\n", image );
+ DBGC ( image, "COMBOOT %s: exited\n", image->name );
break;
case COMBOOT_EXIT_RUN_KERNEL:
assert ( image->replacement );
- DBGC ( image, "COMBOOT %p: exited to run kernel %s\n",
- image, image->replacement->name );
+ DBGC ( image, "COMBOOT %s: exited to run kernel %s\n",
+ image->name, image->replacement->name );
break;
case COMBOOT_EXIT_COMMAND:
- DBGC ( image, "COMBOOT %p: exited after executing command\n",
- image );
+ DBGC ( image, "COMBOOT %s: exited after executing command\n",
+ image->name );
break;
default:
@@ -223,16 +213,16 @@ static int comboot_identify ( struct image *image ) {
ext = strrchr( image->name, '.' );
if ( ! ext ) {
- DBGC ( image, "COMBOOT %p: no extension\n",
- image );
+ DBGC ( image, "COMBOOT %s: no extension\n",
+ image->name );
return -ENOEXEC;
}
++ext;
if ( strcasecmp( ext, "cbt" ) ) {
- DBGC ( image, "COMBOOT %p: unrecognized extension %s\n",
- image, ext );
+ DBGC ( image, "COMBOOT %s: unrecognized extension %s\n",
+ image->name, ext );
return -ENOEXEC;
}
@@ -246,12 +236,12 @@ static int comboot_identify ( struct image *image ) {
*/
static int comboot_prepare_segment ( struct image *image )
{
- userptr_t seg_userptr;
+ void *seg;
size_t filesz, memsz;
int rc;
/* Load image in segment */
- seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
+ seg = real_to_virt ( COMBOOT_PSP_SEG, 0 );
/* Allow etra 0x100 bytes before image for PSP */
filesz = image->len + 0x100;
@@ -260,17 +250,17 @@ static int comboot_prepare_segment ( struct image *image )
memsz = 0xFFFF;
/* Prepare, verify, and load the real-mode segment */
- if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) {
- DBGC ( image, "COMBOOT %p: could not prepare segment: %s\n",
- image, strerror ( rc ) );
+ if ( ( rc = prep_segment ( seg, filesz, memsz ) ) != 0 ) {
+ DBGC ( image, "COMBOOT %s: could not prepare segment: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
/* Zero PSP */
- memset_user ( seg_userptr, 0, 0, 0x100 );
+ memset ( seg, 0, 0x100 );
/* Copy image to segment:0100 */
- memcpy_user ( seg_userptr, 0x100, image->data, 0, image->len );
+ memcpy ( ( seg + 0x100 ), image->data, image->len );
return 0;
}
@@ -284,9 +274,6 @@ static int comboot_prepare_segment ( struct image *image )
static int comboot_probe ( struct image *image ) {
int rc;
- DBGC ( image, "COMBOOT %p: name '%s'\n",
- image, image->name );
-
/* Check if this is a COMBOOT image */
if ( ( rc = comboot_identify ( image ) ) != 0 ) {
@@ -307,8 +294,8 @@ static int comboot_exec ( struct image *image ) {
/* Sanity check for filesize */
if( image->len >= 0xFF00 ) {
- DBGC( image, "COMBOOT %p: image too large\n",
- image );
+ DBGC( image, "COMBOOT %s: image too large\n",
+ image->name );
return -ENOEXEC;
}
diff --git a/src/arch/x86/image/elfboot.c b/src/arch/x86/image/elfboot.c
index dc3568929..d0f91d1c0 100644
--- a/src/arch/x86/image/elfboot.c
+++ b/src/arch/x86/image/elfboot.c
@@ -23,8 +23,10 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+#include <string.h>
#include <errno.h>
#include <elf.h>
+#include <librm.h>
#include <ipxe/image.h>
#include <ipxe/elf.h>
#include <ipxe/features.h>
@@ -52,8 +54,8 @@ static int elfboot_exec ( struct image *image ) {
/* Load the image using core ELF support */
if ( ( rc = elf_load ( image, &entry, &max ) ) != 0 ) {
- DBGC ( image, "ELF %p could not load: %s\n",
- image, strerror ( rc ) );
+ DBGC ( image, "ELF %s could not load: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
@@ -63,14 +65,15 @@ static int elfboot_exec ( struct image *image ) {
shutdown_boot();
/* Jump to OS with flat physical addressing */
- DBGC ( image, "ELF %p starting execution at %lx\n", image, entry );
+ DBGC ( image, "ELF %s starting execution at %lx\n",
+ image->name, entry );
__asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t" /* gcc bug */
"call *%%edi\n\t"
"popl %%ebp\n\t" /* gcc bug */ )
: : "D" ( entry )
: "eax", "ebx", "ecx", "edx", "esi", "memory" );
- DBGC ( image, "ELF %p returned\n", image );
+ DBGC ( image, "ELF %s returned\n", image->name );
/* It isn't safe to continue after calling shutdown() */
while ( 1 ) {}
@@ -86,13 +89,13 @@ static int elfboot_exec ( struct image *image ) {
* @v dest Destination address
* @ret rc Return status code
*/
-static int elfboot_check_segment ( struct image *image, Elf_Phdr *phdr,
+static int elfboot_check_segment ( struct image *image, const Elf_Phdr *phdr,
physaddr_t dest ) {
/* Check that ELF segment uses flat physical addressing */
if ( phdr->p_vaddr != dest ) {
- DBGC ( image, "ELF %p uses virtual addressing (phys %x, "
- "virt %x)\n", image, phdr->p_paddr, phdr->p_vaddr );
+ DBGC ( image, "ELF %s uses virtual addressing (phys %x, virt "
+ "%x)\n", image->name, phdr->p_paddr, phdr->p_vaddr );
return -ENOEXEC;
}
@@ -106,7 +109,7 @@ static int elfboot_check_segment ( struct image *image, Elf_Phdr *phdr,
* @ret rc Return status code
*/
static int elfboot_probe ( struct image *image ) {
- Elf32_Ehdr ehdr;
+ const Elf32_Ehdr *ehdr;
static const uint8_t e_ident[] = {
[EI_MAG0] = ELFMAG0,
[EI_MAG1] = ELFMAG1,
@@ -121,16 +124,22 @@ static int elfboot_probe ( struct image *image ) {
int rc;
/* Read ELF header */
- copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
- if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) {
- DBGC ( image, "Invalid ELF identifier\n" );
+ if ( image->len < sizeof ( *ehdr ) ) {
+ DBGC ( image, "ELF %s too short for ELF header\n",
+ image->name );
+ return -ENOEXEC;
+ }
+ ehdr = image->data;
+ if ( memcmp ( ehdr->e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) {
+ DBGC ( image, "ELF %s invalid identifier\n", image->name );
return -ENOEXEC;
}
/* Check that this image uses flat physical addressing */
- if ( ( rc = elf_segments ( image, &ehdr, elfboot_check_segment,
+ if ( ( rc = elf_segments ( image, ehdr, elfboot_check_segment,
&entry, &max ) ) != 0 ) {
- DBGC ( image, "Unloadable ELF image\n" );
+ DBGC ( image, "ELF %s is not loadable: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
diff --git a/src/arch/x86/image/initrd.c b/src/arch/x86/image/initrd.c
deleted file mode 100644
index d7b1f5773..000000000
--- a/src/arch/x86/image/initrd.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <errno.h>
-#include <initrd.h>
-#include <ipxe/image.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/init.h>
-#include <ipxe/memblock.h>
-#include <ipxe/cpio.h>
-
-/** @file
- *
- * Initial ramdisk (initrd) reshuffling
- *
- */
-
-/** Maximum address available for initrd */
-userptr_t initrd_top;
-
-/** Minimum address available for initrd */
-userptr_t initrd_bottom;
-
-/**
- * Squash initrds as high as possible in memory
- *
- * @v top Highest possible address
- * @ret used Lowest address used by initrds
- */
-static userptr_t initrd_squash_high ( userptr_t top ) {
- userptr_t current = top;
- struct image *initrd;
- struct image *highest;
- size_t len;
-
- /* Squash up any initrds already within or below the region */
- while ( 1 ) {
-
- /* Find the highest image not yet in its final position */
- highest = NULL;
- for_each_image ( initrd ) {
- if ( ( userptr_sub ( initrd->data, current ) < 0 ) &&
- ( ( highest == NULL ) ||
- ( userptr_sub ( initrd->data,
- highest->data ) > 0 ) ) ) {
- highest = initrd;
- }
- }
- if ( ! highest )
- break;
-
- /* Move this image to its final position */
- len = ( ( highest->len + INITRD_ALIGN - 1 ) &
- ~( INITRD_ALIGN - 1 ) );
- current = userptr_sub ( current, len );
- DBGC ( &images, "INITRD squashing %s [%#08lx,%#08lx)->"
- "[%#08lx,%#08lx)\n", highest->name,
- user_to_phys ( highest->data, 0 ),
- user_to_phys ( highest->data, highest->len ),
- user_to_phys ( current, 0 ),
- user_to_phys ( current, highest->len ) );
- memmove_user ( current, 0, highest->data, 0, highest->len );
- highest->data = current;
- }
-
- /* Copy any remaining initrds (e.g. embedded images) to the region */
- for_each_image ( initrd ) {
- if ( userptr_sub ( initrd->data, top ) >= 0 ) {
- len = ( ( initrd->len + INITRD_ALIGN - 1 ) &
- ~( INITRD_ALIGN - 1 ) );
- current = userptr_sub ( current, len );
- DBGC ( &images, "INITRD copying %s [%#08lx,%#08lx)->"
- "[%#08lx,%#08lx)\n", initrd->name,
- user_to_phys ( initrd->data, 0 ),
- user_to_phys ( initrd->data, initrd->len ),
- user_to_phys ( current, 0 ),
- user_to_phys ( current, initrd->len ) );
- memcpy_user ( current, 0, initrd->data, 0,
- initrd->len );
- initrd->data = current;
- }
- }
-
- return current;
-}
-
-/**
- * Swap position of two adjacent initrds
- *
- * @v low Lower initrd
- * @v high Higher initrd
- * @v free Free space
- * @v free_len Length of free space
- */
-static void initrd_swap ( struct image *low, struct image *high,
- userptr_t free, size_t free_len ) {
- size_t len = 0;
- size_t frag_len;
- size_t new_len;
-
- DBGC ( &images, "INITRD swapping %s [%#08lx,%#08lx)<->[%#08lx,%#08lx) "
- "%s\n", low->name, user_to_phys ( low->data, 0 ),
- user_to_phys ( low->data, low->len ),
- user_to_phys ( high->data, 0 ),
- user_to_phys ( high->data, high->len ), high->name );
-
- /* Round down length of free space */
- free_len &= ~( INITRD_ALIGN - 1 );
- assert ( free_len > 0 );
-
- /* Swap image data */
- while ( len < high->len ) {
-
- /* Calculate maximum fragment length */
- frag_len = ( high->len - len );
- if ( frag_len > free_len )
- frag_len = free_len;
- new_len = ( ( len + frag_len + INITRD_ALIGN - 1 ) &
- ~( INITRD_ALIGN - 1 ) );
-
- /* Swap fragments */
- memcpy_user ( free, 0, high->data, len, frag_len );
- memmove_user ( low->data, new_len, low->data, len, low->len );
- memcpy_user ( low->data, len, free, 0, frag_len );
- len = new_len;
- }
-
- /* Adjust data pointers */
- high->data = low->data;
- low->data = userptr_add ( low->data, len );
-}
-
-/**
- * Swap position of any two adjacent initrds not currently in the correct order
- *
- * @v free Free space
- * @v free_len Length of free space
- * @ret swapped A pair of initrds was swapped
- */
-static int initrd_swap_any ( userptr_t free, size_t free_len ) {
- struct image *low;
- struct image *high;
- size_t padded_len;
- userptr_t adjacent;
-
- /* Find any pair of initrds that can be swapped */
- for_each_image ( low ) {
-
- /* Calculate location of adjacent image (if any) */
- padded_len = ( ( low->len + INITRD_ALIGN - 1 ) &
- ~( INITRD_ALIGN - 1 ) );
- adjacent = userptr_add ( low->data, padded_len );
-
- /* Search for adjacent image */
- for_each_image ( high ) {
-
- /* Stop search if all remaining potential
- * adjacent images are already in the correct
- * order.
- */
- if ( high == low )
- break;
-
- /* If we have found the adjacent image, swap and exit */
- if ( high->data == adjacent ) {
- initrd_swap ( low, high, free, free_len );
- return 1;
- }
- }
- }
-
- /* Nothing swapped */
- return 0;
-}
-
-/**
- * Dump initrd locations (for debug)
- *
- */
-static void initrd_dump ( void ) {
- struct image *initrd;
-
- /* Do nothing unless debugging is enabled */
- if ( ! DBG_LOG )
- return;
-
- /* Dump initrd locations */
- for_each_image ( initrd ) {
- DBGC ( &images, "INITRD %s at [%#08lx,%#08lx)\n",
- initrd->name, user_to_phys ( initrd->data, 0 ),
- user_to_phys ( initrd->data, initrd->len ) );
- DBGC2_MD5A ( &images, user_to_phys ( initrd->data, 0 ),
- user_to_virt ( initrd->data, 0 ), initrd->len );
- }
-}
-
-/**
- * Reshuffle initrds into desired order at top of memory
- *
- * @v bottom Lowest address available for initrds
- *
- * After this function returns, the initrds have been rearranged in
- * memory and the external heap structures will have been corrupted.
- * Reshuffling must therefore take place immediately prior to jumping
- * to the loaded OS kernel; no further execution within iPXE is
- * permitted.
- */
-void initrd_reshuffle ( userptr_t bottom ) {
- userptr_t top;
- userptr_t used;
- userptr_t free;
- size_t free_len;
-
- /* Calculate limits of available space for initrds */
- top = initrd_top;
- if ( userptr_sub ( initrd_bottom, bottom ) > 0 )
- bottom = initrd_bottom;
-
- /* Debug */
- DBGC ( &images, "INITRD region [%#08lx,%#08lx)\n",
- user_to_phys ( bottom, 0 ), user_to_phys ( top, 0 ) );
- initrd_dump();
-
- /* Squash initrds as high as possible in memory */
- used = initrd_squash_high ( top );
-
- /* Calculate available free space */
- free = bottom;
- free_len = userptr_sub ( used, free );
-
- /* Bubble-sort initrds into desired order */
- while ( initrd_swap_any ( free, free_len ) ) {}
-
- /* Debug */
- initrd_dump();
-}
-
-/**
- * Check that there is enough space to reshuffle initrds
- *
- * @v len Total length of initrds (including padding)
- * @v bottom Lowest address available for initrds
- * @ret rc Return status code
- */
-int initrd_reshuffle_check ( size_t len, userptr_t bottom ) {
- userptr_t top;
- size_t available;
-
- /* Calculate limits of available space for initrds */
- top = initrd_top;
- if ( userptr_sub ( initrd_bottom, bottom ) > 0 )
- bottom = initrd_bottom;
- available = userptr_sub ( top, bottom );
-
- /* Allow for a sensible minimum amount of free space */
- len += INITRD_MIN_FREE_LEN;
-
- /* Check for available space */
- return ( ( len < available ) ? 0 : -ENOBUFS );
-}
-
-/**
- * initrd startup function
- *
- */
-static void initrd_startup ( void ) {
- size_t len;
-
- /* Record largest memory block available. Do this after any
- * allocations made during driver startup (e.g. large host
- * memory blocks for Infiniband devices, which may still be in
- * use at the time of rearranging if a SAN device is hooked)
- * but before any allocations for downloaded images (which we
- * can safely reuse when rearranging).
- */
- len = largest_memblock ( &initrd_bottom );
- initrd_top = userptr_add ( initrd_bottom, len );
-}
-
-/** initrd startup function */
-struct startup_fn startup_initrd __startup_fn ( STARTUP_LATE ) = {
- .name = "initrd",
- .startup = initrd_startup,
-};
diff --git a/src/arch/x86/image/multiboot.c b/src/arch/x86/image/multiboot.c
index cada021ab..40d6941da 100644
--- a/src/arch/x86/image/multiboot.c
+++ b/src/arch/x86/image/multiboot.c
@@ -31,14 +31,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
#include <stdio.h>
+#include <string.h>
#include <errno.h>
#include <assert.h>
#include <realmode.h>
#include <multiboot.h>
-#include <ipxe/uaccess.h>
#include <ipxe/image.h>
#include <ipxe/segment.h>
-#include <ipxe/io.h>
+#include <ipxe/memmap.h>
#include <ipxe/elf.h>
#include <ipxe/init.h>
#include <ipxe/features.h>
@@ -59,6 +59,9 @@ FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
*/
#define MAX_MODULES 8
+/** Maximum number of memory map entries */
+#define MAX_MEMMAP 8
+
/**
* Maximum combined length of command lines
*
@@ -87,14 +90,6 @@ FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
*/
#define MB_UNSUPPORTED_FLAGS ( MB_COMPULSORY_FLAGS & ~MB_SUPPORTED_FLAGS )
-/** A multiboot header descriptor */
-struct multiboot_header_info {
- /** The actual multiboot header */
- struct multiboot_header mb;
- /** Offset of header within the multiboot image */
- size_t offset;
-};
-
/** Multiboot module command lines */
static char __bss16_array ( mb_cmdlines, [MB_MAX_CMDLINE] );
#define mb_cmdlines __use_data16 ( mb_cmdlines )
@@ -114,32 +109,43 @@ static void multiboot_build_memmap ( struct image *image,
struct multiboot_info *mbinfo,
struct multiboot_memory_map *mbmemmap,
unsigned int limit ) {
- struct memory_map memmap;
- unsigned int i;
-
- /* Get memory map */
- get_memmap ( &memmap );
+ struct memmap_region region;
+ unsigned int remaining;
/* Translate into multiboot format */
memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
- for ( i = 0 ; i < memmap.count ; i++ ) {
- if ( i >= limit ) {
- DBGC ( image, "MULTIBOOT %p limit of %d memmap "
- "entries reached\n", image, limit );
+ remaining = limit;
+ for_each_memmap ( &region, 0 ) {
+
+ /* Ignore any non-memory regions */
+ if ( ! ( region.flags & MEMMAP_FL_MEMORY ) )
+ continue;
+ DBGC_MEMMAP ( image, &region );
+
+ /* Check Multiboot memory map limit */
+ if ( ! remaining ) {
+ DBGC ( image, "MULTIBOOT %s limit of %d memmap "
+ "entries reached\n", image->name, limit );
break;
}
- mbmemmap[i].size = ( sizeof ( mbmemmap[i] ) -
- sizeof ( mbmemmap[i].size ) );
- mbmemmap[i].base_addr = memmap.regions[i].start;
- mbmemmap[i].length = ( memmap.regions[i].end -
- memmap.regions[i].start );
- mbmemmap[i].type = MBMEM_RAM;
- mbinfo->mmap_length += sizeof ( mbmemmap[i] );
- if ( memmap.regions[i].start == 0 )
- mbinfo->mem_lower = ( memmap.regions[i].end / 1024 );
- if ( memmap.regions[i].start == 0x100000 )
- mbinfo->mem_upper = ( ( memmap.regions[i].end -
- 0x100000 ) / 1024 );
+
+ /* Populate Multiboot memory map entry */
+ mbmemmap->size = ( sizeof ( *mbmemmap ) -
+ sizeof ( mbmemmap->size ) );
+ mbmemmap->base_addr = region.min;
+ mbmemmap->length = memmap_size ( &region );
+ mbmemmap->type = MBMEM_RAM;
+
+ /* Update Multiboot information */
+ mbinfo->mmap_length += sizeof ( *mbmemmap );
+ if ( mbmemmap->base_addr == 0 )
+ mbinfo->mem_lower = ( mbmemmap->length / 1024 );
+ if ( mbmemmap->base_addr == 0x100000 )
+ mbinfo->mem_upper = ( mbmemmap->length / 1024 );
+
+ /* Move to next Multiboot memory map entry */
+ mbmemmap++;
+ remaining--;
}
}
@@ -199,8 +205,8 @@ static int multiboot_add_modules ( struct image *image, physaddr_t start,
for_each_image ( module_image ) {
if ( mbinfo->mods_count >= limit ) {
- DBGC ( image, "MULTIBOOT %p limit of %d modules "
- "reached\n", image, limit );
+ DBGC ( image, "MULTIBOOT %s limit of %d modules "
+ "reached\n", image->name, limit );
break;
}
@@ -212,18 +218,18 @@ static int multiboot_add_modules ( struct image *image, physaddr_t start,
start = ( ( start + 0xfff ) & ~0xfff );
/* Prepare segment */
- if ( ( rc = prep_segment ( phys_to_user ( start ),
+ if ( ( rc = prep_segment ( phys_to_virt ( start ),
module_image->len,
module_image->len ) ) != 0 ) {
- DBGC ( image, "MULTIBOOT %p could not prepare module "
- "%s: %s\n", image, module_image->name,
+ DBGC ( image, "MULTIBOOT %s could not prepare module "
+ "%s: %s\n", image->name, module_image->name,
strerror ( rc ) );
return rc;
}
/* Copy module */
- memcpy_user ( phys_to_user ( start ), 0,
- module_image->data, 0, module_image->len );
+ memcpy ( phys_to_virt ( start ), module_image->data,
+ module_image->len );
/* Add module to list */
module = &modules[mbinfo->mods_count++];
@@ -231,8 +237,8 @@ static int multiboot_add_modules ( struct image *image, physaddr_t start,
module->mod_end = ( start + module_image->len );
module->string = multiboot_add_cmdline ( module_image );
module->reserved = 0;
- DBGC ( image, "MULTIBOOT %p module %s is [%x,%x)\n",
- image, module_image->name, module->mod_start,
+ DBGC ( image, "MULTIBOOT %s module %s is [%x,%x)\n",
+ image->name, module_image->name, module->mod_start,
module->mod_end );
start += module_image->len;
}
@@ -255,8 +261,7 @@ static char __bss16_array ( mb_bootloader_name, [32] );
#define mb_bootloader_name __use_data16 ( mb_bootloader_name )
/** The multiboot memory map */
-static struct multiboot_memory_map
- __bss16_array ( mbmemmap, [MAX_MEMORY_REGIONS] );
+static struct multiboot_memory_map __bss16_array ( mbmemmap, [MAX_MEMMAP] );
#define mbmemmap __use_data16 ( mbmemmap )
/** The multiboot module list */
@@ -267,94 +272,101 @@ static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] );
* Find multiboot header
*
* @v image Multiboot file
- * @v hdr Multiboot header descriptor to fill in
- * @ret rc Return status code
+ * @ret offset Offset to Multiboot header, or negative error
*/
-static int multiboot_find_header ( struct image *image,
- struct multiboot_header_info *hdr ) {
- uint32_t buf[64];
+static int multiboot_find_header ( struct image *image ) {
+ const struct multiboot_header *mb;
size_t offset;
- unsigned int buf_idx;
uint32_t checksum;
- /* Scan through first 8kB of image file 256 bytes at a time.
- * (Use the buffering to avoid the overhead of a
- * copy_from_user() for every dword.)
- */
- for ( offset = 0 ; offset < 8192 ; offset += sizeof ( buf[0] ) ) {
+ /* Scan through first 8kB of image file */
+ for ( offset = 0 ; offset < 8192 ; offset += 4 ) {
/* Check for end of image */
- if ( offset > image->len )
+ if ( ( offset + sizeof ( *mb ) ) > image->len )
break;
- /* Refill buffer if applicable */
- buf_idx = ( ( offset % sizeof ( buf ) ) / sizeof ( buf[0] ) );
- if ( buf_idx == 0 ) {
- copy_from_user ( buf, image->data, offset,
- sizeof ( buf ) );
- }
+ mb = ( image->data + offset );
/* Check signature */
- if ( buf[buf_idx] != MULTIBOOT_HEADER_MAGIC )
+ if ( mb->magic != MULTIBOOT_HEADER_MAGIC )
continue;
/* Copy header and verify checksum */
- copy_from_user ( &hdr->mb, image->data, offset,
- sizeof ( hdr->mb ) );
- checksum = ( hdr->mb.magic + hdr->mb.flags +
- hdr->mb.checksum );
+ checksum = ( mb->magic + mb->flags + mb->checksum );
if ( checksum != 0 )
continue;
- /* Record offset of multiboot header and return */
- hdr->offset = offset;
- return 0;
+ /* Return header */
+ return offset;
}
/* No multiboot header found */
+ DBGC ( image, "MULTIBOOT %s has no multiboot header\n",
+ image->name );
return -ENOEXEC;
}
/**
* Load raw multiboot image into memory
*
- * @v image Multiboot file
- * @v hdr Multiboot header descriptor
+ * @v image Multiboot image
+ * @v offset Offset to Multiboot header
* @ret entry Entry point
* @ret max Maximum used address
* @ret rc Return status code
*/
-static int multiboot_load_raw ( struct image *image,
- struct multiboot_header_info *hdr,
+static int multiboot_load_raw ( struct image *image, size_t offset,
physaddr_t *entry, physaddr_t *max ) {
- size_t offset;
+ const struct multiboot_header *mb = ( image->data + offset );
size_t filesz;
size_t memsz;
- userptr_t buffer;
+ void *buffer;
int rc;
/* Sanity check */
- if ( ! ( hdr->mb.flags & MB_FLAG_RAW ) ) {
- DBGC ( image, "MULTIBOOT %p is not flagged as a raw image\n",
- image );
+ if ( ! ( mb->flags & MB_FLAG_RAW ) ) {
+ DBGC ( image, "MULTIBOOT %s is not flagged as a raw image\n",
+ image->name );
return -EINVAL;
}
- /* Verify and prepare segment */
- offset = ( hdr->offset - hdr->mb.header_addr + hdr->mb.load_addr );
- filesz = ( hdr->mb.load_end_addr ?
- ( hdr->mb.load_end_addr - hdr->mb.load_addr ) :
+ /* Calculate starting offset within file */
+ if ( ( mb->load_addr > mb->header_addr ) ||
+ ( ( mb->header_addr - mb->load_addr ) > offset ) ) {
+ DBGC ( image, "MULTIBOOT %s has misplaced header\n",
+ image->name );
+ return -EINVAL;
+ }
+ offset -= ( mb->header_addr - mb->load_addr );
+ assert ( offset < image->len );
+
+ /* Calculate length of initialized data */
+ filesz = ( mb->load_end_addr ?
+ ( mb->load_end_addr - mb->load_addr ) :
( image->len - offset ) );
- memsz = ( hdr->mb.bss_end_addr ?
- ( hdr->mb.bss_end_addr - hdr->mb.load_addr ) : filesz );
- buffer = phys_to_user ( hdr->mb.load_addr );
+ if ( filesz > image->len ) {
+ DBGC ( image, "MULTIBOOT %s has overlength data\n",
+ image->name );
+ return -EINVAL;
+ }
+
+ /* Calculate length of uninitialised data */
+ memsz = ( mb->bss_end_addr ?
+ ( mb->bss_end_addr - mb->load_addr ) : filesz );
+ DBGC ( image, "MULTIBOOT %s loading [%zx,%zx) to [%x,%zx,%zx)\n",
+ image->name, offset, ( offset + filesz ), mb->load_addr,
+ ( mb->load_addr + filesz ), ( mb->load_addr + memsz ) );
+
+ /* Verify and prepare segment */
+ buffer = phys_to_virt ( mb->load_addr );
if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
- DBGC ( image, "MULTIBOOT %p could not prepare segment: %s\n",
- image, strerror ( rc ) );
+ DBGC ( image, "MULTIBOOT %s could not prepare segment: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
/* Copy image to segment */
- memcpy_user ( buffer, 0, image->data, offset, filesz );
+ memcpy ( buffer, ( image->data + offset ), filesz );
/* Record execution entry point and maximum used address */
- *entry = hdr->mb.entry_addr;
- *max = ( hdr->mb.load_addr + memsz );
+ *entry = mb->entry_addr;
+ *max = ( mb->load_addr + memsz );
return 0;
}
@@ -373,8 +385,8 @@ static int multiboot_load_elf ( struct image *image, physaddr_t *entry,
/* Load ELF image*/
if ( ( rc = elf_load ( image, entry, max ) ) != 0 ) {
- DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n",
- image, strerror ( rc ) );
+ DBGC ( image, "MULTIBOOT %s ELF image failed to load: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
@@ -388,22 +400,24 @@ static int multiboot_load_elf ( struct image *image, physaddr_t *entry,
* @ret rc Return status code
*/
static int multiboot_exec ( struct image *image ) {
- struct multiboot_header_info hdr;
+ const struct multiboot_header *mb;
physaddr_t entry;
physaddr_t max;
+ int offset;
int rc;
/* Locate multiboot header, if present */
- if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
- DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
- image );
+ offset = multiboot_find_header ( image );
+ if ( offset < 0 ) {
+ rc = offset;
return rc;
}
+ mb = ( image->data + offset );
/* Abort if we detect flags that we cannot support */
- if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
- DBGC ( image, "MULTIBOOT %p flags %08x not supported\n",
- image, ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) );
+ if ( mb->flags & MB_UNSUPPORTED_FLAGS ) {
+ DBGC ( image, "MULTIBOOT %s flags %#08x not supported\n",
+ image->name, ( mb->flags & MB_UNSUPPORTED_FLAGS ) );
return -ENOTSUP;
}
@@ -413,8 +427,10 @@ static int multiboot_exec ( struct image *image ) {
* behaviour.
*/
if ( ( ( rc = multiboot_load_elf ( image, &entry, &max ) ) != 0 ) &&
- ( ( rc = multiboot_load_raw ( image, &hdr, &entry, &max ) ) != 0 ))
+ ( ( rc = multiboot_load_raw ( image, offset, &entry,
+ &max ) ) != 0 ) ) {
return rc;
+ }
/* Populate multiboot information structure */
memset ( &mbinfo, 0, sizeof ( mbinfo ) );
@@ -444,8 +460,8 @@ static int multiboot_exec ( struct image *image ) {
( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
/* Jump to OS with flat physical addressing */
- DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
- image, entry );
+ DBGC ( image, "MULTIBOOT %s starting execution at %lx\n",
+ image->name, entry );
__asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t"
"call *%%edi\n\t"
"popl %%ebp\n\t" )
@@ -454,7 +470,7 @@ static int multiboot_exec ( struct image *image ) {
"D" ( entry )
: "ecx", "edx", "esi", "memory" );
- DBGC ( image, "MULTIBOOT %p returned\n", image );
+ DBGC ( image, "MULTIBOOT %s returned\n", image->name );
/* It isn't safe to continue after calling shutdown() */
while ( 1 ) {}
@@ -469,17 +485,19 @@ static int multiboot_exec ( struct image *image ) {
* @ret rc Return status code
*/
static int multiboot_probe ( struct image *image ) {
- struct multiboot_header_info hdr;
+ const struct multiboot_header *mb;
+ int offset;
int rc;
/* Locate multiboot header, if present */
- if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
- DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
- image );
+ offset = multiboot_find_header ( image );
+ if ( offset < 0 ) {
+ rc = offset;
return rc;
}
- DBGC ( image, "MULTIBOOT %p found header with flags %08x\n",
- image, hdr.mb.flags );
+ mb = ( image->data + offset );
+ DBGC ( image, "MULTIBOOT %s found header at +%#x with flags %#08x\n",
+ image->name, offset, mb->flags );
return 0;
}
diff --git a/src/arch/x86/image/nbi.c b/src/arch/x86/image/nbi.c
index b691bee20..e0a46758e 100644
--- a/src/arch/x86/image/nbi.c
+++ b/src/arch/x86/image/nbi.c
@@ -1,3 +1,4 @@
+#include <string.h>
#include <errno.h>
#include <assert.h>
#include <realmode.h>
@@ -106,12 +107,12 @@ struct ebinfo {
* @ret rc Return status code
*/
static int nbi_prepare_segment ( struct image *image, size_t offset __unused,
- userptr_t dest, size_t filesz, size_t memsz ){
+ void *dest, size_t filesz, size_t memsz ) {
int rc;
if ( ( rc = prep_segment ( dest, filesz, memsz ) ) != 0 ) {
- DBGC ( image, "NBI %p could not prepare segment: %s\n",
- image, strerror ( rc ) );
+ DBGC ( image, "NBI %s could not prepare segment: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
@@ -129,9 +130,9 @@ static int nbi_prepare_segment ( struct image *image, size_t offset __unused,
* @ret rc Return status code
*/
static int nbi_load_segment ( struct image *image, size_t offset,
- userptr_t dest, size_t filesz,
+ void *dest, size_t filesz,
size_t memsz __unused ) {
- memcpy_user ( dest, 0, image->data, offset, filesz );
+ memcpy ( dest, ( image->data + offset ), filesz );
return 0;
}
@@ -144,22 +145,22 @@ static int nbi_load_segment ( struct image *image, size_t offset,
* @ret rc Return status code
*/
static int nbi_process_segments ( struct image *image,
- struct imgheader *imgheader,
+ const struct imgheader *imgheader,
int ( * process ) ( struct image *image,
size_t offset,
- userptr_t dest,
+ void *dest,
size_t filesz,
size_t memsz ) ) {
- struct segheader sh;
+ const struct segheader *sh;
size_t offset = 0;
size_t sh_off;
- userptr_t dest;
+ void *dest;
size_t filesz;
size_t memsz;
int rc;
/* Copy image header to target location */
- dest = real_to_user ( imgheader->location.segment,
+ dest = real_to_virt ( imgheader->location.segment,
imgheader->location.offset );
filesz = memsz = NBI_HEADER_LENGTH;
if ( ( rc = process ( image, offset, dest, filesz, memsz ) ) != 0 )
@@ -170,32 +171,32 @@ static int nbi_process_segments ( struct image *image,
sh_off = NBI_LENGTH ( imgheader->length );
do {
/* Read segment header */
- copy_from_user ( &sh, image->data, sh_off, sizeof ( sh ) );
- if ( sh.length == 0 ) {
+ sh = ( image->data + sh_off );
+ if ( sh->length == 0 ) {
/* Avoid infinite loop? */
- DBGC ( image, "NBI %p invalid segheader length 0\n",
- image );
+ DBGC ( image, "NBI %s invalid segheader length 0\n",
+ image->name );
return -ENOEXEC;
}
/* Calculate segment load address */
- switch ( NBI_LOADADDR_FLAGS ( sh.flags ) ) {
+ switch ( NBI_LOADADDR_FLAGS ( sh->flags ) ) {
case NBI_LOADADDR_ABS:
- dest = phys_to_user ( sh.loadaddr );
+ dest = phys_to_virt ( sh->loadaddr );
break;
case NBI_LOADADDR_AFTER:
- dest = userptr_add ( dest, memsz + sh.loadaddr );
+ dest = ( dest + memsz + sh->loadaddr );
break;
case NBI_LOADADDR_BEFORE:
- dest = userptr_add ( dest, -sh.loadaddr );
+ dest = ( dest - sh->loadaddr );
break;
case NBI_LOADADDR_END:
/* Not correct according to the spec, but
* maintains backwards compatibility with
* previous versions of Etherboot.
*/
- dest = phys_to_user ( ( extmemsize() + 1024 ) * 1024
- - sh.loadaddr );
+ dest = phys_to_virt ( ( extmemsize() + 1024 ) * 1024
+ - sh->loadaddr );
break;
default:
/* Cannot be reached */
@@ -203,10 +204,11 @@ static int nbi_process_segments ( struct image *image,
}
/* Process this segment */
- filesz = sh.imglength;
- memsz = sh.memlength;
+ filesz = sh->imglength;
+ memsz = sh->memlength;
if ( ( offset + filesz ) > image->len ) {
- DBGC ( image, "NBI %p segment outside file\n", image );
+ DBGC ( image, "NBI %s segment outside file\n",
+ image->name );
return -ENOEXEC;
}
if ( ( rc = process ( image, offset, dest,
@@ -216,17 +218,18 @@ static int nbi_process_segments ( struct image *image,
offset += filesz;
/* Next segheader */
- sh_off += NBI_LENGTH ( sh.length );
+ sh_off += NBI_LENGTH ( sh->length );
if ( sh_off >= NBI_HEADER_LENGTH ) {
- DBGC ( image, "NBI %p header overflow\n", image );
+ DBGC ( image, "NBI %s header overflow\n",
+ image->name );
return -ENOEXEC;
}
- } while ( ! NBI_LAST_SEGHEADER ( sh.flags ) );
+ } while ( ! NBI_LAST_SEGHEADER ( sh->flags ) );
if ( offset != image->len ) {
- DBGC ( image, "NBI %p length wrong (file %zd, metadata %zd)\n",
- image, image->len, offset );
+ DBGC ( image, "NBI %s length wrong (file %zd, metadata %zd)\n",
+ image->name, image->len, offset );
return -ENOEXEC;
}
@@ -239,12 +242,13 @@ static int nbi_process_segments ( struct image *image,
* @v imgheader Image header information
* @ret rc Return status code, if image returns
*/
-static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
+static int nbi_boot16 ( struct image *image,
+ const struct imgheader *imgheader ) {
int discard_D, discard_S, discard_b;
int32_t rc;
- DBGC ( image, "NBI %p executing 16-bit image at %04x:%04x\n", image,
- imgheader->execaddr.segoff.segment,
+ DBGC ( image, "NBI %s executing 16-bit image at %04x:%04x\n",
+ image->name, imgheader->execaddr.segoff.segment,
imgheader->execaddr.segoff.offset );
__asm__ __volatile__ (
@@ -277,7 +281,8 @@ static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
* @v imgheader Image header information
* @ret rc Return status code, if image returns
*/
-static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
+static int nbi_boot32 ( struct image *image,
+ const struct imgheader *imgheader ) {
struct ebinfo loaderinfo = {
product_major_version, product_minor_version,
0
@@ -285,8 +290,8 @@ static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
int discard_D, discard_S, discard_b;
int32_t rc;
- DBGC ( image, "NBI %p executing 32-bit image at %lx\n",
- image, imgheader->execaddr.linear );
+ DBGC ( image, "NBI %s executing 32-bit image at %lx\n",
+ image->name, imgheader->execaddr.linear );
/* Jump to OS with flat physical addressing */
__asm__ __volatile__ (
@@ -321,14 +326,15 @@ static int nbi_prepare_dhcp ( struct image *image ) {
boot_netdev = last_opened_netdev();
if ( ! boot_netdev ) {
- DBGC ( image, "NBI %p could not identify a network device\n",
- image );
+ DBGC ( image, "NBI %s could not identify a network device\n",
+ image->name );
return -ENODEV;
}
if ( ( rc = create_fakedhcpack ( boot_netdev, basemem_packet,
sizeof ( basemem_packet ) ) ) != 0 ) {
- DBGC ( image, "NBI %p failed to build DHCP packet\n", image );
+ DBGC ( image, "NBI %s failed to build DHCP packet\n",
+ image->name );
return rc;
}
@@ -342,15 +348,15 @@ static int nbi_prepare_dhcp ( struct image *image ) {
* @ret rc Return status code
*/
static int nbi_exec ( struct image *image ) {
- struct imgheader imgheader;
+ const struct imgheader *imgheader;
int may_return;
int rc;
/* Retrieve image header */
- copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
+ imgheader = image->data;
- DBGC ( image, "NBI %p placing header at %hx:%hx\n", image,
- imgheader.location.segment, imgheader.location.offset );
+ DBGC ( image, "NBI %s placing header at %hx:%hx\n", image->name,
+ imgheader->location.segment, imgheader->location.offset );
/* NBI files can have overlaps between segments; the bss of
* one segment may overlap the initialised data of another. I
@@ -359,10 +365,10 @@ static int nbi_exec ( struct image *image ) {
* passes: first to initialise the segments, then to copy the
* data. This avoids zeroing out already-copied data.
*/
- if ( ( rc = nbi_process_segments ( image, &imgheader,
+ if ( ( rc = nbi_process_segments ( image, imgheader,
nbi_prepare_segment ) ) != 0 )
return rc;
- if ( ( rc = nbi_process_segments ( image, &imgheader,
+ if ( ( rc = nbi_process_segments ( image, imgheader,
nbi_load_segment ) ) != 0 )
return rc;
@@ -371,25 +377,25 @@ static int nbi_exec ( struct image *image ) {
return rc;
/* Shut down now if NBI image will not return */
- may_return = NBI_PROGRAM_RETURNS ( imgheader.flags );
+ may_return = NBI_PROGRAM_RETURNS ( imgheader->flags );
if ( ! may_return )
shutdown_boot();
/* Execute NBI image */
- if ( NBI_LINEAR_EXEC_ADDR ( imgheader.flags ) ) {
- rc = nbi_boot32 ( image, &imgheader );
+ if ( NBI_LINEAR_EXEC_ADDR ( imgheader->flags ) ) {
+ rc = nbi_boot32 ( image, imgheader );
} else {
- rc = nbi_boot16 ( image, &imgheader );
+ rc = nbi_boot16 ( image, imgheader );
}
if ( ! may_return ) {
/* Cannot continue after shutdown() called */
- DBGC ( image, "NBI %p returned %d from non-returnable image\n",
- image, rc );
+ DBGC ( image, "NBI %s returned %d from non-returnable image\n",
+ image->name, rc );
while ( 1 ) {}
}
- DBGC ( image, "NBI %p returned %d\n", image, rc );
+ DBGC ( image, "NBI %s returned %d\n", image->name, rc );
return rc;
}
@@ -401,18 +407,19 @@ static int nbi_exec ( struct image *image ) {
* @ret rc Return status code
*/
static int nbi_probe ( struct image *image ) {
- struct imgheader imgheader;
+ const struct imgheader *imgheader;
/* If we don't have enough data give up */
if ( image->len < NBI_HEADER_LENGTH ) {
- DBGC ( image, "NBI %p too short for an NBI image\n", image );
+ DBGC ( image, "NBI %s too short for an NBI image\n",
+ image->name );
return -ENOEXEC;
}
+ imgheader = image->data;
/* Check image header */
- copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
- if ( imgheader.magic != NBI_MAGIC ) {
- DBGC ( image, "NBI %p has no NBI signature\n", image );
+ if ( imgheader->magic != NBI_MAGIC ) {
+ DBGC ( image, "NBI %s has no NBI signature\n", image->name );
return -ENOEXEC;
}
diff --git a/src/arch/x86/image/pxe_image.c b/src/arch/x86/image/pxe_image.c
index b6bcb18b4..f88eadc09 100644
--- a/src/arch/x86/image/pxe_image.c
+++ b/src/arch/x86/image/pxe_image.c
@@ -30,10 +30,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
+#include <string.h>
#include <pxe.h>
#include <pxe_call.h>
#include <pic8259.h>
-#include <ipxe/uaccess.h>
#include <ipxe/image.h>
#include <ipxe/segment.h>
#include <ipxe/netdevice.h>
@@ -54,24 +54,24 @@ const char *pxe_cmdline;
* @ret rc Return status code
*/
static int pxe_exec ( struct image *image ) {
- userptr_t buffer = real_to_user ( 0, 0x7c00 );
+ void *buffer = real_to_virt ( 0, 0x7c00 );
struct net_device *netdev;
int rc;
/* Verify and prepare segment */
if ( ( rc = prep_segment ( buffer, image->len, image->len ) ) != 0 ) {
- DBGC ( image, "IMAGE %p could not prepare segment: %s\n",
- image, strerror ( rc ) );
+ DBGC ( image, "IMAGE %s could not prepare segment: %s\n",
+ image->name, strerror ( rc ) );
return rc;
}
/* Copy image to segment */
- memcpy_user ( buffer, 0, image->data, 0, image->len );
+ memcpy ( buffer, image->data, image->len );
/* Arbitrarily pick the most recently opened network device */
if ( ( netdev = last_opened_netdev() ) == NULL ) {
- DBGC ( image, "IMAGE %p could not locate PXE net device\n",
- image );
+ DBGC ( image, "IMAGE %s could not locate PXE net device\n",
+ image->name );
return -ENODEV;
}
netdev_get ( netdev );
@@ -142,7 +142,7 @@ int pxe_probe ( struct image *image ) {
* @ret rc Return status code
*/
int pxe_probe_no_mz ( struct image *image ) {
- uint16_t magic;
+ const uint16_t *magic;
int rc;
/* Probe PXE image */
@@ -152,11 +152,11 @@ int pxe_probe_no_mz ( struct image *image ) {
/* Reject image with an "MZ" signature which may indicate an
* EFI image incorrectly handed out to a BIOS system.
*/
- if ( image->len >= sizeof ( magic ) ) {
- copy_from_user ( &magic, image->data, 0, sizeof ( magic ) );
- if ( magic == cpu_to_le16 ( EFI_IMAGE_DOS_SIGNATURE ) ) {
- DBGC ( image, "IMAGE %p may be an EFI image\n",
- image );
+ if ( image->len >= sizeof ( *magic ) ) {
+ magic = image->data;
+ if ( *magic == cpu_to_le16 ( EFI_IMAGE_DOS_SIGNATURE ) ) {
+ DBGC ( image, "IMAGE %s may be an EFI image\n",
+ image->name );
return -ENOTTY;
}
}
diff --git a/src/arch/x86/image/sdi.c b/src/arch/x86/image/sdi.c
index fa2d0b73f..c0cded239 100644
--- a/src/arch/x86/image/sdi.c
+++ b/src/arch/x86/image/sdi.c
@@ -45,63 +45,36 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FEATURE ( FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1 );
/**
- * Parse SDI image header
- *
- * @v image SDI file
- * @v sdi SDI header to fill in
- * @ret rc Return status code
- */
-static int sdi_parse_header ( struct image *image, struct sdi_header *sdi ) {
-
- /* Sanity check */
- if ( image->len < sizeof ( *sdi ) ) {
- DBGC ( image, "SDI %p too short for SDI header\n", image );
- return -ENOEXEC;
- }
-
- /* Read in header */
- copy_from_user ( sdi, image->data, 0, sizeof ( *sdi ) );
-
- /* Check signature */
- if ( sdi->magic != SDI_MAGIC ) {
- DBGC ( image, "SDI %p is not an SDI image\n", image );
- return -ENOEXEC;
- }
-
- return 0;
-}
-
-/**
* Execute SDI image
*
* @v image SDI file
* @ret rc Return status code
*/
static int sdi_exec ( struct image *image ) {
- struct sdi_header sdi;
+ const struct sdi_header *sdi;
uint32_t sdiptr;
- int rc;
- /* Parse image header */
- if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
- return rc;
+ /* Sanity check */
+ assert ( image->len >= sizeof ( *sdi ) );
+ sdi = image->data;
/* Check that image is bootable */
- if ( sdi.boot_size == 0 ) {
- DBGC ( image, "SDI %p is not bootable\n", image );
+ if ( sdi->boot_size == 0 ) {
+ DBGC ( image, "SDI %s is not bootable\n", image->name );
return -ENOTTY;
}
- DBGC ( image, "SDI %p image at %08lx+%08zx\n",
- image, user_to_phys ( image->data, 0 ), image->len );
- DBGC ( image, "SDI %p boot code at %08lx+%llx\n", image,
- user_to_phys ( image->data, sdi.boot_offset ), sdi.boot_size );
+ DBGC ( image, "SDI %s image at %08lx+%08zx\n",
+ image->name, virt_to_phys ( image->data ), image->len );
+ DBGC ( image, "SDI %s boot code at %08llx+%llx\n", image->name,
+ ( virt_to_phys ( image->data ) + sdi->boot_offset ),
+ sdi->boot_size );
/* Copy boot code */
- memcpy_user ( real_to_user ( SDI_BOOT_SEG, SDI_BOOT_OFF ), 0,
- image->data, sdi.boot_offset, sdi.boot_size );
+ memcpy ( real_to_virt ( SDI_BOOT_SEG, SDI_BOOT_OFF ),
+ ( image->data + sdi->boot_offset ), sdi->boot_size );
/* Jump to boot code */
- sdiptr = ( user_to_phys ( image->data, 0 ) | SDI_WTF );
+ sdiptr = ( virt_to_phys ( image->data ) | SDI_WTF );
__asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" )
: : "i" ( SDI_BOOT_SEG ),
"i" ( SDI_BOOT_OFF ),
@@ -122,12 +95,22 @@ static int sdi_exec ( struct image *image ) {
* @ret rc Return status code
*/
static int sdi_probe ( struct image *image ) {
- struct sdi_header sdi;
- int rc;
+ const struct sdi_header *sdi;
- /* Parse image */
- if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
- return rc;
+ /* Sanity check */
+ if ( image->len < sizeof ( *sdi ) ) {
+ DBGC ( image, "SDI %s too short for SDI header\n",
+ image->name );
+ return -ENOEXEC;
+ }
+ sdi = image->data;
+
+ /* Check signature */
+ if ( sdi->magic != SDI_MAGIC ) {
+ DBGC ( image, "SDI %s is not an SDI image\n",
+ image->name );
+ return -ENOEXEC;
+ }
return 0;
}
diff --git a/src/arch/x86/image/ucode.c b/src/arch/x86/image/ucode.c
index 499c0a940..fd4689e00 100644
--- a/src/arch/x86/image/ucode.c
+++ b/src/arch/x86/image/ucode.c
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <assert.h>
#include <errno.h>
#include <ipxe/uaccess.h>
@@ -149,41 +150,38 @@ static const char * ucode_vendor_name ( const union ucode_vendor_id *vendor ) {
*
* @v update Microcode update
* @v control Microcode update control
+ * @v status Microcode update status
* @v summary Microcode update summary
* @v id APIC ID
* @v optional Status report is optional
* @ret rc Return status code
*/
-static int ucode_status ( struct ucode_update *update,
- struct ucode_control *control,
+static int ucode_status ( const struct ucode_update *update,
+ const struct ucode_control *control,
+ const struct ucode_status *status,
struct ucode_summary *summary,
unsigned int id, int optional ) {
- struct ucode_status status;
struct ucode_descriptor *desc;
/* Sanity check */
assert ( id <= control->apic_max );
- /* Read status report */
- copy_from_user ( &status, phys_to_user ( control->status ),
- ( id * sizeof ( status ) ), sizeof ( status ) );
-
/* Ignore empty optional status reports */
- if ( optional && ( ! status.signature ) )
+ if ( optional && ( ! status->signature ) )
return 0;
DBGC ( update, "UCODE %#08x signature %#08x ucode %#08x->%#08x\n",
- id, status.signature, status.before, status.after );
+ id, status->signature, status->before, status->after );
/* Check CPU signature */
- if ( ! status.signature ) {
+ if ( ! status->signature ) {
DBGC2 ( update, "UCODE %#08x has no signature\n", id );
return -ENOENT;
}
/* Check APIC ID is correct */
- if ( status.id != id ) {
+ if ( status->id != id ) {
DBGC ( update, "UCODE %#08x wrong APIC ID %#08x\n",
- id, status.id );
+ id, status->id );
return -EINVAL;
}
@@ -195,29 +193,29 @@ static int ucode_status ( struct ucode_update *update,
}
/* Check microcode was not downgraded */
- if ( status.after < status.before ) {
+ if ( status->after < status->before ) {
DBGC ( update, "UCODE %#08x was downgraded %#08x->%#08x\n",
- id, status.before, status.after );
+ id, status->before, status->after );
return -ENOTTY;
}
/* Check that expected updates (if any) were applied */
for ( desc = update->desc ; desc->signature ; desc++ ) {
- if ( ( desc->signature == status.signature ) &&
- ( status.after < desc->version ) ) {
+ if ( ( desc->signature == status->signature ) &&
+ ( status->after < desc->version ) ) {
DBGC ( update, "UCODE %#08x failed update %#08x->%#08x "
- "(wanted %#08x)\n", id, status.before,
- status.after, desc->version );
+ "(wanted %#08x)\n", id, status->before,
+ status->after, desc->version );
return -EIO;
}
}
/* Update summary */
summary->count++;
- if ( status.before < summary->low )
- summary->low = status.before;
- if ( status.after > summary->high )
- summary->high = status.after;
+ if ( status->before < summary->low )
+ summary->low = status->before;
+ if ( status->after > summary->high )
+ summary->high = status->after;
return 0;
}
@@ -231,13 +229,13 @@ static int ucode_status ( struct ucode_update *update,
* @ret rc Return status code
*/
static int ucode_update_all ( struct image *image,
- struct ucode_update *update,
+ const struct ucode_update *update,
struct ucode_summary *summary ) {
struct ucode_control control;
struct ucode_vendor *vendor;
- userptr_t status;
+ struct ucode_status *status;
unsigned int max;
- unsigned int i;
+ unsigned int id;
size_t len;
int rc;
@@ -248,7 +246,7 @@ static int ucode_update_all ( struct image *image,
/* Allocate status reports */
max = mp_max_cpuid();
- len = ( ( max + 1 ) * sizeof ( struct ucode_status ) );
+ len = ( ( max + 1 ) * sizeof ( *status ) );
status = umalloc ( len );
if ( ! status ) {
DBGC ( image, "UCODE %s could not allocate %d status reports\n",
@@ -256,12 +254,12 @@ static int ucode_update_all ( struct image *image,
rc = -ENOMEM;
goto err_alloc;
}
- memset_user ( status, 0, 0, len );
+ memset ( status, 0, len );
/* Construct control structure */
memset ( &control, 0, sizeof ( control ) );
control.desc = virt_to_phys ( update->desc );
- control.status = user_to_phys ( status, 0 );
+ control.status = virt_to_phys ( status );
vendor = update->vendor;
if ( vendor ) {
control.ver_clear = vendor->ver_clear;
@@ -274,8 +272,9 @@ static int ucode_update_all ( struct image *image,
/* Update microcode on boot processor */
mp_exec_boot ( ucode_update, &control );
- if ( ( rc = ucode_status ( update, &control, summary,
- mp_boot_cpuid(), 0 ) ) != 0 ) {
+ id = mp_boot_cpuid();
+ if ( ( rc = ucode_status ( update, &control, &status[id],
+ summary, id, 0 ) ) != 0 ) {
DBGC ( image, "UCODE %s failed on boot processor: %s\n",
image->name, strerror ( rc ) );
goto err_boot;
@@ -293,9 +292,9 @@ static int ucode_update_all ( struct image *image,
/* Check status reports */
summary->count = 0;
- for ( i = 0 ; i <= max ; i++ ) {
- if ( ( rc = ucode_status ( update, &control, summary,
- i, 1 ) ) != 0 ) {
+ for ( id = 0 ; id <= max ; id++ ) {
+ if ( ( rc = ucode_status ( update, &control, &status[id],
+ summary, id, 1 ) ) != 0 ) {
goto err_status;
}
}
@@ -359,24 +358,22 @@ static void ucode_describe ( struct image *image, size_t start,
* @ret rc Return status code
*/
static int ucode_verify ( struct image *image, size_t start, size_t len ) {
- uint32_t checksum = 0;
- uint32_t dword;
- size_t offset;
+ const uint32_t *dword;
+ uint32_t checksum;
+ unsigned int count;
/* Check length is a multiple of dwords */
- if ( ( len % sizeof ( dword ) ) != 0 ) {
+ if ( ( len % sizeof ( *dword ) ) != 0 ) {
DBGC ( image, "UCODE %s+%#04zx invalid length %#zx\n",
image->name, start, len );
return -EINVAL;
}
+ dword = ( image->data + start );
/* Calculate checksum */
- for ( offset = start ; len ;
- offset += sizeof ( dword ), len -= sizeof ( dword ) ) {
- copy_from_user ( &dword, image->data, offset,
- sizeof ( dword ) );
- checksum += dword;
- }
+ count = ( len / sizeof ( *dword ) );
+ for ( checksum = 0 ; count ; count-- )
+ checksum += *(dword++);
if ( checksum != 0 ) {
DBGC ( image, "UCODE %s+%#04zx bad checksum %#08x\n",
image->name, start, checksum );
@@ -396,9 +393,9 @@ static int ucode_verify ( struct image *image, size_t start, size_t len ) {
*/
static int ucode_parse_intel ( struct image *image, size_t start,
struct ucode_update *update ) {
- struct intel_ucode_header hdr;
- struct intel_ucode_ext_header exthdr;
- struct intel_ucode_ext ext;
+ const struct intel_ucode_header *hdr;
+ const struct intel_ucode_ext_header *exthdr;
+ const struct intel_ucode_ext *ext;
struct ucode_descriptor desc;
size_t remaining;
size_t offset;
@@ -409,27 +406,27 @@ static int ucode_parse_intel ( struct image *image, size_t start,
/* Read header */
remaining = ( image->len - start );
- if ( remaining < sizeof ( hdr ) ) {
+ if ( remaining < sizeof ( *hdr ) ) {
DBGC ( image, "UCODE %s+%#04zx too small for Intel header\n",
image->name, start );
return -ENOEXEC;
}
- copy_from_user ( &hdr, image->data, start, sizeof ( hdr ) );
+ hdr = ( image->data + start );
/* Determine lengths */
- data_len = hdr.data_len;
+ data_len = hdr->data_len;
if ( ! data_len )
data_len = INTEL_UCODE_DATA_LEN;
- len = hdr.len;
+ len = hdr->len;
if ( ! len )
- len = ( sizeof ( hdr ) + data_len );
+ len = ( sizeof ( *hdr ) + data_len );
/* Verify a selection of fields */
- if ( ( hdr.hver != INTEL_UCODE_HVER ) ||
- ( hdr.lver != INTEL_UCODE_LVER ) ||
- ( len < sizeof ( hdr ) ) ||
+ if ( ( hdr->hver != INTEL_UCODE_HVER ) ||
+ ( hdr->lver != INTEL_UCODE_LVER ) ||
+ ( len < sizeof ( *hdr ) ) ||
( len > remaining ) ||
- ( data_len > ( len - sizeof ( hdr ) ) ) ||
+ ( data_len > ( len - sizeof ( *hdr ) ) ) ||
( ( data_len % sizeof ( uint32_t ) ) != 0 ) ||
( ( len % INTEL_UCODE_ALIGN ) != 0 ) ) {
DBGC2 ( image, "UCODE %s+%#04zx is not an Intel update\n",
@@ -444,48 +441,46 @@ static int ucode_parse_intel ( struct image *image, size_t start,
return rc;
/* Populate descriptor */
- desc.signature = hdr.signature;
- desc.version = hdr.version;
- desc.address = user_to_phys ( image->data,
- ( start + sizeof ( hdr ) ) );
+ desc.signature = hdr->signature;
+ desc.version = hdr->version;
+ desc.address = ( virt_to_phys ( image->data ) + start +
+ sizeof ( *hdr ) );
/* Add non-extended descriptor, if applicable */
- ucode_describe ( image, start, &ucode_intel, &desc, hdr.platforms,
+ ucode_describe ( image, start, &ucode_intel, &desc, hdr->platforms,
update );
/* Construct extended descriptors, if applicable */
- offset = ( sizeof ( hdr ) + data_len );
- if ( offset <= ( len - sizeof ( exthdr ) ) ) {
+ offset = ( sizeof ( *hdr ) + data_len );
+ if ( offset <= ( len - sizeof ( *exthdr ) ) ) {
/* Read extended header */
- copy_from_user ( &exthdr, image->data, ( start + offset ),
- sizeof ( exthdr ) );
- offset += sizeof ( exthdr );
+ exthdr = ( image->data + start + offset );
+ offset += sizeof ( *exthdr );
/* Read extended signatures */
- for ( i = 0 ; i < exthdr.count ; i++ ) {
+ for ( i = 0 ; i < exthdr->count ; i++ ) {
/* Read extended signature */
- if ( offset > ( len - sizeof ( ext ) ) ) {
+ if ( offset > ( len - sizeof ( *ext ) ) ) {
DBGC ( image, "UCODE %s+%#04zx extended "
"signature overrun\n",
image->name, start );
return -EINVAL;
}
- copy_from_user ( &ext, image->data, ( start + offset ),
- sizeof ( ext ) );
- offset += sizeof ( ext );
+ ext = ( image->data + start + offset );
+ offset += sizeof ( *ext );
/* Avoid duplicating non-extended descriptor */
- if ( ( ext.signature == hdr.signature ) &&
- ( ext.platforms == hdr.platforms ) ) {
+ if ( ( ext->signature == hdr->signature ) &&
+ ( ext->platforms == hdr->platforms ) ) {
continue;
}
/* Construct descriptor, if applicable */
- desc.signature = ext.signature;
+ desc.signature = ext->signature;
ucode_describe ( image, start, &ucode_intel, &desc,
- ext.platforms, update );
+ ext->platforms, update );
}
}
@@ -502,10 +497,10 @@ static int ucode_parse_intel ( struct image *image, size_t start,
*/
static int ucode_parse_amd ( struct image *image, size_t start,
struct ucode_update *update ) {
- struct amd_ucode_header hdr;
- struct amd_ucode_equivalence equiv;
- struct amd_ucode_patch_header phdr;
- struct amd_ucode_patch patch;
+ const struct amd_ucode_header *hdr;
+ const struct amd_ucode_equivalence *equiv;
+ const struct amd_ucode_patch_header *phdr;
+ const struct amd_ucode_patch *patch;
struct ucode_descriptor desc;
size_t remaining;
size_t offset;
@@ -515,91 +510,85 @@ static int ucode_parse_amd ( struct image *image, size_t start,
/* Read header */
remaining = ( image->len - start );
- if ( remaining < sizeof ( hdr ) ) {
+ if ( remaining < sizeof ( *hdr ) ) {
DBGC ( image, "UCODE %s+%#04zx too small for AMD header\n",
image->name, start );
return -ENOEXEC;
}
- copy_from_user ( &hdr, image->data, start, sizeof ( hdr ) );
+ hdr = ( image->data + start );
/* Check header */
- if ( hdr.magic != AMD_UCODE_MAGIC ) {
+ if ( hdr->magic != AMD_UCODE_MAGIC ) {
DBGC2 ( image, "UCODE %s+%#04zx is not an AMD update\n",
image->name, start );
return -ENOEXEC;
}
DBGC2 ( image, "UCODE %s+%#04zx is an AMD update\n",
image->name, start );
- if ( hdr.type != AMD_UCODE_EQUIV_TYPE ) {
+ if ( hdr->type != AMD_UCODE_EQUIV_TYPE ) {
DBGC ( image, "UCODE %s+%#04zx unsupported equivalence table "
- "type %d\n", image->name, start, hdr.type );
+ "type %d\n", image->name, start, hdr->type );
return -ENOTSUP;
}
- if ( hdr.len > ( remaining - sizeof ( hdr ) ) ) {
+ if ( hdr->len > ( remaining - sizeof ( *hdr ) ) ) {
DBGC ( image, "UCODE %s+%#04zx truncated equivalence table\n",
image->name, start );
return -EINVAL;
}
/* Count number of equivalence table entries */
- offset = sizeof ( hdr );
- for ( count = 0 ; offset < ( sizeof ( hdr ) + hdr.len ) ;
- count++, offset += sizeof ( equiv ) ) {
- copy_from_user ( &equiv, image->data, ( start + offset ),
- sizeof ( equiv ) );
- if ( ! equiv.signature )
+ offset = sizeof ( *hdr );
+ equiv = ( image->data + start + offset );
+ for ( count = 0 ; offset < ( sizeof ( *hdr ) + hdr->len ) ;
+ count++, offset += sizeof ( *equiv ) ) {
+ if ( ! equiv[count].signature )
break;
}
DBGC2 ( image, "UCODE %s+%#04zx has %d equivalence table entries\n",
image->name, start, count );
/* Parse available updates */
- offset = ( sizeof ( hdr ) + hdr.len );
+ offset = ( sizeof ( *hdr ) + hdr->len );
used = 0;
while ( used < count ) {
/* Read patch header */
- if ( ( offset + sizeof ( phdr ) ) > remaining ) {
+ if ( ( offset + sizeof ( *phdr ) ) > remaining ) {
DBGC ( image, "UCODE %s+%#04zx truncated patch "
"header\n", image->name, start );
return -EINVAL;
}
- copy_from_user ( &phdr, image->data, ( start + offset ),
- sizeof ( phdr ) );
- offset += sizeof ( phdr );
+ phdr = ( image->data + start + offset );
+ offset += sizeof ( *phdr );
/* Validate patch header */
- if ( phdr.type != AMD_UCODE_PATCH_TYPE ) {
+ if ( phdr->type != AMD_UCODE_PATCH_TYPE ) {
DBGC ( image, "UCODE %s+%#04zx unsupported patch type "
- "%d\n", image->name, start, phdr.type );
+ "%d\n", image->name, start, phdr->type );
return -ENOTSUP;
}
- if ( phdr.len < sizeof ( patch ) ) {
+ if ( phdr->len < sizeof ( *patch ) ) {
DBGC ( image, "UCODE %s+%#04zx underlength patch\n",
image->name, start );
return -EINVAL;
}
- if ( phdr.len > ( remaining - offset ) ) {
+ if ( phdr->len > ( remaining - offset ) ) {
DBGC ( image, "UCODE %s+%#04zx truncated patch\n",
image->name, start );
return -EINVAL;
}
/* Read patch and construct descriptor */
- copy_from_user ( &patch, image->data, ( start + offset ),
- sizeof ( patch ) );
- desc.version = patch.version;
- desc.address = user_to_phys ( image->data, ( start + offset ) );
- offset += phdr.len;
+ patch = ( image->data + start + offset );
+ desc.version = patch->version;
+ desc.address = ( virt_to_phys ( image->data ) +
+ start + offset );
+ offset += phdr->len;
/* Parse equivalence table to find matching signatures */
for ( i = 0 ; i < count ; i++ ) {
- copy_from_user ( &equiv, image->data,
- ( start + sizeof ( hdr ) +
- ( i * ( sizeof ( equiv ) ) ) ),
- sizeof ( equiv ) );
- if ( patch.id == equiv.id ) {
- desc.signature = equiv.signature;
+ if ( patch->id == equiv[i].id ) {
+ desc.signature = equiv[i].signature;
ucode_describe ( image, start, &ucode_amd,
&desc, 0, update );
used++;
@@ -744,19 +733,19 @@ static int ucode_exec ( struct image *image ) {
* @ret rc Return status code
*/
static int ucode_probe ( struct image *image ) {
- union {
+ const union {
struct intel_ucode_header intel;
struct amd_ucode_header amd;
- } header;
+ } *header;
/* Sanity check */
- if ( image->len < sizeof ( header ) ) {
+ if ( image->len < sizeof ( *header ) ) {
DBGC ( image, "UCODE %s too short\n", image->name );
return -ENOEXEC;
}
/* Read first microcode image header */
- copy_from_user ( &header, image->data, 0, sizeof ( header ) );
+ header = image->data;
/* Check for something that looks like an Intel update
*
@@ -769,19 +758,19 @@ static int ucode_probe ( struct image *image ) {
* the image, and do not want to have a microcode image
* erroneously treated as a PXE boot executable.
*/
- if ( ( header.intel.hver == INTEL_UCODE_HVER ) &&
- ( header.intel.lver == INTEL_UCODE_LVER ) &&
- ( ( header.intel.date.century == 0x19 ) ||
- ( ( header.intel.date.century >= 0x20 ) &&
- ( header.intel.date.century <= 0x29 ) ) ) ) {
+ if ( ( header->intel.hver == INTEL_UCODE_HVER ) &&
+ ( header->intel.lver == INTEL_UCODE_LVER ) &&
+ ( ( header->intel.date.century == 0x19 ) ||
+ ( ( header->intel.date.century >= 0x20 ) &&
+ ( header->intel.date.century <= 0x29 ) ) ) ) {
DBGC ( image, "UCODE %s+%#04zx looks like an Intel update\n",
image->name, ( ( size_t ) 0 ) );
return 0;
}
/* Check for AMD update signature */
- if ( ( header.amd.magic == AMD_UCODE_MAGIC ) &&
- ( header.amd.type == AMD_UCODE_EQUIV_TYPE ) ) {
+ if ( ( header->amd.magic == AMD_UCODE_MAGIC ) &&
+ ( header->amd.type == AMD_UCODE_EQUIV_TYPE ) ) {
DBGC ( image, "UCODE %s+%#04zx looks like an AMD update\n",
image->name, ( ( size_t ) 0 ) );
return 0;