summaryrefslogtreecommitdiffstats
path: root/src/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/Makefile4
-rw-r--r--src/arch/x86/core/cpuid.c5
-rw-r--r--src/arch/x86/core/cpuid_settings.c20
-rw-r--r--src/arch/x86/core/debugcon.c1
-rw-r--r--src/arch/x86/core/gdbmach.c1
-rw-r--r--src/arch/x86/core/pci_autoboot.c1
-rw-r--r--src/arch/x86/core/pcidirect.c4
-rw-r--r--src/arch/x86/core/rdrand.c1
-rw-r--r--src/arch/x86/core/relocate.c96
-rw-r--r--src/arch/x86/core/runtime.c17
-rw-r--r--src/arch/x86/core/video_subr.c1
-rw-r--r--src/arch/x86/core/vram_settings.c5
-rw-r--r--src/arch/x86/core/x86_bigint.c100
-rw-r--r--src/arch/x86/core/x86_io.c69
-rw-r--r--src/arch/x86/core/x86_string.c1
-rw-r--r--src/arch/x86/core/x86_tcpip.c1
-rw-r--r--src/arch/x86/core/x86_uart.c60
-rw-r--r--src/arch/x86/drivers/net/undiisr.S10
-rw-r--r--src/arch/x86/drivers/net/undinet.c53
-rw-r--r--src/arch/x86/drivers/xen/hvm.c1
-rw-r--r--src/arch/x86/hci/commands/cpuid_cmd.c6
-rw-r--r--src/arch/x86/hci/commands/pxe_cmd.c12
-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
-rw-r--r--src/arch/x86/include/basemem.h5
-rw-r--r--src/arch/x86/include/bios_disks.h69
-rw-r--r--src/arch/x86/include/bits/acpi.h1
-rw-r--r--src/arch/x86/include/bits/bigint.h108
-rw-r--r--src/arch/x86/include/bits/bitops.h1
-rw-r--r--src/arch/x86/include/bits/endian.h1
-rw-r--r--src/arch/x86/include/bits/errfile.h5
-rw-r--r--src/arch/x86/include/bits/io.h1
-rw-r--r--src/arch/x86/include/bits/iomap.h1
-rw-r--r--src/arch/x86/include/bits/memmap.h15
-rw-r--r--src/arch/x86/include/bits/nap.h12
-rw-r--r--src/arch/x86/include/bits/ns16550.h60
-rw-r--r--src/arch/x86/include/bits/pci_io.h2
-rw-r--r--src/arch/x86/include/bits/reboot.h1
-rw-r--r--src/arch/x86/include/bits/sanboot.h1
-rw-r--r--src/arch/x86/include/bits/smbios.h1
-rw-r--r--src/arch/x86/include/bits/string.h1
-rw-r--r--src/arch/x86/include/bits/tcpip.h1
-rw-r--r--src/arch/x86/include/bits/time.h1
-rw-r--r--src/arch/x86/include/bits/uaccess.h14
-rw-r--r--src/arch/x86/include/bits/uart.h41
-rw-r--r--src/arch/x86/include/bits/umalloc.h14
-rw-r--r--src/arch/x86/include/bits/xen.h1
-rw-r--r--src/arch/x86/include/initrd.h23
-rw-r--r--src/arch/x86/include/ipxe/bios_nap.h1
-rw-r--r--src/arch/x86/include/ipxe/bios_reboot.h1
-rw-r--r--src/arch/x86/include/ipxe/bios_sanboot.h1
-rw-r--r--src/arch/x86/include/ipxe/bios_smbios.h1
-rw-r--r--src/arch/x86/include/ipxe/cpuid.h4
-rw-r--r--src/arch/x86/include/ipxe/efi/efix86_nap.h18
-rw-r--r--src/arch/x86/include/ipxe/int15.h22
-rw-r--r--src/arch/x86/include/ipxe/iomap_pages.h1
-rw-r--r--src/arch/x86/include/ipxe/memtop_umalloc.h18
-rw-r--r--src/arch/x86/include/ipxe/pcibios.h14
-rw-r--r--src/arch/x86/include/ipxe/pcicloud.h18
-rw-r--r--src/arch/x86/include/ipxe/pcidirect.h14
-rw-r--r--src/arch/x86/include/ipxe/rsdp.h5
-rw-r--r--src/arch/x86/include/ipxe/rtc_time.h1
-rw-r--r--src/arch/x86/include/ipxe/x86_io.h1
-rw-r--r--src/arch/x86/include/libkir.h4
-rw-r--r--src/arch/x86/include/librm.h125
-rw-r--r--src/arch/x86/include/pic8259.h47
-rw-r--r--src/arch/x86/include/pxe.h3
-rw-r--r--src/arch/x86/include/realmode.h16
-rw-r--r--src/arch/x86/interface/efi/efix86_nap.c57
-rw-r--r--src/arch/x86/interface/pcbios/acpi_timer.c9
-rw-r--r--src/arch/x86/interface/pcbios/acpipwr.c19
-rw-r--r--src/arch/x86/interface/pcbios/basemem.c2
-rw-r--r--src/arch/x86/interface/pcbios/bios_cachedhcp.c4
-rw-r--r--src/arch/x86/interface/pcbios/bios_mp.c7
-rw-r--r--src/arch/x86/interface/pcbios/bios_reboot.c11
-rw-r--r--src/arch/x86/interface/pcbios/bios_smbios.c36
-rw-r--r--src/arch/x86/interface/pcbios/biosint.c1
-rw-r--r--src/arch/x86/interface/pcbios/e820mangler.S8
-rw-r--r--src/arch/x86/interface/pcbios/hidemem.c66
-rw-r--r--src/arch/x86/interface/pcbios/int13.c31
-rw-r--r--src/arch/x86/interface/pcbios/int13con.c1
-rw-r--r--src/arch/x86/interface/pcbios/int15.c (renamed from src/arch/x86/interface/pcbios/memmap.c)137
-rw-r--r--src/arch/x86/interface/pcbios/memtop_umalloc.c235
-rw-r--r--src/arch/x86/interface/pcbios/pcibios.c4
-rw-r--r--src/arch/x86/interface/pcbios/pcicloud.c194
-rw-r--r--src/arch/x86/interface/pcbios/rsdp.c42
-rw-r--r--src/arch/x86/interface/pcbios/rtc_entropy.c33
-rw-r--r--src/arch/x86/interface/pcbios/vesafb.c41
-rw-r--r--src/arch/x86/interface/pxe/pxe_call.c37
-rw-r--r--src/arch/x86/interface/pxe/pxe_file.c71
-rw-r--r--src/arch/x86/interface/pxe/pxe_preboot.c9
-rw-r--r--src/arch/x86/interface/pxe/pxe_tftp.c16
-rw-r--r--src/arch/x86/interface/pxe/pxe_udp.c13
-rw-r--r--src/arch/x86/interface/syslinux/com32_call.c24
-rw-r--r--src/arch/x86/interface/syslinux/comboot_call.c90
-rw-r--r--src/arch/x86/interface/vmware/guestinfo.c1
-rw-r--r--src/arch/x86/interface/vmware/vmconsole.c1
-rw-r--r--src/arch/x86/prefix/lkrnprefix.S2
-rw-r--r--src/arch/x86/prefix/pxeprefix.S85
-rw-r--r--src/arch/x86/prefix/unlzma.S6
-rw-r--r--src/arch/x86/scripts/pcbios.lds6
-rw-r--r--src/arch/x86/transitions/librm_mgmt.c56
110 files changed, 1584 insertions, 2502 deletions
diff --git a/src/arch/x86/Makefile b/src/arch/x86/Makefile
index ef801365e..4a4d8ee91 100644
--- a/src/arch/x86/Makefile
+++ b/src/arch/x86/Makefile
@@ -3,9 +3,9 @@
ASM_TCHAR := @
ASM_TCHAR_OPS := @
-# Include common x86 headers
+# Include x86-specific headers
#
-INCDIRS += arch/x86/include
+INCDIRS := arch/$(ARCH)/include arch/x86/include $(INCDIRS)
# x86-specific directories containing source files
#
diff --git a/src/arch/x86/core/cpuid.c b/src/arch/x86/core/cpuid.c
index 1a7c93e83..0461b846e 100644
--- a/src/arch/x86/core/cpuid.c
+++ b/src/arch/x86/core/cpuid.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <string.h>
#include <errno.h>
@@ -84,8 +85,8 @@ int cpuid_supported ( uint32_t function ) {
return rc;
/* Find highest supported function number within this family */
- cpuid ( ( function & CPUID_EXTENDED ), 0, &max_function, &discard_b,
- &discard_c, &discard_d );
+ cpuid ( ( function & ( CPUID_EXTENDED | CPUID_HYPERVISOR ) ), 0,
+ &max_function, &discard_b, &discard_c, &discard_d );
/* Fail if maximum function number is meaningless (e.g. if we
* are attempting to call an extended function on a CPU which
diff --git a/src/arch/x86/core/cpuid_settings.c b/src/arch/x86/core/cpuid_settings.c
index 0b67ee91d..ef0164069 100644
--- a/src/arch/x86/core/cpuid_settings.c
+++ b/src/arch/x86/core/cpuid_settings.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <string.h>
#include <errno.h>
@@ -38,7 +39,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* Bit 31 Extended function
* Bits 30-24 (bit 22 = 1) Subfunction number
- * (bit 22 = 0) Number of consecutive functions to call, minus one
+ * Bit 30 (bit 22 = 0) Hypervisor function
+ * Bits 29-24 (bit 22 = 0) Number of consecutive functions to call, minus one
* Bit 23 Return result as little-endian (used for strings)
* Bit 22 Interpret bits 30-24 as a subfunction number
* Bits 21-18 Unused
@@ -98,7 +100,7 @@ enum cpuid_flags {
* @v tag Setting tag
* @ret function Starting function number
*/
-#define CPUID_FUNCTION( tag ) ( (tag) & 0x800000ffUL )
+#define CPUID_FUNCTION( tag ) ( (tag) & 0xc00000ffUL )
/**
* Extract subfunction number from CPUID setting tag
@@ -109,6 +111,14 @@ enum cpuid_flags {
#define CPUID_SUBFUNCTION( tag ) ( ( (tag) >> 24 ) & 0x7f )
/**
+ * Extract number of consecutive functions from CPUID setting tag
+ *
+ * @v tag Setting tag
+ * @ret num_functions Number of consecutive functions
+ */
+#define CPUID_NUM_FUNCTIONS( tag ) ( ( ( (tag) >> 24 ) & 0x3f ) + 1 )
+
+/**
* Extract register array from CPUID setting tag
*
* @v tag Setting tag
@@ -165,12 +175,13 @@ static int cpuid_settings_fetch ( struct settings *settings,
/* Call each function in turn */
function = CPUID_FUNCTION ( setting->tag );
- subfunction = CPUID_SUBFUNCTION ( setting->tag );
if ( setting->tag & CPUID_USE_SUBFUNCTION ) {
+ function &= ~CPUID_HYPERVISOR;
+ subfunction = CPUID_SUBFUNCTION ( setting->tag );
num_functions = 1;
} else {
- num_functions = ( subfunction + 1 );
subfunction = 0;
+ num_functions = CPUID_NUM_FUNCTIONS ( setting->tag );
}
for ( ; num_functions-- ; function++ ) {
@@ -240,6 +251,7 @@ static void cpuid_settings_init ( void ) {
/** CPUID settings initialiser */
struct init_fn cpuid_settings_init_fn __init_fn ( INIT_NORMAL ) = {
+ .name = "cpuid",
.initialise = cpuid_settings_init,
};
diff --git a/src/arch/x86/core/debugcon.c b/src/arch/x86/core/debugcon.c
index 60de61f55..0e3a5dfc7 100644
--- a/src/arch/x86/core/debugcon.c
+++ b/src/arch/x86/core/debugcon.c
@@ -86,5 +86,6 @@ static void debugcon_init ( void ) {
* Debug port console initialisation function
*/
struct init_fn debugcon_init_fn __init_fn ( INIT_EARLY ) = {
+ .name = "debugcon",
.initialise = debugcon_init,
};
diff --git a/src/arch/x86/core/gdbmach.c b/src/arch/x86/core/gdbmach.c
index af6abfedd..d4d187e35 100644
--- a/src/arch/x86/core/gdbmach.c
+++ b/src/arch/x86/core/gdbmach.c
@@ -31,7 +31,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/uaccess.h>
#include <ipxe/gdbstub.h>
#include <librm.h>
-#include <gdbmach.h>
/** @file
*
diff --git a/src/arch/x86/core/pci_autoboot.c b/src/arch/x86/core/pci_autoboot.c
index 337598091..243e45026 100644
--- a/src/arch/x86/core/pci_autoboot.c
+++ b/src/arch/x86/core/pci_autoboot.c
@@ -44,5 +44,6 @@ static void pci_autoboot_init ( void ) {
/** PCI autoboot device initialisation function */
struct init_fn pci_autoboot_init_fn __init_fn ( INIT_NORMAL ) = {
+ .name = "autoboot",
.initialise = pci_autoboot_init,
};
diff --git a/src/arch/x86/core/pcidirect.c b/src/arch/x86/core/pcidirect.c
index f4659a1ac..887b78a0b 100644
--- a/src/arch/x86/core/pcidirect.c
+++ b/src/arch/x86/core/pcidirect.c
@@ -45,6 +45,7 @@ void pcidirect_prepare ( struct pci_device *pci, int where ) {
PCIDIRECT_CONFIG_ADDRESS );
}
+PROVIDE_PCIAPI_INLINE ( direct, pci_can_probe );
PROVIDE_PCIAPI_INLINE ( direct, pci_discover );
PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_word );
@@ -53,5 +54,4 @@ PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_byte );
PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_word );
PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword );
PROVIDE_PCIAPI_INLINE ( direct, pci_ioremap );
-
-struct pci_api pcidirect_api = PCIAPI_RUNTIME ( direct );
+PROVIDE_PCIAPI_RUNTIME ( direct, PCIAPI_PRIORITY_DIRECT );
diff --git a/src/arch/x86/core/rdrand.c b/src/arch/x86/core/rdrand.c
index 850ab1f11..05fc3cd23 100644
--- a/src/arch/x86/core/rdrand.c
+++ b/src/arch/x86/core/rdrand.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
/** @file
*
diff --git a/src/arch/x86/core/relocate.c b/src/arch/x86/core/relocate.c
index 765d46560..3cdc53c2e 100644
--- a/src/arch/x86/core/relocate.c
+++ b/src/arch/x86/core/relocate.c
@@ -1,4 +1,5 @@
-#include <ipxe/io.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/memmap.h>
#include <registers.h>
/*
@@ -41,82 +42,73 @@ extern char _etextdata[];
* to the prefix in %edi.
*/
__asmcall void relocate ( struct i386_all_regs *ix86 ) {
- struct memory_map memmap;
- uint32_t start, end, size, padded_size, max;
- uint32_t new_start, new_end;
- unsigned i;
+ struct memmap_region region;
+ physaddr_t start, end, max;
+ physaddr_t new_start, new_end;
+ physaddr_t r_start, r_end;
+ size_t size, padded_size;
- /* Get memory map and current location */
- get_memmap ( &memmap );
+ /* Show whole memory map (for debugging) */
+ memmap_dump_all ( 0 );
+
+ /* Get current location */
start = virt_to_phys ( _textdata );
end = virt_to_phys ( _etextdata );
size = ( end - start );
padded_size = ( size + ALIGN - 1 );
- DBG ( "Relocate: currently at [%x,%x)\n"
- "...need %x bytes for %d-byte alignment\n",
- start, end, padded_size, ALIGN );
+ DBGC ( &region, "Relocate: currently at [%#08lx,%#08lx)\n"
+ "...need %#zx bytes for %d-byte alignment\n",
+ start, end, padded_size, ALIGN );
/* Determine maximum usable address */
max = MAX_ADDR;
if ( ix86->regs.ebp < max ) {
max = ix86->regs.ebp;
- DBG ( "Limiting relocation to [0,%x)\n", max );
+ DBGC ( &region, "Limiting relocation to [0,%#08lx)\n", max );
}
/* Walk through the memory map and find the highest address
- * below 4GB that iPXE will fit into.
+ * above the current iPXE and below 4GB that iPXE will fit
+ * into.
*/
new_end = end;
- for ( i = 0 ; i < memmap.count ; i++ ) {
- struct memory_region *region = &memmap.regions[i];
- uint32_t r_start, r_end;
+ for_each_memmap_from ( &region, end, 0 ) {
- DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
-
/* Truncate block to maximum address. This will be
- * less than 4GB, which means that we can get away
- * with using just 32-bit arithmetic after this stage.
+ * strictly less than 4GB, which means that we can get
+ * away with using just 32-bit arithmetic after this
+ * stage.
*/
- if ( region->start > max ) {
- DBG ( "...starts after max=%x\n", max );
+ DBGC_MEMMAP ( &region, &region );
+ if ( region.min > max ) {
+ DBGC ( &region, "...starts after max=%#08lx\n", max );
+ break;
+ }
+ r_start = region.min;
+ if ( ! memmap_is_usable ( &region ) ) {
+ DBGC ( &region, "...not usable\n" );
continue;
}
- r_start = region->start;
- if ( region->end > max ) {
- DBG ( "...end truncated to max=%x\n", max );
+ r_end = ( r_start + memmap_size ( &region ) );
+ if ( ( r_end == 0 ) || ( r_end > max ) ) {
+ DBGC ( &region, "...end truncated to max=%#08lx\n",
+ max );
r_end = max;
- } else {
- r_end = region->end;
- }
- DBG ( "...usable portion is [%x,%x)\n", r_start, r_end );
-
- /* If we have rounded down r_end below r_ start, skip
- * this block.
- */
- if ( r_end < r_start ) {
- DBG ( "...truncated to negative size\n" );
- continue;
}
+ DBGC ( &region, "...usable portion is [%#08lx,%#08lx)\n",
+ r_start, r_end );
/* Check that there is enough space to fit in iPXE */
- if ( ( r_end - r_start ) < size ) {
- DBG ( "...too small (need %x bytes)\n", size );
+ if ( ( r_end - r_start ) < padded_size ) {
+ DBGC ( &region, "...too small (need %#zx bytes)\n",
+ padded_size );
continue;
}
- /* If the start address of the iPXE we would
- * place in this block is higher than the end address
- * of the current highest block, use this block.
- *
- * Note that this avoids overlaps with the current
- * iPXE, as well as choosing the highest of all viable
- * blocks.
- */
- if ( ( r_end - size ) > new_end ) {
- new_end = r_end;
- DBG ( "...new best block found.\n" );
- }
+ /* Use highest block with enough space */
+ new_end = r_end;
+ DBGC ( &region, "...new best block found.\n" );
}
/* Calculate new location of iPXE, and align it to the
@@ -126,9 +118,9 @@ __asmcall void relocate ( struct i386_all_regs *ix86 ) {
new_start += ( ( start - new_start ) & ( ALIGN - 1 ) );
new_end = new_start + size;
- DBG ( "Relocating from [%x,%x) to [%x,%x)\n",
- start, end, new_start, new_end );
-
+ DBGC ( &region, "Relocating from [%#08lx,%#08lx) to [%#08lx,%#08lx)\n",
+ start, end, new_start, new_end );
+
/* Let prefix know what to copy */
ix86->regs.esi = start;
ix86->regs.edi = new_start;
diff --git a/src/arch/x86/core/runtime.c b/src/arch/x86/core/runtime.c
index 02072b5bf..86083b1f9 100644
--- a/src/arch/x86/core/runtime.c
+++ b/src/arch/x86/core/runtime.c
@@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
@@ -69,6 +70,7 @@ static void cmdline_image_free ( struct refcnt *refcnt ) {
struct image *image = container_of ( refcnt, struct image, refcnt );
DBGC ( image, "RUNTIME freeing command line\n" );
+ free_image ( refcnt );
free ( cmdline_copy );
}
@@ -76,6 +78,7 @@ static void cmdline_image_free ( struct refcnt *refcnt ) {
static struct image cmdline_image = {
.refcnt = REF_INIT ( cmdline_image_free ),
.name = "<CMDLINE>",
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ),
.type = &script_image_type,
};
@@ -114,9 +117,7 @@ static void cmdline_strip ( char *cmdline, const char *cruft ) {
* @ret rc Return status code
*/
static int cmdline_init ( void ) {
- userptr_t cmdline_user;
char *cmdline;
- size_t len;
int rc;
/* Do nothing if no command line was specified */
@@ -124,19 +125,15 @@ static int cmdline_init ( void ) {
DBGC ( colour, "RUNTIME found no command line\n" );
return 0;
}
- cmdline_user = phys_to_user ( cmdline_phys );
- len = ( strlen_user ( cmdline_user, 0 ) + 1 /* NUL */ );
/* Allocate and copy command line */
- cmdline_copy = malloc ( len );
+ cmdline_copy = strdup ( phys_to_virt ( cmdline_phys ) );
if ( ! cmdline_copy ) {
- DBGC ( colour, "RUNTIME could not allocate %zd bytes for "
- "command line\n", len );
+ DBGC ( colour, "RUNTIME could not allocate command line\n" );
rc = -ENOMEM;
goto err_alloc_cmdline_copy;
}
cmdline = cmdline_copy;
- copy_from_user ( cmdline, cmdline_user, 0, len );
DBGC ( colour, "RUNTIME found command line \"%s\" at %08x\n",
cmdline, cmdline_phys );
@@ -151,7 +148,7 @@ static int cmdline_init ( void ) {
DBGC ( colour, "RUNTIME using command line \"%s\"\n", cmdline );
/* Prepare and register image */
- cmdline_image.data = virt_to_user ( cmdline );
+ cmdline_image.data = cmdline;
cmdline_image.len = strlen ( cmdline );
if ( cmdline_image.len ) {
if ( ( rc = register_image ( &cmdline_image ) ) != 0 ) {
@@ -193,7 +190,7 @@ static int initrd_init ( void ) {
initrd_phys, ( initrd_phys + initrd_len ) );
/* Create initrd image */
- image = image_memory ( "<INITRD>", phys_to_user ( initrd_phys ),
+ image = image_memory ( "<INITRD>", phys_to_virt ( initrd_phys ),
initrd_len );
if ( ! image ) {
DBGC ( colour, "RUNTIME could not create initrd image\n" );
diff --git a/src/arch/x86/core/video_subr.c b/src/arch/x86/core/video_subr.c
index f5cc4cdd4..4e9ef466f 100644
--- a/src/arch/x86/core/video_subr.c
+++ b/src/arch/x86/core/video_subr.c
@@ -109,5 +109,6 @@ struct console_driver vga_console __console_driver = {
};
struct init_fn video_init_fn __init_fn ( INIT_EARLY ) = {
+ .name = "video",
.initialise = video_init,
};
diff --git a/src/arch/x86/core/vram_settings.c b/src/arch/x86/core/vram_settings.c
index 9c169b40c..a97a463fe 100644
--- a/src/arch/x86/core/vram_settings.c
+++ b/src/arch/x86/core/vram_settings.c
@@ -23,6 +23,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+#include <string.h>
#include <ipxe/uaccess.h>
#include <ipxe/settings.h>
@@ -47,12 +48,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* @ret len Length of setting data, or negative error
*/
static int vram_fetch ( void *data, size_t len ) {
- userptr_t vram = phys_to_user ( VRAM_BASE );
+ const void *vram = phys_to_virt ( VRAM_BASE );
/* Copy video RAM */
if ( len > VRAM_LEN )
len = VRAM_LEN;
- copy_from_user ( data, vram, 0, len );
+ memcpy ( data, vram, len );
return VRAM_LEN;
}
diff --git a/src/arch/x86/core/x86_bigint.c b/src/arch/x86/core/x86_bigint.c
deleted file mode 100644
index 74e5da9a2..000000000
--- a/src/arch/x86/core/x86_bigint.c
+++ /dev/null
@@ -1,100 +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 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 <stdint.h>
-#include <string.h>
-#include <ipxe/bigint.h>
-
-/** @file
- *
- * Big integer support
- */
-
-/**
- * Multiply big integers
- *
- * @v multiplicand0 Element 0 of big integer to be multiplied
- * @v multiplicand_size Number of elements in multiplicand
- * @v multiplier0 Element 0 of big integer to be multiplied
- * @v multiplier_size Number of elements in multiplier
- * @v result0 Element 0 of big integer to hold result
- */
-void bigint_multiply_raw ( const uint32_t *multiplicand0,
- unsigned int multiplicand_size,
- const uint32_t *multiplier0,
- unsigned int multiplier_size,
- uint32_t *result0 ) {
- unsigned int result_size = ( multiplicand_size + multiplier_size );
- const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
- *multiplicand = ( ( const void * ) multiplicand0 );
- const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
- *multiplier = ( ( const void * ) multiplier0 );
- bigint_t ( result_size ) __attribute__ (( may_alias ))
- *result = ( ( void * ) result0 );
- unsigned int i;
- unsigned int j;
- uint32_t multiplicand_element;
- uint32_t multiplier_element;
- uint32_t *result_elements;
- uint32_t discard_a;
- uint32_t discard_d;
- long index;
-
- /* Zero result */
- memset ( result, 0, sizeof ( *result ) );
-
- /* Multiply integers one element at a time */
- for ( i = 0 ; i < multiplicand_size ; i++ ) {
- multiplicand_element = multiplicand->element[i];
- for ( j = 0 ; j < multiplier_size ; j++ ) {
- multiplier_element = multiplier->element[j];
- result_elements = &result->element[ i + j ];
- /* Perform a single multiply, and add the
- * resulting double-element into the result,
- * carrying as necessary. The carry can
- * never overflow beyond the end of the
- * result, since:
- *
- * a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
- */
- __asm__ __volatile__ ( "mull %5\n\t"
- "addl %%eax, (%6,%2,4)\n\t"
- "adcl %%edx, 4(%6,%2,4)\n\t"
- "\n1:\n\t"
- "adcl $0, 8(%6,%2,4)\n\t"
- "inc %2\n\t"
- /* Does not affect CF */
- "jc 1b\n\t"
- : "=&a" ( discard_a ),
- "=&d" ( discard_d ),
- "=&r" ( index ),
- "+m" ( *result )
- : "0" ( multiplicand_element ),
- "g" ( multiplier_element ),
- "r" ( result_elements ),
- "2" ( 0 ) );
- }
- }
-}
diff --git a/src/arch/x86/core/x86_io.c b/src/arch/x86/core/x86_io.c
index 6c6b6e1e7..270ed7bef 100644
--- a/src/arch/x86/core/x86_io.c
+++ b/src/arch/x86/core/x86_io.c
@@ -32,6 +32,69 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
+/** Threshold for port I/O-mapped addresses
+ *
+ * On x86, port I/O instructions (inb/outb/etc) can take only an 8-bit
+ * or 16-bit address (in %dx). All I/O ports must therefore have a
+ * value in the first 64kB of the address space.
+ *
+ * Virtual addresses below 64kB can never be MMIO addresses:
+ *
+ * - In the UEFI memory model and x86_64 BIOS memory model, virtual
+ * addresses below 64kB are identity-mapped to the corresponding
+ * physical address. Since the first 64kB of address space is
+ * always RAM, no MMIO device can exist within this region.
+ *
+ * - In the i386 BIOS memory model, virtual addresses below 64kB cover
+ * the iPXE binary itself (which starts at address zero). Since the
+ * size of .textdata can never realistically be below 64kB (not
+ * least since the heap alone is 512kB), and since iPXE is placed
+ * into RAM as a contiguous block, no MMIO device can exist within
+ * this region.
+ *
+ * We therefore know that any (virtual) address returned by ioremap()
+ * must be outside the first 64kB of the address space. We can
+ * therefore use this as a threshold to determine whether a given
+ * address is a port I/O address or an MMIO address.
+ */
+#define PIO_THRESHOLD 0x10000
+
+/**
+ * Read from I/O-mapped or memory-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+#define X86_IOREADX( _api_func, _suffix, _type ) \
+static _type x86_ ## _api_func ( volatile _type *io_addr ) { \
+ if ( ( ( intptr_t ) io_addr ) < PIO_THRESHOLD ) { \
+ return in ## _suffix ( io_addr ); \
+ } else { \
+ return read ## _suffix ( io_addr ); \
+ } \
+}
+X86_IOREADX ( ioread8, b, uint8_t );
+X86_IOREADX ( ioread16, w, uint16_t );
+X86_IOREADX ( ioread32, l, uint32_t );
+
+/**
+ * Write to I/O-mapped or memory-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+#define X86_IOWRITEX( _api_func, _suffix, _type ) \
+static void x86_ ## _api_func ( _type data, volatile _type *io_addr ) { \
+ if ( ( ( intptr_t ) io_addr ) < PIO_THRESHOLD ) { \
+ out ## _suffix ( data, io_addr ); \
+ } else { \
+ write ## _suffix ( data, io_addr ); \
+ } \
+}
+X86_IOWRITEX ( iowrite8, b, uint8_t );
+X86_IOWRITEX ( iowrite16, w, uint16_t );
+X86_IOWRITEX ( iowrite32, l, uint32_t );
+
/**
* Read 64-bit qword from memory-mapped device
*
@@ -101,3 +164,9 @@ PROVIDE_IOAPI_INLINE ( x86, writeq );
PROVIDE_IOAPI ( x86, readq, i386_readq );
PROVIDE_IOAPI ( x86, writeq, i386_writeq );
#endif
+PROVIDE_IOAPI ( x86, ioread8, x86_ioread8 );
+PROVIDE_IOAPI ( x86, ioread16, x86_ioread16 );
+PROVIDE_IOAPI ( x86, ioread32, x86_ioread32 );
+PROVIDE_IOAPI ( x86, iowrite8, x86_iowrite8 );
+PROVIDE_IOAPI ( x86, iowrite16, x86_iowrite16 );
+PROVIDE_IOAPI ( x86, iowrite32, x86_iowrite32 );
diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c
index 1a1e79dac..923552f66 100644
--- a/src/arch/x86/core/x86_string.c
+++ b/src/arch/x86/core/x86_string.c
@@ -28,6 +28,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <string.h>
#include <config/defaults.h>
diff --git a/src/arch/x86/core/x86_tcpip.c b/src/arch/x86/core/x86_tcpip.c
index ed323d5d0..b3bfe2546 100644
--- a/src/arch/x86/core/x86_tcpip.c
+++ b/src/arch/x86/core/x86_tcpip.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
/** @file
*
diff --git a/src/arch/x86/core/x86_uart.c b/src/arch/x86/core/x86_uart.c
index e455775bf..03809ff9b 100644
--- a/src/arch/x86/core/x86_uart.c
+++ b/src/arch/x86/core/x86_uart.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ * Copyright (C) 2025 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
@@ -29,41 +29,47 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
-#include <errno.h>
-#include <ipxe/uart.h>
+#include <string.h>
+#include <ipxe/serial.h>
+#include <ipxe/ns16550.h>
-/** UART port bases */
-static uint16_t uart_base[] = {
- [COM1] = 0x3f8,
- [COM2] = 0x2f8,
- [COM3] = 0x3e8,
- [COM4] = 0x2e8,
-};
+/** Define a fixed ISA UART */
+#define ISA_UART( NAME, BASE ) \
+ static struct ns16550_uart ns16550_ ## NAME = { \
+ .base = ( ( void * ) (BASE) ), \
+ .clock = NS16550_CLK_DEFAULT, \
+ }; \
+ struct uart NAME = { \
+ .refcnt = REF_INIT ( ref_no_free ), \
+ .name = #NAME, \
+ .op = &ns16550_operations, \
+ .priv = &ns16550_ ## NAME, \
+ }
+
+/* Fixed ISA UARTs */
+ISA_UART ( com1, COM1_BASE );
+ISA_UART ( com2, COM2_BASE );
+ISA_UART ( com3, COM3_BASE );
+ISA_UART ( com4, COM4_BASE );
/**
- * Select UART port
+ * Register fixed ISA UARTs
*
- * @v uart UART
- * @v port Port number, or 0 to disable
* @ret rc Return status code
*/
-int uart_select ( struct uart *uart, unsigned int port ) {
+int uart_register_fixed ( void ) {
+ static struct uart *ports[] = { COM1, COM2, COM3, COM4 };
+ unsigned int i;
int rc;
- /* Set new UART base */
- if ( port >= ( sizeof ( uart_base ) / sizeof ( uart_base[0] ) ) ) {
- rc = -ENODEV;
- goto err;
+ /* Register all fixed ISA UARTs */
+ for ( i = 0 ; i < ( sizeof ( ports ) / sizeof ( ports[0] ) ) ; i++ ) {
+ if ( ( rc = uart_register ( ports[i] ) ) != 0 ) {
+ DBGC ( ports[i], "UART could not register %s: %s\n",
+ ports[i]->name, strerror ( rc ) );
+ return rc;
+ }
}
- uart->base = ( ( void * ) ( intptr_t ) uart_base[port] );
-
- /* Check that UART exists */
- if ( ( rc = uart_exists ( uart ) ) != 0 )
- goto err;
return 0;
-
- err:
- uart->base = NULL;
- return rc;
}
diff --git a/src/arch/x86/drivers/net/undiisr.S b/src/arch/x86/drivers/net/undiisr.S
index 8ba5c5354..0b07cb396 100644
--- a/src/arch/x86/drivers/net/undiisr.S
+++ b/src/arch/x86/drivers/net/undiisr.S
@@ -33,8 +33,16 @@ undiisr:
/* Check that we have an UNDI entry point */
cmpw $0, undinet_entry_point
je chain
-
+
+ /* Mask interrupt and set rearm flag */
+ movw undiisr_imr, %dx
+ inb %dx, %al
+ orb undiisr_bit, %al
+ outb %al, %dx
+ movb %al, undiisr_rearm
+
/* Issue UNDI API call */
+ movw %ds, %ax
movw %ax, %es
movw $undinet_params, %di
movw $PXENV_UNDI_ISR, %bx
diff --git a/src/arch/x86/drivers/net/undinet.c b/src/arch/x86/drivers/net/undinet.c
index 43cb18bfe..f4f78432a 100644
--- a/src/arch/x86/drivers/net/undinet.c
+++ b/src/arch/x86/drivers/net/undinet.c
@@ -373,6 +373,18 @@ extern void undiisr ( void );
uint8_t __data16 ( undiisr_irq );
#define undiisr_irq __use_data16 ( undiisr_irq )
+/** IRQ mask register */
+uint16_t __data16 ( undiisr_imr );
+#define undiisr_imr __use_data16 ( undiisr_imr )
+
+/** IRQ mask bit */
+uint8_t __data16 ( undiisr_bit );
+#define undiisr_bit __use_data16 ( undiisr_bit )
+
+/** IRQ rearm flag */
+uint8_t __data16 ( undiisr_rearm );
+#define undiisr_rearm __use_data16 ( undiisr_rearm )
+
/** IRQ chain vector */
struct segoff __data16 ( undiisr_next_handler );
#define undiisr_next_handler __use_data16 ( undiisr_next_handler )
@@ -395,6 +407,9 @@ static void undinet_hook_isr ( unsigned int irq ) {
assert ( undiisr_irq == 0 );
undiisr_irq = irq;
+ undiisr_imr = IMR_REG ( irq );
+ undiisr_bit = IMR_BIT ( irq );
+ undiisr_rearm = 0;
hook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
&undiisr_next_handler );
}
@@ -588,6 +603,14 @@ static void undinet_poll ( struct net_device *netdev ) {
* support interrupts.
*/
if ( ! undinet_isr_triggered() ) {
+
+ /* Rearm interrupt if needed */
+ if ( undiisr_rearm ) {
+ undiisr_rearm = 0;
+ assert ( undinic->irq != 0 );
+ enable_irq ( undinic->irq );
+ }
+
/* Allow interrupt to occur */
profile_start ( &undinet_irq_profiler );
__asm__ __volatile__ ( "sti\n\t"
@@ -838,15 +861,19 @@ static const struct undinet_irq_broken undinet_irq_broken_list[] = {
{ 0x8086, 0x1503, PCI_ANY_ID, PCI_ANY_ID },
/* HP 745 G3 laptop */
{ 0x14e4, 0x1687, PCI_ANY_ID, PCI_ANY_ID },
+ /* ASUSTeK KNPA-U16 server */
+ { 0x8086, 0x1521, 0x1043, PCI_ANY_ID },
};
/**
* Check for devices with broken support for generating interrupts
*
- * @v desc Device description
+ * @v netdev Net device
* @ret irq_is_broken Interrupt support is broken; no interrupts are generated
*/
-static int undinet_irq_is_broken ( struct device_description *desc ) {
+static int undinet_irq_is_broken ( struct net_device *netdev ) {
+ struct undi_nic *undinic = netdev->priv;
+ struct device_description *desc = &netdev->dev->desc;
const struct undinet_irq_broken *broken;
struct pci_device pci;
uint16_t subsys_vendor;
@@ -872,9 +899,25 @@ static int undinet_irq_is_broken ( struct device_description *desc ) {
( broken->pci_subsys_vendor == PCI_ANY_ID ) ) &&
( ( broken->pci_subsys == subsys ) ||
( broken->pci_subsys == PCI_ANY_ID ) ) ) {
+ DBGC ( undinic, "UNDINIC %p %04x:%04x subsys "
+ "%04x:%04x has broken interrupts\n",
+ undinic, desc->vendor, desc->device,
+ subsys_vendor, subsys );
return 1;
}
}
+
+ /* Check for a PCI Express capability. Given the number of
+ * issues found with legacy INTx emulation on PCIe systems, we
+ * assume that there is a high chance of interrupts not
+ * working on any PCIe device.
+ */
+ if ( pci_find_capability ( &pci, PCI_CAP_ID_EXP ) ) {
+ DBGC ( undinic, "UNDINIC %p is PCI Express: assuming "
+ "interrupts are unreliable\n", undinic );
+ return 1;
+ }
+
return 0;
}
@@ -972,6 +1015,10 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
}
DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
+ if ( undinic->irq ) {
+ /* Sanity check - prefix should have disabled the IRQ */
+ assert ( ! irq_enabled ( undinic->irq ) );
+ }
/* Get interface information */
memset ( &undi_iface, 0, sizeof ( undi_iface ) );
@@ -993,7 +1040,7 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
undinic );
undinic->hacks |= UNDI_HACK_EB54;
}
- if ( undinet_irq_is_broken ( &dev->desc ) ) {
+ if ( undinet_irq_is_broken ( netdev ) ) {
DBGC ( undinic, "UNDINIC %p forcing polling mode due to "
"broken interrupts\n", undinic );
undinic->irq_supported = 0;
diff --git a/src/arch/x86/drivers/xen/hvm.c b/src/arch/x86/drivers/xen/hvm.c
index b77cdd14c..cf41cc955 100644
--- a/src/arch/x86/drivers/xen/hvm.c
+++ b/src/arch/x86/drivers/xen/hvm.c
@@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdio.h>
+#include <string.h>
#include <errno.h>
#include <ipxe/malloc.h>
#include <ipxe/pci.h>
diff --git a/src/arch/x86/hci/commands/cpuid_cmd.c b/src/arch/x86/hci/commands/cpuid_cmd.c
index d73ce2a3e..f4d7305e8 100644
--- a/src/arch/x86/hci/commands/cpuid_cmd.c
+++ b/src/arch/x86/hci/commands/cpuid_cmd.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
#include <stdio.h>
@@ -95,7 +96,4 @@ static int cpuid_exec ( int argc, char **argv ) {
}
/** x86 CPU feature detection command */
-struct command cpuid_command __command = {
- .name = "cpuid",
- .exec = cpuid_exec,
-};
+COMMAND ( cpuid, cpuid_exec );
diff --git a/src/arch/x86/hci/commands/pxe_cmd.c b/src/arch/x86/hci/commands/pxe_cmd.c
index 473b97f97..cf1a36ed6 100644
--- a/src/arch/x86/hci/commands/pxe_cmd.c
+++ b/src/arch/x86/hci/commands/pxe_cmd.c
@@ -105,13 +105,5 @@ static int stoppxe_exec ( int argc __unused, char **argv __unused ) {
}
/** PXE commands */
-struct command pxe_commands[] __command = {
- {
- .name = "startpxe",
- .exec = startpxe_exec,
- },
- {
- .name = "stoppxe",
- .exec = stoppxe_exec,
- },
-};
+COMMAND ( startpxe, startpxe_exec );
+COMMAND ( stoppxe, stoppxe_exec );
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;
diff --git a/src/arch/x86/include/basemem.h b/src/arch/x86/include/basemem.h
index 01c2ea917..9ac918ac0 100644
--- a/src/arch/x86/include/basemem.h
+++ b/src/arch/x86/include/basemem.h
@@ -27,9 +27,4 @@ static inline unsigned int get_fbms ( void ) {
extern void set_fbms ( unsigned int new_fbms );
-/* Actually in hidemem.c, but putting it here avoids polluting the
- * architecture-independent include/hidemem.h.
- */
-extern void hide_basemem ( void );
-
#endif /* _BASEMEM_H */
diff --git a/src/arch/x86/include/bios_disks.h b/src/arch/x86/include/bios_disks.h
deleted file mode 100644
index 0dd7c4ebb..000000000
--- a/src/arch/x86/include/bios_disks.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef BIOS_DISKS_H
-#define BIOS_DISKS_H
-
-#include "dev.h"
-
-/*
- * Constants
- *
- */
-
-#define BIOS_DISK_MAX_NAME_LEN 6
-
-struct bios_disk_sector {
- char data[512];
-};
-
-/*
- * The location of a BIOS disk
- *
- */
-struct bios_disk_loc {
- uint8_t drive;
-};
-
-/*
- * A physical BIOS disk device
- *
- */
-struct bios_disk_device {
- char name[BIOS_DISK_MAX_NAME_LEN];
- uint8_t drive;
- uint8_t type;
-};
-
-/*
- * A BIOS disk driver, with a valid device ID range and naming
- * function.
- *
- */
-struct bios_disk_driver {
- void ( *fill_drive_name ) ( char *buf, uint8_t drive );
- uint8_t min_drive;
- uint8_t max_drive;
-};
-
-/*
- * Define a BIOS disk driver
- *
- */
-#define BIOS_DISK_DRIVER( _name, _fill_drive_name, _min_drive, _max_drive ) \
- static struct bios_disk_driver _name = { \
- .fill_drive_name = _fill_drive_name, \
- .min_drive = _min_drive, \
- .max_drive = _max_drive, \
- }
-
-/*
- * Functions in bios_disks.c
- *
- */
-
-
-/*
- * bios_disk bus global definition
- *
- */
-extern struct bus_driver bios_disk_driver;
-
-#endif /* BIOS_DISKS_H */
diff --git a/src/arch/x86/include/bits/acpi.h b/src/arch/x86/include/bits/acpi.h
index a6ff90804..287bdafeb 100644
--- a/src/arch/x86/include/bits/acpi.h
+++ b/src/arch/x86/include/bits/acpi.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/rsdp.h>
diff --git a/src/arch/x86/include/bits/bigint.h b/src/arch/x86/include/bits/bigint.h
index a6bc2ca1d..21cffa0cf 100644
--- a/src/arch/x86/include/bits/bigint.h
+++ b/src/arch/x86/include/bits/bigint.h
@@ -7,6 +7,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
#include <string.h>
@@ -32,10 +33,12 @@ bigint_init_raw ( uint32_t *value0, unsigned int size,
long discard_c;
/* Copy raw data in reverse order, padding with zeros */
- __asm__ __volatile__ ( "\n1:\n\t"
+ __asm__ __volatile__ ( "jecxz 2f\n\t"
+ "\n1:\n\t"
"movb -1(%3,%1), %%al\n\t"
"stosb\n\t"
"loop 1b\n\t"
+ "\n2:\n\t"
"xorl %%eax, %%eax\n\t"
"mov %4, %1\n\t"
"rep stosb\n\t"
@@ -52,8 +55,9 @@ bigint_init_raw ( uint32_t *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
+ * @ret carry Carry flag
*/
-static inline __attribute__ (( always_inline )) void
+static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -61,17 +65,20 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
long index;
void *discard_S;
long discard_c;
+ int carry;
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
"\n1:\n\t"
"lodsl\n\t"
- "adcl %%eax, (%4,%0,4)\n\t"
+ "adcl %%eax, (%5,%0,4)\n\t"
"inc %0\n\t" /* Does not affect CF */
"loop 1b\n\t"
: "=&r" ( index ), "=&S" ( discard_S ),
- "=&c" ( discard_c ), "+m" ( *value )
+ "=&c" ( discard_c ), "=@ccc" ( carry ),
+ "+m" ( *value )
: "r" ( value0 ), "1" ( addend0 ), "2" ( size )
: "eax" );
+ return carry;
}
/**
@@ -80,8 +87,9 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
+ * @ret borrow Borrow flag
*/
-static inline __attribute__ (( always_inline )) void
+static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -89,61 +97,71 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
long index;
void *discard_S;
long discard_c;
+ int borrow;
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
"\n1:\n\t"
"lodsl\n\t"
- "sbbl %%eax, (%4,%0,4)\n\t"
+ "sbbl %%eax, (%5,%0,4)\n\t"
"inc %0\n\t" /* Does not affect CF */
"loop 1b\n\t"
: "=&r" ( index ), "=&S" ( discard_S ),
- "=&c" ( discard_c ), "+m" ( *value )
+ "=&c" ( discard_c ), "=@ccc" ( borrow ),
+ "+m" ( *value )
: "r" ( value0 ), "1" ( subtrahend0 ),
"2" ( size )
: "eax" );
+ return borrow;
}
/**
- * Rotate big integer left
+ * Shift big integer left
*
* @v value0 Element 0 of big integer
* @v size Number of elements
+ * @ret out Bit shifted out
*/
-static inline __attribute__ (( always_inline )) void
-bigint_rol_raw ( uint32_t *value0, unsigned int size ) {
+static inline __attribute__ (( always_inline )) int
+bigint_shl_raw ( uint32_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
long index;
long discard_c;
+ int out;
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
"\n1:\n\t"
- "rcll $1, (%3,%0,4)\n\t"
+ "rcll $1, (%4,%0,4)\n\t"
"inc %0\n\t" /* Does not affect CF */
"loop 1b\n\t"
: "=&r" ( index ), "=&c" ( discard_c ),
- "+m" ( *value )
+ "=@ccc" ( out ), "+m" ( *value )
: "r" ( value0 ), "1" ( size ) );
+ return out;
}
/**
- * Rotate big integer right
+ * Shift big integer right
*
* @v value0 Element 0 of big integer
* @v size Number of elements
+ * @ret out Bit shifted out
*/
-static inline __attribute__ (( always_inline )) void
-bigint_ror_raw ( uint32_t *value0, unsigned int size ) {
+static inline __attribute__ (( always_inline )) int
+bigint_shr_raw ( uint32_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
long discard_c;
+ int out;
__asm__ __volatile__ ( "clc\n\t"
"\n1:\n\t"
- "rcrl $1, -4(%2,%0,4)\n\t"
+ "rcrl $1, -4(%3,%0,4)\n\t"
"loop 1b\n\t"
- : "=&c" ( discard_c ), "+m" ( *value )
+ : "=&c" ( discard_c ), "=@ccc" ( out ),
+ "+m" ( *value )
: "r" ( value0 ), "0" ( size ) );
+ return out;
}
/**
@@ -196,25 +214,6 @@ bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0,
}
/**
- * Test if bit is set in big integer
- *
- * @v value0 Element 0 of big integer
- * @v size Number of elements
- * @v bit Bit to test
- * @ret is_set Bit is set
- */
-static inline __attribute__ (( always_inline )) int
-bigint_bit_is_set_raw ( const uint32_t *value0, unsigned int size,
- unsigned int bit ) {
- const bigint_t ( size ) __attribute__ (( may_alias )) *value =
- ( ( const void * ) value0 );
- unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
- unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
-
- return ( value->element[index] & ( 1 << subindex ) );
-}
-
-/**
* Find highest bit set in big integer
*
* @v value0 Element 0 of big integer
@@ -312,20 +311,45 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
long discard_c;
/* Copy raw data in reverse order */
- __asm__ __volatile__ ( "\n1:\n\t"
+ __asm__ __volatile__ ( "jecxz 2f\n\t"
+ "\n1:\n\t"
"movb -1(%3,%1), %%al\n\t"
"stosb\n\t"
"loop 1b\n\t"
+ "\n2:\n\t"
: "=&D" ( discard_D ), "=&c" ( discard_c ),
"+m" ( *out_bytes )
: "r" ( value0 ), "0" ( out ), "1" ( len )
: "eax" );
}
-extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
- unsigned int multiplicand_size,
- const uint32_t *multiplier0,
- unsigned int multiplier_size,
- uint32_t *value0 );
+/**
+ * Multiply big integer elements
+ *
+ * @v multiplicand Multiplicand element
+ * @v multiplier Multiplier element
+ * @v result Result element
+ * @v carry Carry element
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_multiply_one ( const uint32_t multiplicand, const uint32_t multiplier,
+ uint32_t *result, uint32_t *carry ) {
+ uint32_t discard_a;
+
+ __asm__ __volatile__ ( /* Perform multiplication */
+ "mull %3\n\t"
+ /* Accumulate carry */
+ "addl %5, %0\n\t"
+ "adcl $0, %1\n\t"
+ /* Accumulate result */
+ "addl %0, %2\n\t"
+ "adcl $0, %1\n\t"
+ : "=&a" ( discard_a ),
+ "=&d" ( *carry ),
+ "+m" ( *result )
+ : "g" ( multiplicand ),
+ "0" ( multiplier ),
+ "r" ( *carry ) );
+}
#endif /* _BITS_BIGINT_H */
diff --git a/src/arch/x86/include/bits/bitops.h b/src/arch/x86/include/bits/bitops.h
index f697b8c8f..cdbc3b0a2 100644
--- a/src/arch/x86/include/bits/bitops.h
+++ b/src/arch/x86/include/bits/bitops.h
@@ -14,6 +14,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
diff --git a/src/arch/x86/include/bits/endian.h b/src/arch/x86/include/bits/endian.h
index 85718cfdd..72279117d 100644
--- a/src/arch/x86/include/bits/endian.h
+++ b/src/arch/x86/include/bits/endian.h
@@ -2,6 +2,7 @@
#define _BITS_ENDIAN_H
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h
index 78b3dea1c..e7aec6f39 100644
--- a/src/arch/x86/include/bits/errfile.h
+++ b/src/arch/x86/include/bits/errfile.h
@@ -2,14 +2,14 @@
#define _BITS_ERRFILE_H
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
/**
* @addtogroup errfile Error file identifiers
* @{
*/
-#define ERRFILE_memtop_umalloc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 )
-#define ERRFILE_memmap ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 )
+#define ERRFILE_int15 ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 )
#define ERRFILE_pnpbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00020000 )
#define ERRFILE_bios_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 )
#define ERRFILE_biosint ( ERRFILE_ARCH | ERRFILE_CORE | 0x00040000 )
@@ -42,7 +42,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 )
#define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 )
#define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 )
-#define ERRFILE_initrd ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000c0000 )
#define ERRFILE_pxe_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000d0000 )
#define ERRFILE_ucode ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000e0000 )
diff --git a/src/arch/x86/include/bits/io.h b/src/arch/x86/include/bits/io.h
index 95673ad8d..cde0b6829 100644
--- a/src/arch/x86/include/bits/io.h
+++ b/src/arch/x86/include/bits/io.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
/** Page shift */
#define PAGE_SHIFT 12
diff --git a/src/arch/x86/include/bits/iomap.h b/src/arch/x86/include/bits/iomap.h
index d6fff257e..d524bd805 100644
--- a/src/arch/x86/include/bits/iomap.h
+++ b/src/arch/x86/include/bits/iomap.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/iomap_pages.h>
diff --git a/src/arch/x86/include/bits/memmap.h b/src/arch/x86/include/bits/memmap.h
new file mode 100644
index 000000000..e68550fb8
--- /dev/null
+++ b/src/arch/x86/include/bits/memmap.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_MEMMAP_H
+#define _BITS_MEMMAP_H
+
+/** @file
+ *
+ * x86-specific system memory map API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
+
+#include <ipxe/int15.h>
+
+#endif /* _BITS_MEMMAP_H */
diff --git a/src/arch/x86/include/bits/nap.h b/src/arch/x86/include/bits/nap.h
index 7103b94c0..52c8d81ba 100644
--- a/src/arch/x86/include/bits/nap.h
+++ b/src/arch/x86/include/bits/nap.h
@@ -8,8 +8,16 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/bios_nap.h>
-#include <ipxe/efi/efix86_nap.h>
-#endif /* _BITS_MAP_H */
+/**
+ * Sleep until next CPU interrupt
+ *
+ */
+static inline __attribute__ (( always_inline )) void cpu_halt ( void ) {
+ __asm__ __volatile__ ( "hlt" );
+}
+
+#endif /* _BITS_NAP_H */
diff --git a/src/arch/x86/include/bits/ns16550.h b/src/arch/x86/include/bits/ns16550.h
new file mode 100644
index 000000000..dbb1cd51c
--- /dev/null
+++ b/src/arch/x86/include/bits/ns16550.h
@@ -0,0 +1,60 @@
+#ifndef _BITS_NS16550_H
+#define _BITS_NS16550_H
+
+/** @file
+ *
+ * 16550-compatible UART
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdint.h>
+#include <ipxe/io.h>
+
+/**
+ * Write to UART register
+ *
+ * @v ns16550 16550 UART
+ * @v address Register address
+ * @v data Data
+ */
+static inline __attribute__ (( always_inline )) void
+ns16550_write ( struct ns16550_uart *ns16550, unsigned int address,
+ uint8_t data ) {
+
+ iowrite8 ( data, ( ns16550->base + address ) );
+}
+
+/**
+ * Read from UART register
+ *
+ * @v ns16550 16550 UART
+ * @v address Register address
+ * @ret data Data
+ */
+static inline __attribute__ (( always_inline )) uint8_t
+ns16550_read ( struct ns16550_uart *ns16550, unsigned int address ) {
+
+ return ioread8 ( ns16550->base + address );
+}
+
+/* Fixed ISA serial port base addresses */
+#define COM1_BASE 0x3f8
+#define COM2_BASE 0x2f8
+#define COM3_BASE 0x3e8
+#define COM4_BASE 0x2e8
+
+/* Fixed ISA serial ports */
+extern struct uart com1;
+extern struct uart com2;
+extern struct uart com3;
+extern struct uart com4;
+
+/* Fixed ISA serial port names */
+#define COM1 &com1
+#define COM2 &com2
+#define COM3 &com3
+#define COM4 &com4
+
+#endif /* _BITS_NS16550_H */
diff --git a/src/arch/x86/include/bits/pci_io.h b/src/arch/x86/include/bits/pci_io.h
index a074d3370..b6c01e5c4 100644
--- a/src/arch/x86/include/bits/pci_io.h
+++ b/src/arch/x86/include/bits/pci_io.h
@@ -8,9 +8,9 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/pcibios.h>
#include <ipxe/pcidirect.h>
-#include <ipxe/pcicloud.h>
#endif /* _BITS_PCI_IO_H */
diff --git a/src/arch/x86/include/bits/reboot.h b/src/arch/x86/include/bits/reboot.h
index e702dd3d0..8d8d0b40e 100644
--- a/src/arch/x86/include/bits/reboot.h
+++ b/src/arch/x86/include/bits/reboot.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/bios_reboot.h>
diff --git a/src/arch/x86/include/bits/sanboot.h b/src/arch/x86/include/bits/sanboot.h
index 1b9924e64..ff7b88d14 100644
--- a/src/arch/x86/include/bits/sanboot.h
+++ b/src/arch/x86/include/bits/sanboot.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/bios_sanboot.h>
diff --git a/src/arch/x86/include/bits/smbios.h b/src/arch/x86/include/bits/smbios.h
index 9977c87ac..2be98d887 100644
--- a/src/arch/x86/include/bits/smbios.h
+++ b/src/arch/x86/include/bits/smbios.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/bios_smbios.h>
diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h
index c26fe30d5..8b2b3070b 100644
--- a/src/arch/x86/include/bits/string.h
+++ b/src/arch/x86/include/bits/string.h
@@ -25,6 +25,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
/** @file
*
diff --git a/src/arch/x86/include/bits/tcpip.h b/src/arch/x86/include/bits/tcpip.h
index 0ac55b1a0..52d032427 100644
--- a/src/arch/x86/include/bits/tcpip.h
+++ b/src/arch/x86/include/bits/tcpip.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
extern uint16_t tcpip_continue_chksum ( uint16_t partial, const void *data,
size_t len );
diff --git a/src/arch/x86/include/bits/time.h b/src/arch/x86/include/bits/time.h
index 556d96f64..a4aa8cc6e 100644
--- a/src/arch/x86/include/bits/time.h
+++ b/src/arch/x86/include/bits/time.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/rtc_time.h>
diff --git a/src/arch/x86/include/bits/uaccess.h b/src/arch/x86/include/bits/uaccess.h
deleted file mode 100644
index e9e7e5af5..000000000
--- a/src/arch/x86/include/bits/uaccess.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _BITS_UACCESS_H
-#define _BITS_UACCESS_H
-
-/** @file
- *
- * x86-specific user access API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <librm.h>
-
-#endif /* _BITS_UACCESS_H */
diff --git a/src/arch/x86/include/bits/uart.h b/src/arch/x86/include/bits/uart.h
deleted file mode 100644
index e09cd3f4c..000000000
--- a/src/arch/x86/include/bits/uart.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _BITS_UART_H
-#define _BITS_UART_H
-
-/** @file
- *
- * 16550-compatible UART
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <ipxe/io.h>
-
-/**
- * Write to UART register
- *
- * @v uart UART
- * @v addr Register address
- * @v data Data
- */
-static inline __attribute__ (( always_inline )) void
-uart_write ( struct uart *uart, unsigned int addr, uint8_t data ) {
- outb ( data, ( uart->base + addr ) );
-}
-
-/**
- * Read from UART register
- *
- * @v uart UART
- * @v addr Register address
- * @ret data Data
- */
-static inline __attribute__ (( always_inline )) uint8_t
-uart_read ( struct uart *uart, unsigned int addr ) {
- return inb ( uart->base + addr );
-}
-
-extern int uart_select ( struct uart *uart, unsigned int port );
-
-#endif /* _BITS_UART_H */
diff --git a/src/arch/x86/include/bits/umalloc.h b/src/arch/x86/include/bits/umalloc.h
deleted file mode 100644
index 5d1f554d8..000000000
--- a/src/arch/x86/include/bits/umalloc.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _BITS_UMALLOC_H
-#define _BITS_UMALLOC_H
-
-/** @file
- *
- * x86-specific user memory allocation API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <ipxe/memtop_umalloc.h>
-
-#endif /* _BITS_UMALLOC_H */
diff --git a/src/arch/x86/include/bits/xen.h b/src/arch/x86/include/bits/xen.h
index 3433cea1f..313bec254 100644
--- a/src/arch/x86/include/bits/xen.h
+++ b/src/arch/x86/include/bits/xen.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
/* Hypercall registers */
#ifdef __x86_64__
diff --git a/src/arch/x86/include/initrd.h b/src/arch/x86/include/initrd.h
deleted file mode 100644
index 2fb9d3d3a..000000000
--- a/src/arch/x86/include/initrd.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _INITRD_H
-#define _INITRD_H
-
-/** @file
- *
- * Initial ramdisk (initrd) reshuffling
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <ipxe/uaccess.h>
-
-/** Minimum free space required to reshuffle initrds
- *
- * Chosen to avoid absurdly long reshuffling times
- */
-#define INITRD_MIN_FREE_LEN ( 512 * 1024 )
-
-extern void initrd_reshuffle ( userptr_t bottom );
-extern int initrd_reshuffle_check ( size_t len, userptr_t bottom );
-
-#endif /* _INITRD_H */
diff --git a/src/arch/x86/include/ipxe/bios_nap.h b/src/arch/x86/include/ipxe/bios_nap.h
index c9b82c1e5..7d94b3c4a 100644
--- a/src/arch/x86/include/ipxe/bios_nap.h
+++ b/src/arch/x86/include/ipxe/bios_nap.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef NAP_PCBIOS
#define NAP_PREFIX_pcbios
diff --git a/src/arch/x86/include/ipxe/bios_reboot.h b/src/arch/x86/include/ipxe/bios_reboot.h
index 3f6df9073..bd1bb42cc 100644
--- a/src/arch/x86/include/ipxe/bios_reboot.h
+++ b/src/arch/x86/include/ipxe/bios_reboot.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef REBOOT_PCBIOS
#define REBOOT_PREFIX_pcbios
diff --git a/src/arch/x86/include/ipxe/bios_sanboot.h b/src/arch/x86/include/ipxe/bios_sanboot.h
index 85d698039..d28339e4e 100644
--- a/src/arch/x86/include/ipxe/bios_sanboot.h
+++ b/src/arch/x86/include/ipxe/bios_sanboot.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef SANBOOT_PCBIOS
#define SANBOOT_PREFIX_pcbios
diff --git a/src/arch/x86/include/ipxe/bios_smbios.h b/src/arch/x86/include/ipxe/bios_smbios.h
index 9f7f9c8ff..1815e3617 100644
--- a/src/arch/x86/include/ipxe/bios_smbios.h
+++ b/src/arch/x86/include/ipxe/bios_smbios.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef SMBIOS_PCBIOS
#define SMBIOS_PREFIX_pcbios
diff --git a/src/arch/x86/include/ipxe/cpuid.h b/src/arch/x86/include/ipxe/cpuid.h
index 90d1bf01d..1851a859b 100644
--- a/src/arch/x86/include/ipxe/cpuid.h
+++ b/src/arch/x86/include/ipxe/cpuid.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
@@ -33,6 +34,9 @@ struct x86_features {
/** CPUID extended function */
#define CPUID_EXTENDED 0x80000000UL
+/** CPUID hypervisor function */
+#define CPUID_HYPERVISOR 0x40000000UL
+
/** Get vendor ID and largest standard function */
#define CPUID_VENDOR_ID 0x00000000UL
diff --git a/src/arch/x86/include/ipxe/efi/efix86_nap.h b/src/arch/x86/include/ipxe/efi/efix86_nap.h
deleted file mode 100644
index 1a391c9b6..000000000
--- a/src/arch/x86/include/ipxe/efi/efix86_nap.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _IPXE_EFIX86_NAP_H
-#define _IPXE_EFIX86_NAP_H
-
-/** @file
- *
- * EFI CPU sleeping
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#ifdef NAP_EFIX86
-#define NAP_PREFIX_efix86
-#else
-#define NAP_PREFIX_efix86 __efix86_
-#endif
-
-#endif /* _IPXE_EFIX86_NAP_H */
diff --git a/src/arch/x86/include/ipxe/int15.h b/src/arch/x86/include/ipxe/int15.h
new file mode 100644
index 000000000..590c0e9a7
--- /dev/null
+++ b/src/arch/x86/include/ipxe/int15.h
@@ -0,0 +1,22 @@
+#ifndef _IPXE_INT15_H
+#define _IPXE_INT15_H
+
+/** @file
+ *
+ * INT15-based memory map
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
+
+#ifdef MEMMAP_INT15
+#define MEMMAP_PREFIX_int15
+#else
+#define MEMMAP_PREFIX_int15 __int15_
+#endif
+
+extern void int15_intercept ( int intercept );
+extern void hide_basemem ( void );
+
+#endif /* _IPXE_INT15_H */
diff --git a/src/arch/x86/include/ipxe/iomap_pages.h b/src/arch/x86/include/ipxe/iomap_pages.h
index 18e0a3002..e74dabd90 100644
--- a/src/arch/x86/include/ipxe/iomap_pages.h
+++ b/src/arch/x86/include/ipxe/iomap_pages.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef IOMAP_PAGES
#define IOMAP_PREFIX_pages
diff --git a/src/arch/x86/include/ipxe/memtop_umalloc.h b/src/arch/x86/include/ipxe/memtop_umalloc.h
deleted file mode 100644
index dee055d16..000000000
--- a/src/arch/x86/include/ipxe/memtop_umalloc.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _IPXE_MEMTOP_UMALLOC_H
-#define _IPXE_MEMTOP_UMALLOC_H
-
-/** @file
- *
- * External memory allocation
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#ifdef UMALLOC_MEMTOP
-#define UMALLOC_PREFIX_memtop
-#else
-#define UMALLOC_PREFIX_memtop __memtop_
-#endif
-
-#endif /* _IPXE_MEMTOP_UMALLOC_H */
diff --git a/src/arch/x86/include/ipxe/pcibios.h b/src/arch/x86/include/ipxe/pcibios.h
index 3caea1cfe..2fd03198e 100644
--- a/src/arch/x86/include/ipxe/pcibios.h
+++ b/src/arch/x86/include/ipxe/pcibios.h
@@ -10,6 +10,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef PCIAPI_PCBIOS
#define PCIAPI_PREFIX_pcbios
@@ -33,6 +34,17 @@ extern int pcibios_write ( struct pci_device *pci, uint32_t command,
uint32_t value );
/**
+ * Check if PCI bus probing is allowed
+ *
+ * @v pci PCI device
+ * @ret ok Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_can_probe ) ( struct pci_device *pci __unused ) {
+ return 1;
+}
+
+/**
* Read byte from PCI configuration space via PCI BIOS
*
* @v pci PCI device
@@ -145,6 +157,4 @@ PCIAPI_INLINE ( pcbios, pci_ioremap ) ( struct pci_device *pci __unused,
return ioremap ( bus_addr, len );
}
-extern struct pci_api pcibios_api;
-
#endif /* _IPXE_PCIBIOS_H */
diff --git a/src/arch/x86/include/ipxe/pcicloud.h b/src/arch/x86/include/ipxe/pcicloud.h
deleted file mode 100644
index 52268908c..000000000
--- a/src/arch/x86/include/ipxe/pcicloud.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _IPXE_PCICLOUD_H
-#define _IPXE_PCICLOUD_H
-
-/** @file
- *
- * Cloud VM PCI configuration space access
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#ifdef PCIAPI_CLOUD
-#define PCIAPI_PREFIX_cloud
-#else
-#define PCIAPI_PREFIX_cloud __cloud_
-#endif
-
-#endif /* _IPXE_PCICLOUD_H */
diff --git a/src/arch/x86/include/ipxe/pcidirect.h b/src/arch/x86/include/ipxe/pcidirect.h
index 98c6a2bbb..5863b4d16 100644
--- a/src/arch/x86/include/ipxe/pcidirect.h
+++ b/src/arch/x86/include/ipxe/pcidirect.h
@@ -2,6 +2,7 @@
#define _PCIDIRECT_H
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
#include <ipxe/io.h>
@@ -26,6 +27,17 @@ struct pci_device;
extern void pcidirect_prepare ( struct pci_device *pci, int where );
/**
+ * Check if PCI bus probing is allowed
+ *
+ * @v pci PCI device
+ * @ret ok Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_can_probe ) ( struct pci_device *pci __unused ) {
+ return 1;
+}
+
+/**
* Find next PCI bus:dev.fn address range in system
*
* @v busdevfn Starting PCI bus:dev.fn address
@@ -155,6 +167,4 @@ PCIAPI_INLINE ( direct, pci_ioremap ) ( struct pci_device *pci __unused,
return ioremap ( bus_addr, len );
}
-extern struct pci_api pcidirect_api;
-
#endif /* _PCIDIRECT_H */
diff --git a/src/arch/x86/include/ipxe/rsdp.h b/src/arch/x86/include/ipxe/rsdp.h
index 14afcd774..f371d9a20 100644
--- a/src/arch/x86/include/ipxe/rsdp.h
+++ b/src/arch/x86/include/ipxe/rsdp.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef ACPI_RSDP
#define ACPI_PREFIX_rsdp
@@ -20,9 +21,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* @v signature Requested table signature
* @v index Requested index of table with this signature
- * @ret table Table, or UNULL if not found
+ * @ret table Table, or NULL if not found
*/
-static inline __attribute__ (( always_inline )) userptr_t
+static inline __attribute__ (( always_inline )) const struct acpi_header *
ACPI_INLINE ( rsdp, acpi_find ) ( uint32_t signature, unsigned int index ) {
return acpi_find_via_rsdt ( signature, index );
diff --git a/src/arch/x86/include/ipxe/rtc_time.h b/src/arch/x86/include/ipxe/rtc_time.h
index cb8c7f49e..49c6313ed 100644
--- a/src/arch/x86/include/ipxe/rtc_time.h
+++ b/src/arch/x86/include/ipxe/rtc_time.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef TIME_RTC
#define TIME_PREFIX_rtc
diff --git a/src/arch/x86/include/ipxe/x86_io.h b/src/arch/x86/include/ipxe/x86_io.h
index eeb3f8454..164b57e92 100644
--- a/src/arch/x86/include/ipxe/x86_io.h
+++ b/src/arch/x86/include/ipxe/x86_io.h
@@ -16,6 +16,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#ifdef IOAPI_X86
#define IOAPI_PREFIX_x86
diff --git a/src/arch/x86/include/libkir.h b/src/arch/x86/include/libkir.h
index 1f5b13504..76766b6c2 100644
--- a/src/arch/x86/include/libkir.h
+++ b/src/arch/x86/include/libkir.h
@@ -194,7 +194,7 @@ copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) {
* @ret buffer User buffer
*/
static inline __attribute__ (( always_inline )) userptr_t
-real_to_user ( unsigned int segment, unsigned int offset ) {
+real_to_virt ( unsigned int segment, unsigned int offset ) {
return ( ( segment << 16 ) | offset );
}
@@ -210,7 +210,7 @@ real_to_user ( unsigned int segment, unsigned int offset ) {
*/
static inline __attribute__ (( always_inline )) userptr_t
virt_to_user ( void * virtual ) {
- return real_to_user ( rm_ds, ( intptr_t ) virtual );
+ return real_to_virt ( rm_ds, ( intptr_t ) virtual );
}
/* TEXT16_CODE: declare a fragment of code that resides in .text16 */
diff --git a/src/arch/x86/include/librm.h b/src/arch/x86/include/librm.h
index 84b345d3a..666be0438 100644
--- a/src/arch/x86/include/librm.h
+++ b/src/arch/x86/include/librm.h
@@ -64,12 +64,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#else /* ASSEMBLY */
-#ifdef UACCESS_LIBRM
-#define UACCESS_PREFIX_librm
-#else
-#define UACCESS_PREFIX_librm __librm_
-#endif
-
/**
* Call C function from real-mode code
*
@@ -79,114 +73,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
"pushl $( " _S2 ( VIRTUAL ( function ) ) " )\n\t" \
"call virt_call\n\t"
-/* Variables in librm.S */
-extern const unsigned long virt_offset;
-
-/**
- * Convert physical address to user pointer
- *
- * @v phys_addr Physical address
- * @ret userptr User pointer
- */
-static inline __always_inline userptr_t
-UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
-
- /* In a 64-bit build, any valid physical address is directly
- * usable as a virtual address, since the low 4GB is
- * identity-mapped.
- */
- if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
- return phys_addr;
-
- /* In a 32-bit build, subtract virt_offset */
- return ( phys_addr - virt_offset );
-}
-
-/**
- * Convert user buffer to physical address
- *
- * @v userptr User pointer
- * @v offset Offset from user pointer
- * @ret phys_addr Physical address
- */
-static inline __always_inline unsigned long
-UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
- unsigned long addr = ( userptr + offset );
-
- /* In a 64-bit build, any virtual address in the low 4GB is
- * directly usable as a physical address, since the low 4GB is
- * identity-mapped.
- */
- if ( ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) &&
- ( addr <= 0xffffffffUL ) )
- return addr;
-
- /* In a 32-bit build or in a 64-bit build with a virtual
- * address above 4GB: add virt_offset
- */
- return ( addr + virt_offset );
-}
-
-static inline __always_inline userptr_t
-UACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) {
- return trivial_virt_to_user ( addr );
-}
-
-static inline __always_inline void *
-UACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) {
- return trivial_user_to_virt ( userptr, offset );
-}
-
-static inline __always_inline userptr_t
-UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
- return trivial_userptr_add ( userptr, offset );
-}
-
-static inline __always_inline off_t
-UACCESS_INLINE ( librm, userptr_sub ) ( userptr_t userptr,
- userptr_t subtrahend ) {
- return trivial_userptr_sub ( userptr, subtrahend );
-}
-
-static inline __always_inline void
-UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
- userptr_t src, off_t src_off,
- size_t len ) {
- trivial_memcpy_user ( dest, dest_off, src, src_off, len );
-}
-
-static inline __always_inline void
-UACCESS_INLINE ( librm, memmove_user ) ( userptr_t dest, off_t dest_off,
- userptr_t src, off_t src_off,
- size_t len ) {
- trivial_memmove_user ( dest, dest_off, src, src_off, len );
-}
-
-static inline __always_inline int
-UACCESS_INLINE ( librm, memcmp_user ) ( userptr_t first, off_t first_off,
- userptr_t second, off_t second_off,
- size_t len ) {
- return trivial_memcmp_user ( first, first_off, second, second_off, len);
-}
-
-static inline __always_inline void
-UACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset,
- int c, size_t len ) {
- trivial_memset_user ( buffer, offset, c, len );
-}
-
-static inline __always_inline size_t
-UACCESS_INLINE ( librm, strlen_user ) ( userptr_t buffer, off_t offset ) {
- return trivial_strlen_user ( buffer, offset );
-}
-
-static inline __always_inline off_t
-UACCESS_INLINE ( librm, memchr_user ) ( userptr_t buffer, off_t offset,
- int c, size_t len ) {
- return trivial_memchr_user ( buffer, offset, c, len );
-}
-
-
/******************************************************************************
*
* Access to variables in .data16 and .text16
@@ -244,8 +130,8 @@ extern const uint16_t __text16 ( rm_cs );
extern const uint16_t __text16 ( rm_ds );
#define rm_ds __use_text16 ( rm_ds )
-extern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size );
-extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
+extern uint16_t copy_to_rm_stack ( const void *data, size_t size );
+extern void remove_from_rm_stack ( void *data, size_t size );
/* CODE_DEFAULT: restore default .code32/.code64 directive */
#ifdef __x86_64__
@@ -460,6 +346,10 @@ enum page_flags {
/** The I/O space page table */
extern struct page_table io_pages;
+/** Maximum number of I/O pages */
+#define IO_PAGE_COUNT \
+ ( sizeof ( io_pages.page ) / sizeof ( io_pages.page[0] ) )
+
/** I/O page size
*
* We choose to use 2MB pages for I/O space, to minimise the number of
@@ -479,7 +369,8 @@ extern char __text16_array ( sipi, [] );
#define sipi __use_text16 ( sipi )
/** Length of startup IPI real-mode handler */
-extern char sipi_len[];
+extern size_t ABS_SYMBOL ( sipi_len );
+#define sipi_len ABS_VALUE ( sipi_len )
/** Startup IPI real-mode handler copy of real-mode data segment */
extern uint16_t __text16 ( sipi_ds );
diff --git a/src/arch/x86/include/pic8259.h b/src/arch/x86/include/pic8259.h
index dbec5fd2c..0dc59cf27 100644
--- a/src/arch/x86/include/pic8259.h
+++ b/src/arch/x86/include/pic8259.h
@@ -47,9 +47,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/* Macros to enable/disable IRQs */
#define IMR_REG(x) ( (x) < IRQ_PIC_CUTOFF ? PIC1_IMR : PIC2_IMR )
#define IMR_BIT(x) ( 1 << ( (x) % IRQ_PIC_CUTOFF ) )
-#define irq_enabled(x) ( ( inb ( IMR_REG(x) ) & IMR_BIT(x) ) == 0 )
-#define enable_irq(x) outb ( inb( IMR_REG(x) ) & ~IMR_BIT(x), IMR_REG(x) )
-#define disable_irq(x) outb ( inb( IMR_REG(x) ) | IMR_BIT(x), IMR_REG(x) )
/* Macros for acknowledging IRQs */
#define ICR_REG( irq ) ( (irq) < IRQ_PIC_CUTOFF ? PIC1_ICR : PIC2_ICR )
@@ -63,6 +60,50 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IRQ_MAX 15
#define IRQ_NONE -1U
+/**
+ * Check if interrupt is enabled
+ *
+ * @v irq Interrupt number
+ * @ret enabled Interrupt is currently enabled
+ */
+static inline __attribute__ (( always_inline )) int
+irq_enabled ( unsigned int irq ) {
+ int imr = inb ( IMR_REG ( irq ) );
+ int mask = IMR_BIT ( irq );
+
+ return ( ( imr & mask ) == 0 );
+}
+
+/**
+ * Enable interrupt
+ *
+ * @v irq Interrupt number
+ * @ret enabled Interrupt was previously enabled
+ */
+static inline __attribute__ (( always_inline )) int
+enable_irq ( unsigned int irq ) {
+ int imr = inb ( IMR_REG ( irq ) );
+ int mask = IMR_BIT ( irq );
+
+ outb ( ( imr & ~mask ), IMR_REG ( irq ) );
+ return ( ( imr & mask ) == 0 );
+}
+
+/**
+ * Disable interrupt
+ *
+ * @v irq Interrupt number
+ * @ret enabled Interrupt was previously enabled
+ */
+static inline __attribute__ (( always_inline )) int
+disable_irq ( unsigned int irq ) {
+ int imr = inb ( IMR_REG ( irq ) );
+ int mask = IMR_BIT ( irq );
+
+ outb ( ( imr | mask ), IMR_REG ( irq ) );
+ return ( ( imr & mask ) == 0 );
+}
+
/* Function prototypes
*/
void send_eoi ( unsigned int irq );
diff --git a/src/arch/x86/include/pxe.h b/src/arch/x86/include/pxe.h
index 54649b504..8e7aa1ce7 100644
--- a/src/arch/x86/include/pxe.h
+++ b/src/arch/x86/include/pxe.h
@@ -85,8 +85,6 @@ struct pxe_api_call {
* @ret exit PXE API call exit code
*/
PXENV_EXIT_t ( * entry ) ( union u_PXENV_ANY *params );
- /** Length of parameters */
- uint16_t params_len;
/** Opcode */
uint16_t opcode;
};
@@ -112,7 +110,6 @@ struct pxe_api_call {
( union u_PXENV_ANY *params ) ) _entry ) \
: ( ( PXENV_EXIT_t ( * ) \
( union u_PXENV_ANY *params ) ) _entry ) ), \
- .params_len = sizeof ( _params_type ), \
.opcode = _opcode, \
}
diff --git a/src/arch/x86/include/realmode.h b/src/arch/x86/include/realmode.h
index 4defd3b97..7baec56ca 100644
--- a/src/arch/x86/include/realmode.h
+++ b/src/arch/x86/include/realmode.h
@@ -2,7 +2,9 @@
#define REALMODE_H
#include <stdint.h>
+#include <string.h>
#include <registers.h>
+#include <librm.h>
#include <ipxe/uaccess.h>
/*
@@ -65,15 +67,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
/**
- * Convert segment:offset address to user buffer
+ * Convert segment:offset address to virtual address
*
* @v segment Real-mode segment
* @v offset Real-mode offset
- * @ret buffer User buffer
+ * @ret virt Virtual address
*/
-static inline __always_inline userptr_t
-real_to_user ( unsigned int segment, unsigned int offset ) {
- return ( phys_to_user ( ( segment << 4 ) + offset ) );
+static inline __always_inline void *
+real_to_virt ( unsigned int segment, unsigned int offset ) {
+ return ( phys_to_virt ( ( segment << 4 ) + offset ) );
}
/**
@@ -87,7 +89,7 @@ real_to_user ( unsigned int segment, unsigned int offset ) {
static inline __always_inline void
copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
void *src, size_t n ) {
- copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n );
+ memcpy ( real_to_virt ( dest_seg, dest_off ), src, n );
}
/**
@@ -101,7 +103,7 @@ copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
static inline __always_inline void
copy_from_real ( void *dest, unsigned int src_seg,
unsigned int src_off, size_t n ) {
- copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n );
+ memcpy ( dest, real_to_virt ( src_seg, src_off ), n );
}
/**
diff --git a/src/arch/x86/interface/efi/efix86_nap.c b/src/arch/x86/interface/efi/efix86_nap.c
deleted file mode 100644
index 296876b85..000000000
--- a/src/arch/x86/interface/efi/efix86_nap.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2008 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 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 <ipxe/nap.h>
-#include <ipxe/efi/efi.h>
-
-/** @file
- *
- * iPXE CPU sleeping API for EFI
- *
- */
-
-/**
- * Sleep until next interrupt
- *
- */
-static void efix86_cpu_nap ( void ) {
- /*
- * I can't find any EFI API that allows us to put the CPU to
- * sleep. The CpuSleep() function is defined in CpuLib.h, but
- * isn't part of any exposed protocol so we have no way to
- * call it.
- *
- * The EFI shell doesn't seem to bother sleeping the CPU; it
- * just sits there idly burning power.
- *
- * If a shutdown is in progess, there may be nothing to
- * generate an interrupt since the timer is disabled in the
- * first step of ExitBootServices().
- */
- if ( ! efi_shutdown_in_progress )
- __asm__ __volatile__ ( "hlt" );
-}
-
-PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );
diff --git a/src/arch/x86/interface/pcbios/acpi_timer.c b/src/arch/x86/interface/pcbios/acpi_timer.c
index 2e4047e38..e1523578b 100644
--- a/src/arch/x86/interface/pcbios/acpi_timer.c
+++ b/src/arch/x86/interface/pcbios/acpi_timer.c
@@ -102,20 +102,19 @@ static void acpi_udelay ( unsigned long usecs ) {
* @ret rc Return status code
*/
static int acpi_timer_probe ( void ) {
- struct acpi_fadt fadtab;
- userptr_t fadt;
+ const struct acpi_fadt *fadt;
unsigned int pm_tmr_blk;
/* Locate FADT */
- fadt = acpi_table ( FADT_SIGNATURE, 0 );
+ fadt = container_of ( acpi_table ( FADT_SIGNATURE, 0 ),
+ struct acpi_fadt, acpi );
if ( ! fadt ) {
DBGC ( &acpi_timer, "ACPI could not find FADT\n" );
return -ENOENT;
}
/* Read FADT */
- copy_from_user ( &fadtab, fadt, 0, sizeof ( fadtab ) );
- pm_tmr_blk = le32_to_cpu ( fadtab.pm_tmr_blk );
+ pm_tmr_blk = le32_to_cpu ( fadt->pm_tmr_blk );
if ( ! pm_tmr_blk ) {
DBGC ( &acpi_timer, "ACPI has no timer\n" );
return -ENOENT;
diff --git a/src/arch/x86/interface/pcbios/acpipwr.c b/src/arch/x86/interface/pcbios/acpipwr.c
index f08b4af25..cb82ef1b4 100644
--- a/src/arch/x86/interface/pcbios/acpipwr.c
+++ b/src/arch/x86/interface/pcbios/acpipwr.c
@@ -23,6 +23,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
@@ -62,8 +63,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* uglier hacks I have ever implemented, but it's still prettier than
* the ACPI specification itself.
*/
-static int acpi_extract_sx ( userptr_t zsdt, size_t len, size_t offset,
- void *data ) {
+static int acpi_extract_sx ( const struct acpi_header *zsdt, size_t len,
+ size_t offset, void *data ) {
unsigned int *sx = data;
uint8_t bytes[4];
uint8_t *byte;
@@ -77,7 +78,8 @@ static int acpi_extract_sx ( userptr_t zsdt, size_t len, size_t offset,
}
/* Read first four bytes of value */
- copy_from_user ( bytes, zsdt, offset, sizeof ( bytes ) );
+ memcpy ( bytes, ( ( ( const void * ) zsdt ) + offset ),
+ sizeof ( bytes ) );
DBGC ( colour, "ACPI found \\_Sx containing %02x:%02x:%02x:%02x\n",
bytes[0], bytes[1], bytes[2], bytes[3] );
@@ -111,8 +113,7 @@ static int acpi_extract_sx ( userptr_t zsdt, size_t len, size_t offset,
* @ret rc Return status code
*/
int acpi_poweroff ( void ) {
- struct acpi_fadt fadtab;
- userptr_t fadt;
+ const struct acpi_fadt *fadt;
unsigned int pm1a_cnt_blk;
unsigned int pm1b_cnt_blk;
unsigned int pm1a_cnt;
@@ -123,16 +124,16 @@ int acpi_poweroff ( void ) {
int rc;
/* Locate FADT */
- fadt = acpi_table ( FADT_SIGNATURE, 0 );
+ fadt = container_of ( acpi_table ( FADT_SIGNATURE, 0 ),
+ struct acpi_fadt, acpi );
if ( ! fadt ) {
DBGC ( colour, "ACPI could not find FADT\n" );
return -ENOENT;
}
/* Read FADT */
- copy_from_user ( &fadtab, fadt, 0, sizeof ( fadtab ) );
- pm1a_cnt_blk = le32_to_cpu ( fadtab.pm1a_cnt_blk );
- pm1b_cnt_blk = le32_to_cpu ( fadtab.pm1b_cnt_blk );
+ pm1a_cnt_blk = le32_to_cpu ( fadt->pm1a_cnt_blk );
+ pm1b_cnt_blk = le32_to_cpu ( fadt->pm1b_cnt_blk );
pm1a_cnt = ( pm1a_cnt_blk + ACPI_PM1_CNT );
pm1b_cnt = ( pm1b_cnt_blk + ACPI_PM1_CNT );
diff --git a/src/arch/x86/interface/pcbios/basemem.c b/src/arch/x86/interface/pcbios/basemem.c
index 6a46081aa..8f3a30e92 100644
--- a/src/arch/x86/interface/pcbios/basemem.c
+++ b/src/arch/x86/interface/pcbios/basemem.c
@@ -27,7 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <realmode.h>
#include <bios.h>
#include <basemem.h>
-#include <ipxe/hidemem.h>
+#include <ipxe/memmap.h>
/** @file
*
diff --git a/src/arch/x86/interface/pcbios/bios_cachedhcp.c b/src/arch/x86/interface/pcbios/bios_cachedhcp.c
index bea803d6e..60191c9c5 100644
--- a/src/arch/x86/interface/pcbios/bios_cachedhcp.c
+++ b/src/arch/x86/interface/pcbios/bios_cachedhcp.c
@@ -24,6 +24,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
+#include <string.h>
#include <ipxe/init.h>
#include <ipxe/cachedhcp.h>
#include <realmode.h>
@@ -60,7 +61,7 @@ static void cachedhcp_init ( void ) {
/* Record cached DHCPACK */
if ( ( rc = cachedhcp_record ( &cached_dhcpack, 0,
- phys_to_user ( cached_dhcpack_phys ),
+ phys_to_virt ( cached_dhcpack_phys ),
sizeof ( BOOTPLAYER_t ) ) ) != 0 ) {
DBGC ( colour, "CACHEDHCP could not record DHCPACK: %s\n",
strerror ( rc ) );
@@ -73,5 +74,6 @@ static void cachedhcp_init ( void ) {
/** Cached DHCPACK initialisation function */
struct init_fn cachedhcp_init_fn __init_fn ( INIT_NORMAL ) = {
+ .name = "cachedhcp",
.initialise = cachedhcp_init,
};
diff --git a/src/arch/x86/interface/pcbios/bios_mp.c b/src/arch/x86/interface/pcbios/bios_mp.c
index 9e1179ccd..4525a60cf 100644
--- a/src/arch/x86/interface/pcbios/bios_mp.c
+++ b/src/arch/x86/interface/pcbios/bios_mp.c
@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
#include <registers.h>
+#include <librm.h>
#include <ipxe/uaccess.h>
#include <ipxe/timer.h>
#include <ipxe/msr.h>
@@ -92,9 +93,9 @@ static void bios_mp_exec_boot ( mp_func_t func, void *opaque ) {
"pushl %k1\n\t"
"call *%k0\n\t"
"addl $8, %%esp\n\t" )
- : : "r" ( mp_address ( mp_call ) ),
- "r" ( mp_address ( func ) ),
- "r" ( mp_address ( opaque ) ) );
+ : : "R" ( mp_address ( mp_call ) ),
+ "R" ( mp_address ( func ) ),
+ "R" ( mp_address ( opaque ) ) );
}
/**
diff --git a/src/arch/x86/interface/pcbios/bios_reboot.c b/src/arch/x86/interface/pcbios/bios_reboot.c
index 071173f19..c7f25405f 100644
--- a/src/arch/x86/interface/pcbios/bios_reboot.c
+++ b/src/arch/x86/interface/pcbios/bios_reboot.c
@@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
+#include <string.h>
#include <ipxe/reboot.h>
#include <realmode.h>
#include <bios.h>
@@ -38,14 +39,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* Reboot system
*
- * @v warm Perform a warm reboot
+ * @v flags Reboot flags
*/
-static void bios_reboot ( int warm ) {
- uint16_t flag;
+static void bios_reboot ( int flags ) {
+ uint16_t type;
/* Configure BIOS for cold/warm reboot */
- flag = ( warm ? BDA_REBOOT_WARM : 0 );
- put_real ( flag, BDA_SEG, BDA_REBOOT );
+ type = ( ( flags & REBOOT_WARM ) ? BDA_REBOOT_WARM : 0 );
+ put_real ( type, BDA_SEG, BDA_REBOOT );
/* Jump to system reset vector */
__asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : );
diff --git a/src/arch/x86/interface/pcbios/bios_smbios.c b/src/arch/x86/interface/pcbios/bios_smbios.c
index 366679d36..aaec1eea1 100644
--- a/src/arch/x86/interface/pcbios/bios_smbios.c
+++ b/src/arch/x86/interface/pcbios/bios_smbios.c
@@ -45,19 +45,18 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* @ret rc Return status code
*/
static int bios_find_smbios2 ( struct smbios *smbios ) {
- struct smbios_entry entry;
- int rc;
+ const struct smbios_entry *entry;
/* Scan through BIOS segment to find SMBIOS 32-bit entry point */
- if ( ( rc = find_smbios_entry ( real_to_user ( BIOS_SEG, 0 ), 0x10000,
- &entry ) ) != 0 )
- return rc;
+ entry = find_smbios_entry ( real_to_virt ( BIOS_SEG, 0 ), 0x10000 );
+ if ( ! entry )
+ return -ENOENT;
/* Fill in entry point descriptor structure */
- smbios->address = phys_to_user ( entry.smbios_address );
- smbios->len = entry.smbios_len;
- smbios->count = entry.smbios_count;
- smbios->version = SMBIOS_VERSION ( entry.major, entry.minor );
+ smbios->address = phys_to_virt ( entry->smbios_address );
+ smbios->len = entry->smbios_len;
+ smbios->count = entry->smbios_count;
+ smbios->version = SMBIOS_VERSION ( entry->major, entry->minor );
return 0;
}
@@ -69,26 +68,25 @@ static int bios_find_smbios2 ( struct smbios *smbios ) {
* @ret rc Return status code
*/
static int bios_find_smbios3 ( struct smbios *smbios ) {
- struct smbios3_entry entry;
- int rc;
+ const struct smbios3_entry *entry;
/* Scan through BIOS segment to find SMBIOS 64-bit entry point */
- if ( ( rc = find_smbios3_entry ( real_to_user ( BIOS_SEG, 0 ), 0x10000,
- &entry ) ) != 0 )
- return rc;
+ entry = find_smbios3_entry ( real_to_virt ( BIOS_SEG, 0 ), 0x10000 );
+ if ( ! entry )
+ return -ENOENT;
/* Check that address is accessible */
- if ( entry.smbios_address > ~( ( physaddr_t ) 0 ) ) {
+ if ( entry->smbios_address > ~( ( physaddr_t ) 0 ) ) {
DBG ( "SMBIOS3 at %08llx is inaccessible\n",
- ( ( unsigned long long ) entry.smbios_address ) );
+ ( ( unsigned long long ) entry->smbios_address ) );
return -ENOTSUP;
}
/* Fill in entry point descriptor structure */
- smbios->address = phys_to_user ( entry.smbios_address );
- smbios->len = entry.smbios_len;
+ smbios->address = phys_to_virt ( entry->smbios_address );
+ smbios->len = entry->smbios_len;
smbios->count = 0;
- smbios->version = SMBIOS_VERSION ( entry.major, entry.minor );
+ smbios->version = SMBIOS_VERSION ( entry->major, entry->minor );
return 0;
}
diff --git a/src/arch/x86/interface/pcbios/biosint.c b/src/arch/x86/interface/pcbios/biosint.c
index 667e9ed81..f5e54ede8 100644
--- a/src/arch/x86/interface/pcbios/biosint.c
+++ b/src/arch/x86/interface/pcbios/biosint.c
@@ -1,3 +1,4 @@
+#include <string.h>
#include <errno.h>
#include <realmode.h>
#include <biosint.h>
diff --git a/src/arch/x86/interface/pcbios/e820mangler.S b/src/arch/x86/interface/pcbios/e820mangler.S
index ef5dc2754..b9e891dff 100644
--- a/src/arch/x86/interface/pcbios/e820mangler.S
+++ b/src/arch/x86/interface/pcbios/e820mangler.S
@@ -564,6 +564,8 @@ int15_88:
int15:
/* See if we want to intercept this call */
pushfw
+ cmpb $0, %cs:int15_intercept_flag
+ je 3f
cmpw $0xe820, %ax
jne 1f
cmpl $SMAP, %edx
@@ -587,3 +589,9 @@ int15:
int15_vector:
.long 0
.size int15_vector, . - int15_vector
+
+ .section ".text16.data", "aw", @progbits
+ .globl int15_intercept_flag
+int15_intercept_flag:
+ .byte 1
+ .size int15_intercept_flag, . - int15_intercept_flag
diff --git a/src/arch/x86/interface/pcbios/hidemem.c b/src/arch/x86/interface/pcbios/hidemem.c
index 1a3022c5d..2b85459b6 100644
--- a/src/arch/x86/interface/pcbios/hidemem.c
+++ b/src/arch/x86/interface/pcbios/hidemem.c
@@ -22,6 +22,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+#include <string.h>
#include <assert.h>
#include <realmode.h>
#include <biosint.h>
@@ -29,7 +30,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <fakee820.h>
#include <ipxe/init.h>
#include <ipxe/io.h>
-#include <ipxe/hidemem.h>
+#include <ipxe/uheap.h>
+#include <ipxe/memmap.h>
/** Set to true if you want to test a fake E820 map */
#define FAKE_E820 0
@@ -72,13 +74,17 @@ extern void int15();
extern struct segoff __text16 ( int15_vector );
#define int15_vector __use_text16 ( int15_vector )
+/** INT 15 interception flag */
+extern uint8_t __text16 ( int15_intercept_flag );
+#define int15_intercept_flag __use_text16 ( int15_intercept_flag )
+
/* The linker defines these symbols for us */
extern char _textdata[];
extern char _etextdata[];
-extern char _text16_memsz[];
-#define _text16_memsz ( ( size_t ) _text16_memsz )
-extern char _data16_memsz[];
-#define _data16_memsz ( ( size_t ) _data16_memsz )
+extern size_t ABS_SYMBOL ( _text16_memsz );
+#define _text16_memsz ABS_VALUE ( _text16_memsz )
+extern size_t ABS_SYMBOL ( _data16_memsz );
+#define _data16_memsz ABS_VALUE ( _data16_memsz )
/**
* Hide region of memory from system memory map
@@ -113,21 +119,43 @@ void hide_basemem ( void ) {
}
/**
- * Hide umalloc() region
+ * Hide .text and .data
+ *
+ */
+void hide_textdata ( void ) {
+ hide_region ( &hidemem_textdata, virt_to_phys ( _textdata ),
+ virt_to_phys ( _etextdata ) );
+}
+
+/**
+ * Synchronise in-use regions with the externally visible system memory map
*
*/
-void hide_umalloc ( physaddr_t start, physaddr_t end ) {
- assert ( end <= virt_to_phys ( _textdata ) );
+static void int15_sync ( void ) {
+ physaddr_t start;
+ physaddr_t end;
+
+ /* Besides our fixed base memory and textdata regions, we
+ * support hiding only a single in-use memory region (the
+ * umalloc region), which must be placed before the hidden
+ * textdata region (even if zero-length).
+ */
+ start = uheap_start;
+ end = uheap_end;
+ if ( start == end )
+ start = end = virt_to_phys ( _textdata );
hide_region ( &hidemem_umalloc, start, end );
}
/**
- * Hide .text and .data
+ * Set INT 15 interception flag
*
+ * @v intercept Intercept INT 15 calls to modify memory map
*/
-void hide_textdata ( void ) {
- hide_region ( &hidemem_textdata, virt_to_phys ( _textdata ),
- virt_to_phys ( _etextdata ) );
+void int15_intercept ( int intercept ) {
+
+ /* Set flag for INT 15 handler */
+ int15_intercept_flag = intercept;
}
/**
@@ -137,26 +165,25 @@ void hide_textdata ( void ) {
* returned by the BIOS.
*/
static void hide_etherboot ( void ) {
- struct memory_map memmap;
unsigned int rm_ds_top;
unsigned int rm_cs_top;
unsigned int fbms;
/* Dump memory map before mangling */
DBG ( "Hiding iPXE from system memory map\n" );
- get_memmap ( &memmap );
+ memmap_dump_all ( 1 );
/* Hook in fake E820 map, if we're testing one */
if ( FAKE_E820 ) {
DBG ( "Hooking in fake E820 map\n" );
fake_e820();
- get_memmap ( &memmap );
+ memmap_dump_all ( 1 );
}
/* Initialise the hidden regions */
hide_basemem();
- hide_umalloc ( virt_to_phys ( _textdata ), virt_to_phys ( _textdata ) );
hide_textdata();
+ int15_sync();
/* Some really moronic BIOSes bring up the PXE stack via the
* UNDI loader entry point and then don't bother to unload it
@@ -183,7 +210,7 @@ static void hide_etherboot ( void ) {
/* Dump memory map after mangling */
DBG ( "Hidden iPXE from system memory map\n" );
- get_memmap ( &memmap );
+ memmap_dump_all ( 1 );
}
/**
@@ -193,7 +220,6 @@ static void hide_etherboot ( void ) {
* possible.
*/
static void unhide_etherboot ( int flags __unused ) {
- struct memory_map memmap;
int rc;
/* If we have more than one hooked interrupt at this point, it
@@ -224,7 +250,7 @@ static void unhide_etherboot ( int flags __unused ) {
/* Dump memory map after unhiding */
DBG ( "Unhidden iPXE from system memory map\n" );
- get_memmap ( &memmap );
+ memmap_dump_all ( 1 );
}
/** Hide Etherboot startup function */
@@ -233,3 +259,5 @@ struct startup_fn hide_etherboot_startup_fn __startup_fn ( STARTUP_EARLY ) = {
.startup = hide_etherboot,
.shutdown = unhide_etherboot,
};
+
+PROVIDE_MEMMAP ( int15, memmap_sync, int15_sync );
diff --git a/src/arch/x86/interface/pcbios/int13.c b/src/arch/x86/interface/pcbios/int13.c
index 372d40ba3..3fb25d261 100644
--- a/src/arch/x86/interface/pcbios/int13.c
+++ b/src/arch/x86/interface/pcbios/int13.c
@@ -25,17 +25,18 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <limits.h>
#include <byteswap.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/blockdev.h>
-#include <ipxe/io.h>
#include <ipxe/acpi.h>
#include <ipxe/sanboot.h>
#include <ipxe/device.h>
#include <ipxe/pci.h>
#include <ipxe/eltorito.h>
+#include <ipxe/memmap.h>
#include <realmode.h>
#include <bios.h>
#include <biosint.h>
@@ -181,8 +182,7 @@ static int int13_parse_eltorito ( struct san_device *sandev, void *scratch ) {
int rc;
/* Read boot record volume descriptor */
- if ( ( rc = sandev_read ( sandev, ELTORITO_LBA, 1,
- virt_to_user ( boot ) ) ) != 0 ) {
+ if ( ( rc = sandev_read ( sandev, ELTORITO_LBA, 1, boot ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x could not read El "
"Torito boot record volume descriptor: %s\n",
sandev->drive, strerror ( rc ) );
@@ -228,7 +228,7 @@ static int int13_guess_geometry_hdd ( struct san_device *sandev, void *scratch,
int rc;
/* Read partition table */
- if ( ( rc = sandev_read ( sandev, 0, 1, virt_to_user ( mbr ) ) ) != 0 ) {
+ if ( ( rc = sandev_read ( sandev, 0, 1, mbr ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x could not read "
"partition table to guess geometry: %s\n",
sandev->drive, strerror ( rc ) );
@@ -517,12 +517,12 @@ static int int13_rw_sectors ( struct san_device *sandev,
int ( * sandev_rw ) ( struct san_device *sandev,
uint64_t lba,
unsigned int count,
- userptr_t buffer ) ) {
+ void *buffer ) ) {
struct int13_data *int13 = sandev->priv;
unsigned int cylinder, head, sector;
unsigned long lba;
unsigned int count;
- userptr_t buffer;
+ void *buffer;
int rc;
/* Validate blocksize */
@@ -549,7 +549,7 @@ static int int13_rw_sectors ( struct san_device *sandev,
lba = ( ( ( ( cylinder * int13->heads ) + head )
* int13->sectors_per_track ) + sector - 1 );
count = ix86->regs.al;
- buffer = real_to_user ( ix86->segs.es, ix86->regs.bx );
+ buffer = real_to_virt ( ix86->segs.es, ix86->regs.bx );
DBGC2 ( sandev->drive, "C/H/S %d/%d/%d = LBA %08lx <-> %04x:%04x "
"(count %d)\n", cylinder, head, sector, lba, ix86->segs.es,
@@ -710,12 +710,12 @@ static int int13_extended_rw ( struct san_device *sandev,
int ( * sandev_rw ) ( struct san_device *sandev,
uint64_t lba,
unsigned int count,
- userptr_t buffer ) ) {
+ void *buffer ) ) {
struct int13_disk_address addr;
uint8_t bufsize;
uint64_t lba;
unsigned long count;
- userptr_t buffer;
+ void *buffer;
int rc;
/* Extended reads are not allowed on floppy drives.
@@ -743,11 +743,11 @@ static int int13_extended_rw ( struct san_device *sandev,
if ( ( addr.count == 0xff ) ||
( ( addr.buffer.segment == 0xffff ) &&
( addr.buffer.offset == 0xffff ) ) ) {
- buffer = phys_to_user ( addr.buffer_phys );
+ buffer = phys_to_virt ( addr.buffer_phys );
DBGC2 ( sandev->drive, "%08llx",
( ( unsigned long long ) addr.buffer_phys ) );
} else {
- buffer = real_to_user ( addr.buffer.segment,
+ buffer = real_to_virt ( addr.buffer.segment,
addr.buffer.offset );
DBGC2 ( sandev->drive, "%04x:%04x", addr.buffer.segment,
addr.buffer.offset );
@@ -1058,7 +1058,7 @@ static int int13_cdrom_read_boot_catalog ( struct san_device *sandev,
/* Read from boot catalog */
if ( ( rc = sandev_read ( sandev, start, command.count,
- phys_to_user ( command.buffer ) ) ) != 0 ) {
+ phys_to_virt ( command.buffer ) ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x could not read boot "
"catalog: %s\n", sandev->drive, strerror ( rc ) );
return -INT13_STATUS_READ_ERROR;
@@ -1455,8 +1455,8 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
"catalog (status %04x)\n", drive, status );
return -EIO;
}
- copy_from_user ( &catalog, phys_to_user ( eltorito_cmd.buffer ), 0,
- sizeof ( catalog ) );
+ memcpy ( &catalog, phys_to_virt ( eltorito_cmd.buffer ),
+ sizeof ( catalog ) );
/* Sanity checks */
if ( catalog.valid.platform_id != ELTORITO_PLATFORM_X86 ) {
@@ -1523,7 +1523,6 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
*/
static int int13_boot ( unsigned int drive,
struct san_boot_config *config __unused ) {
- struct memory_map memmap;
struct segoff address;
int rc;
@@ -1537,7 +1536,7 @@ static int int13_boot ( unsigned int drive,
* many problems that turn out to be memory-map related that
* it's worth doing.
*/
- get_memmap ( &memmap );
+ memmap_dump_all ( 1 );
/* Jump to boot sector */
if ( ( rc = call_bootsector ( address.segment, address.offset,
diff --git a/src/arch/x86/interface/pcbios/int13con.c b/src/arch/x86/interface/pcbios/int13con.c
index 8106cd153..925228874 100644
--- a/src/arch/x86/interface/pcbios/int13con.c
+++ b/src/arch/x86/interface/pcbios/int13con.c
@@ -288,6 +288,7 @@ static void int13con_init ( void ) {
* INT13 console initialisation function
*/
struct init_fn int13con_init_fn __init_fn ( INIT_CONSOLE ) = {
+ .name = "int13con",
.initialise = int13con_init,
};
diff --git a/src/arch/x86/interface/pcbios/memmap.c b/src/arch/x86/interface/pcbios/int15.c
index daae382b8..73bdbbe4a 100644
--- a/src/arch/x86/interface/pcbios/memmap.c
+++ b/src/arch/x86/interface/pcbios/int15.c
@@ -24,11 +24,14 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
+#include <string.h>
#include <errno.h>
+#include <assert.h>
#include <realmode.h>
#include <bios.h>
#include <memsizes.h>
#include <ipxe/io.h>
+#include <ipxe/memmap.h>
/**
* @file
@@ -151,7 +154,7 @@ static unsigned int extmemsize_88 ( void ) {
* @ret extmem Extended memory size, in kB
*
* Note that this is only an approximation; for an accurate picture,
- * use the E820 memory map obtained via get_memmap();
+ * use the E820 memory map obtained via memmap_describe();
*/
unsigned int extmemsize ( void ) {
unsigned int extmem_e801;
@@ -166,12 +169,13 @@ unsigned int extmemsize ( void ) {
/**
* Get e820 memory map
*
- * @v memmap Memory map to fill in
+ * @v region Memory region of interest to be updated
* @ret rc Return status code
*/
-static int meme820 ( struct memory_map *memmap ) {
- struct memory_region *region = memmap->regions;
- struct memory_region *prev_region = NULL;
+static int meme820 ( struct memmap_region *region ) {
+ unsigned int count = 0;
+ uint64_t start = 0;
+ uint64_t len = 0;
uint32_t next = 0;
uint32_t smap;
uint32_t size;
@@ -225,13 +229,6 @@ static int meme820 ( struct memory_map *memmap ) {
break;
}
- /* If first region is not RAM, assume map is invalid */
- if ( ( memmap->count == 0 ) &&
- ( e820buf.type != E820_TYPE_RAM ) ) {
- DBG ( "INT 15,e820 failed, first entry not RAM\n" );
- return -EINVAL;
- }
-
DBG ( "INT 15,e820 region [%llx,%llx) type %d",
e820buf.start, ( e820buf.start + e820buf.len ),
( int ) e820buf.type );
@@ -258,27 +255,36 @@ static int meme820 ( struct memory_map *memmap ) {
continue;
}
- region->start = e820buf.start;
- region->end = e820buf.start + e820buf.len;
-
/* Check for adjacent regions and merge them */
- if ( prev_region && ( region->start == prev_region->end ) ) {
- prev_region->end = region->end;
+ if ( e820buf.start == ( start + len ) ) {
+ len += e820buf.len;
} else {
- prev_region = region;
- region++;
- memmap->count++;
+ start = e820buf.start;
+ len = e820buf.len;
}
- if ( memmap->count >= ( sizeof ( memmap->regions ) /
- sizeof ( memmap->regions[0] ) ) ) {
- DBG ( "INT 15,e820 too many regions returned\n" );
- /* Not a fatal error; what we've got so far at
- * least represents valid regions of memory,
- * even if we couldn't get them all.
- */
- break;
+ /* Sanity check: first region (base memory) should
+ * start at address zero.
+ */
+ if ( ( count == 0 ) && ( start != 0 ) ) {
+ DBG ( "INT 15,e820 region 0 starts at %llx (expected "
+ "0); assuming insane\n", start );
+ return -EINVAL;
+ }
+
+ /* Sanity check: second region (extended memory)
+ * should start at address 0x100000.
+ */
+ if ( ( count == 1 ) && ( start != 0x100000 ) ) {
+ DBG ( "INT 15,e820 region 1 starts at %llx (expected "
+ "100000); assuming insane\n", start );
+ return -EINVAL;
}
+
+ /* Update region of interest */
+ memmap_update ( region, start, len, MEMMAP_FL_MEMORY, "e820" );
+ count++;
+
} while ( next != 0 );
/* Sanity checks. Some BIOSes report complete garbage via INT
@@ -287,19 +293,9 @@ static int meme820 ( struct memory_map *memmap ) {
* region (starting at 0) and at least one high memory region
* (starting at 0x100000).
*/
- if ( memmap->count < 2 ) {
+ if ( count < 2 ) {
DBG ( "INT 15,e820 returned only %d regions; assuming "
- "insane\n", memmap->count );
- return -EINVAL;
- }
- if ( memmap->regions[0].start != 0 ) {
- DBG ( "INT 15,e820 region 0 starts at %llx (expected 0); "
- "assuming insane\n", memmap->regions[0].start );
- return -EINVAL;
- }
- if ( memmap->regions[1].start != 0x100000 ) {
- DBG ( "INT 15,e820 region 1 starts at %llx (expected 100000); "
- "assuming insane\n", memmap->regions[0].start );
+ "insane\n", count );
return -EINVAL;
}
@@ -307,37 +303,52 @@ static int meme820 ( struct memory_map *memmap ) {
}
/**
- * Get memory map
+ * Describe memory region from system memory map
*
- * @v memmap Memory map to fill in
+ * @v min Minimum address
+ * @v hide Hide in-use regions from the memory map
+ * @v region Region descriptor to fill in
*/
-void x86_get_memmap ( struct memory_map *memmap ) {
- unsigned int basemem, extmem;
+static void int15_describe ( uint64_t min, int hide,
+ struct memmap_region *region ) {
+ unsigned int basemem;
+ unsigned int extmem;
+ uint64_t inaccessible;
int rc;
- DBG ( "Fetching system memory map\n" );
+ /* Initialise region */
+ memmap_init ( min, region );
- /* Clear memory map */
- memset ( memmap, 0, sizeof ( *memmap ) );
+ /* Mark addresses above 4GB as inaccessible: we have no way to
+ * access them either in a 32-bit build or in a 64-bit build
+ * (since the 64-bit build identity-maps only the 32-bit
+ * address space).
+ */
+ inaccessible = ( 1ULL << 32 );
+ memmap_update ( region, inaccessible, -inaccessible,
+ MEMMAP_FL_INACCESSIBLE, NULL );
- /* Get base and extended memory sizes */
- basemem = basememsize();
- DBG ( "FBMS base memory size %d kB [0,%x)\n",
- basemem, ( basemem * 1024 ) );
- extmem = extmemsize();
-
- /* Try INT 15,e820 first */
- if ( ( rc = meme820 ( memmap ) ) == 0 ) {
+ /* Enable/disable INT 15 interception as applicable */
+ int15_intercept ( hide );
+
+ /* Try INT 15,e820 first, falling back to constructing a map
+ * from basemem and extmem sizes
+ */
+ if ( ( rc = meme820 ( region ) ) == 0 ) {
DBG ( "Obtained system memory map via INT 15,e820\n" );
- return;
+ } else {
+ basemem = basememsize();
+ DBG ( "FBMS base memory size %d kB [0,%x)\n",
+ basemem, ( basemem * 1024 ) );
+ extmem = extmemsize();
+ memmap_update ( region, 0, ( basemem * 1024 ),
+ MEMMAP_FL_MEMORY, "basemem" );
+ memmap_update ( region, 0x100000, ( extmem * 1024 ),
+ MEMMAP_FL_MEMORY, "extmem" );
}
- /* Fall back to constructing a map from basemem and extmem sizes */
- DBG ( "INT 15,e820 failed; constructing map\n" );
- memmap->regions[0].end = ( basemem * 1024 );
- memmap->regions[1].start = 0x100000;
- memmap->regions[1].end = 0x100000 + ( extmem * 1024 );
- memmap->count = 2;
+ /* Restore INT 15 interception */
+ int15_intercept ( 1 );
}
-PROVIDE_IOAPI ( x86, get_memmap, x86_get_memmap );
+PROVIDE_MEMMAP ( int15, memmap_describe, int15_describe );
diff --git a/src/arch/x86/interface/pcbios/memtop_umalloc.c b/src/arch/x86/interface/pcbios/memtop_umalloc.c
deleted file mode 100644
index 1d3f40a1c..000000000
--- a/src/arch/x86/interface/pcbios/memtop_umalloc.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2007 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 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 );
-
-/**
- * @file
- *
- * External memory allocation
- *
- */
-
-#include <limits.h>
-#include <errno.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/hidemem.h>
-#include <ipxe/io.h>
-#include <ipxe/memblock.h>
-#include <ipxe/umalloc.h>
-
-/** Maximum usable address for external allocated memory */
-#define EM_MAX_ADDRESS 0xffffffffUL
-
-/** Alignment of external allocated memory */
-#define EM_ALIGN ( 4 * 1024 )
-
-/** Equivalent of NOWHERE for user pointers */
-#define UNOWHERE ( ~UNULL )
-
-/** An external memory block */
-struct external_memory {
- /** Size of this memory block (excluding this header) */
- size_t size;
- /** Block is currently in use */
- int used;
-};
-
-/** Top of heap */
-static userptr_t top = UNULL;
-
-/** Bottom of heap (current lowest allocated block) */
-static userptr_t bottom = UNULL;
-
-/** Remaining space on heap */
-static size_t heap_size;
-
-/**
- * Find largest usable memory region
- *
- * @ret start Start of region
- * @ret len Length of region
- */
-size_t largest_memblock ( userptr_t *start ) {
- struct memory_map memmap;
- struct memory_region *region;
- physaddr_t max = EM_MAX_ADDRESS;
- physaddr_t region_start;
- physaddr_t region_end;
- size_t region_len;
- unsigned int i;
- size_t len = 0;
-
- /* Avoid returning uninitialised data on error */
- *start = UNULL;
-
- /* Scan through all memory regions */
- get_memmap ( &memmap );
- for ( i = 0 ; i < memmap.count ; i++ ) {
- region = &memmap.regions[i];
- DBG ( "Considering [%llx,%llx)\n", region->start, region->end );
-
- /* Truncate block to maximum physical address */
- if ( region->start > max ) {
- DBG ( "...starts after maximum address %lx\n", max );
- continue;
- }
- region_start = region->start;
- if ( region->end > max ) {
- DBG ( "...end truncated to maximum address %lx\n", max);
- region_end = 0; /* =max, given the wraparound */
- } else {
- region_end = region->end;
- }
- region_len = ( region_end - region_start );
-
- /* Use largest block */
- if ( region_len > len ) {
- DBG ( "...new best block found\n" );
- *start = phys_to_user ( region_start );
- len = region_len;
- }
- }
-
- return len;
-}
-
-/**
- * Initialise external heap
- *
- */
-static void init_eheap ( void ) {
- userptr_t base;
-
- heap_size = largest_memblock ( &base );
- bottom = top = userptr_add ( base, heap_size );
- DBG ( "External heap grows downwards from %lx (size %zx)\n",
- user_to_phys ( top, 0 ), heap_size );
-}
-
-/**
- * Collect free blocks
- *
- */
-static void ecollect_free ( void ) {
- struct external_memory extmem;
- size_t len;
-
- /* Walk the free list and collect empty blocks */
- while ( bottom != top ) {
- copy_from_user ( &extmem, bottom, -sizeof ( extmem ),
- sizeof ( extmem ) );
- if ( extmem.used )
- break;
- DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ),
- user_to_phys ( bottom, extmem.size ) );
- len = ( extmem.size + sizeof ( extmem ) );
- bottom = userptr_add ( bottom, len );
- heap_size += len;
- }
-}
-
-/**
- * Reallocate external memory
- *
- * @v old_ptr Memory previously allocated by umalloc(), or UNULL
- * @v new_size Requested size
- * @ret new_ptr Allocated memory, or UNULL
- *
- * Calling realloc() with a new size of zero is a valid way to free a
- * memory block.
- */
-static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
- struct external_memory extmem;
- userptr_t new = ptr;
- size_t align;
-
- /* (Re)initialise external memory allocator if necessary */
- if ( bottom == top )
- init_eheap();
-
- /* Get block properties into extmem */
- if ( ptr && ( ptr != UNOWHERE ) ) {
- /* Determine old size */
- copy_from_user ( &extmem, ptr, -sizeof ( extmem ),
- sizeof ( extmem ) );
- } else {
- /* Create a zero-length block */
- if ( heap_size < sizeof ( extmem ) ) {
- DBG ( "EXTMEM out of space\n" );
- return UNULL;
- }
- ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) );
- heap_size -= sizeof ( extmem );
- DBG ( "EXTMEM allocating [%lx,%lx)\n",
- user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) );
- extmem.size = 0;
- }
- extmem.used = ( new_size > 0 );
-
- /* Expand/shrink block if possible */
- if ( ptr == bottom ) {
- /* Update block */
- new = userptr_add ( ptr, - ( new_size - extmem.size ) );
- align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) );
- new_size += align;
- new = userptr_add ( new, -align );
- if ( new_size > ( heap_size + extmem.size ) ) {
- DBG ( "EXTMEM out of space\n" );
- return UNULL;
- }
- DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n",
- user_to_phys ( ptr, 0 ),
- user_to_phys ( ptr, extmem.size ),
- user_to_phys ( new, 0 ),
- user_to_phys ( new, new_size ));
- memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ?
- extmem.size : new_size ) );
- bottom = new;
- heap_size -= ( new_size - extmem.size );
- extmem.size = new_size;
- } else {
- /* Cannot expand; can only pretend to shrink */
- if ( new_size > extmem.size ) {
- /* Refuse to expand */
- DBG ( "EXTMEM cannot expand [%lx,%lx)\n",
- user_to_phys ( ptr, 0 ),
- user_to_phys ( ptr, extmem.size ) );
- return UNULL;
- }
- }
-
- /* Write back block properties */
- copy_to_user ( new, -sizeof ( extmem ), &extmem,
- sizeof ( extmem ) );
-
- /* Collect any free blocks and update hidden memory region */
- ecollect_free();
- hide_umalloc ( user_to_phys ( bottom, ( ( bottom == top ) ?
- 0 : -sizeof ( extmem ) ) ),
- user_to_phys ( top, 0 ) );
-
- return ( new_size ? new : UNOWHERE );
-}
-
-PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc );
diff --git a/src/arch/x86/interface/pcbios/pcibios.c b/src/arch/x86/interface/pcbios/pcibios.c
index 7b7a769e3..6b88ee907 100644
--- a/src/arch/x86/interface/pcbios/pcibios.c
+++ b/src/arch/x86/interface/pcbios/pcibios.c
@@ -120,6 +120,7 @@ int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
return ( status >> 8 );
}
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_can_probe );
PROVIDE_PCIAPI ( pcbios, pci_discover, pcibios_discover );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word );
@@ -128,5 +129,4 @@ PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_ioremap );
-
-struct pci_api pcibios_api = PCIAPI_RUNTIME ( pcbios );
+PROVIDE_PCIAPI_RUNTIME ( pcbios, PCIAPI_PRIORITY_PCBIOS );
diff --git a/src/arch/x86/interface/pcbios/pcicloud.c b/src/arch/x86/interface/pcbios/pcicloud.c
deleted file mode 100644
index 98ba38b31..000000000
--- a/src/arch/x86/interface/pcbios/pcicloud.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2022 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 <stdint.h>
-#include <ipxe/init.h>
-#include <ipxe/pci.h>
-#include <ipxe/ecam.h>
-#include <ipxe/pcibios.h>
-#include <ipxe/pcidirect.h>
-#include <ipxe/pcicloud.h>
-
-/** @file
- *
- * Cloud VM PCI configuration space access
- *
- */
-
-/** Selected PCI configuration space access API */
-static struct pci_api *pcicloud = &ecam_api;
-
-/**
- * Find next PCI bus:dev.fn address range in system
- *
- * @v busdevfn Starting PCI bus:dev.fn address
- * @v range PCI bus:dev.fn address range to fill in
- */
-static void pcicloud_discover ( uint32_t busdevfn, struct pci_range *range ) {
-
- pcicloud->pci_discover ( busdevfn, range );
-}
-
-/**
- * Read byte from PCI configuration space
- *
- * @v pci PCI device
- * @v where Location within PCI configuration space
- * @v value Value read
- * @ret rc Return status code
- */
-static int pcicloud_read_config_byte ( struct pci_device *pci,
- unsigned int where, uint8_t *value ) {
-
- return pcicloud->pci_read_config_byte ( pci, where, value );
-}
-
-/**
- * Read 16-bit word from PCI configuration space
- *
- * @v pci PCI device
- * @v where Location within PCI configuration space
- * @v value Value read
- * @ret rc Return status code
- */
-static int pcicloud_read_config_word ( struct pci_device *pci,
- unsigned int where, uint16_t *value ) {
-
- return pcicloud->pci_read_config_word ( pci, where, value );
-}
-
-/**
- * Read 32-bit dword from PCI configuration space
- *
- * @v pci PCI device
- * @v where Location within PCI configuration space
- * @v value Value read
- * @ret rc Return status code
- */
-static int pcicloud_read_config_dword ( struct pci_device *pci,
- unsigned int where, uint32_t *value ) {
-
- return pcicloud->pci_read_config_dword ( pci, where, value );
-}
-
-/**
- * Write byte to PCI configuration space
- *
- * @v pci PCI device
- * @v where Location within PCI configuration space
- * @v value Value to be written
- * @ret rc Return status code
- */
-static int pcicloud_write_config_byte ( struct pci_device *pci,
- unsigned int where, uint8_t value ) {
-
- return pcicloud->pci_write_config_byte ( pci, where, value );
-}
-
-/**
- * Write 16-bit word to PCI configuration space
- *
- * @v pci PCI device
- * @v where Location within PCI configuration space
- * @v value Value to be written
- * @ret rc Return status code
- */
-static int pcicloud_write_config_word ( struct pci_device *pci,
- unsigned int where, uint16_t value ) {
-
- return pcicloud->pci_write_config_word ( pci, where, value );
-}
-
-/**
- * Write 32-bit dword to PCI configuration space
- *
- * @v pci PCI device
- * @v where Location within PCI configuration space
- * @v value Value to be written
- * @ret rc Return status code
- */
-static int pcicloud_write_config_dword ( struct pci_device *pci,
- unsigned int where, uint32_t value ) {
-
- return pcicloud->pci_write_config_dword ( pci, where, value );
-}
-
-/**
- * Map PCI bus address as an I/O address
- *
- * @v bus_addr PCI bus address
- * @v len Length of region
- * @ret io_addr I/O address, or NULL on error
- */
-static void * pcicloud_ioremap ( struct pci_device *pci,
- unsigned long bus_addr, size_t len ) {
-
- return pcicloud->pci_ioremap ( pci, bus_addr, len );
-}
-
-PROVIDE_PCIAPI ( cloud, pci_discover, pcicloud_discover );
-PROVIDE_PCIAPI ( cloud, pci_read_config_byte, pcicloud_read_config_byte );
-PROVIDE_PCIAPI ( cloud, pci_read_config_word, pcicloud_read_config_word );
-PROVIDE_PCIAPI ( cloud, pci_read_config_dword, pcicloud_read_config_dword );
-PROVIDE_PCIAPI ( cloud, pci_write_config_byte, pcicloud_write_config_byte );
-PROVIDE_PCIAPI ( cloud, pci_write_config_word, pcicloud_write_config_word );
-PROVIDE_PCIAPI ( cloud, pci_write_config_dword, pcicloud_write_config_dword );
-PROVIDE_PCIAPI ( cloud, pci_ioremap, pcicloud_ioremap );
-
-/**
- * Initialise cloud VM PCI configuration space access
- *
- */
-static void pcicloud_init ( void ) {
- static struct pci_api *apis[] = {
- &ecam_api, &pcibios_api, &pcidirect_api
- };
- struct pci_device pci;
- uint32_t busdevfn;
- unsigned int i;
- int rc;
-
- /* Select first API that successfully discovers a PCI device */
- for ( i = 0 ; i < ( sizeof ( apis ) / sizeof ( apis[0] ) ) ; i++ ) {
- pcicloud = apis[i];
- busdevfn = 0;
- if ( ( rc = pci_find_next ( &pci, &busdevfn ) ) == 0 ) {
- DBGC ( pcicloud, "PCICLOUD selected %s API (found "
- PCI_FMT ")\n", pcicloud->name,
- PCI_ARGS ( &pci ) );
- return;
- }
- }
-
- /* Fall back to using final attempted API if no devices found */
- pcicloud = apis[ i - 1 ];
- DBGC ( pcicloud, "PCICLOUD selected %s API (nothing detected)\n",
- pcicloud->name );
-}
-
-/** Cloud VM PCI configuration space access initialisation function */
-struct init_fn pcicloud_init_fn __init_fn ( INIT_EARLY ) = {
- .initialise = pcicloud_init,
-};
diff --git a/src/arch/x86/interface/pcbios/rsdp.c b/src/arch/x86/interface/pcbios/rsdp.c
index 3c67b7525..6913be552 100644
--- a/src/arch/x86/interface/pcbios/rsdp.c
+++ b/src/arch/x86/interface/pcbios/rsdp.c
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
#include <stdint.h>
+#include <string.h>
#include <realmode.h>
#include <bios.h>
#include <ipxe/acpi.h>
@@ -53,50 +54,51 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* @v start Start address to search
* @v len Length to search
- * @ret rsdt ACPI root system description table, or UNULL
+ * @ret rsdt ACPI root system description table, or NULL
*/
-static userptr_t rsdp_find_rsdt_range ( userptr_t start, size_t len ) {
+static const struct acpi_rsdt * rsdp_find_rsdt_range ( const void *start,
+ size_t len ) {
static const char signature[8] = RSDP_SIGNATURE;
- struct acpi_rsdp rsdp;
- userptr_t rsdt;
+ const struct acpi_rsdp *rsdp;
+ const struct acpi_rsdt *rsdt;
size_t offset;
uint8_t sum;
unsigned int i;
/* Search for RSDP */
- for ( offset = 0 ; ( ( offset + sizeof ( rsdp ) ) < len ) ;
+ for ( offset = 0 ; ( ( offset + sizeof ( *rsdp ) ) < len ) ;
offset += RSDP_STRIDE ) {
/* Check signature and checksum */
- copy_from_user ( &rsdp, start, offset, sizeof ( rsdp ) );
- if ( memcmp ( rsdp.signature, signature,
+ rsdp = ( start + offset );
+ if ( memcmp ( rsdp->signature, signature,
sizeof ( signature ) ) != 0 )
continue;
- for ( sum = 0, i = 0 ; i < sizeof ( rsdp ) ; i++ )
- sum += *( ( ( uint8_t * ) &rsdp ) + i );
+ for ( sum = 0, i = 0 ; i < sizeof ( *rsdp ) ; i++ )
+ sum += *( ( ( uint8_t * ) rsdp ) + i );
if ( sum != 0 )
continue;
/* Extract RSDT */
- rsdt = phys_to_user ( le32_to_cpu ( rsdp.rsdt ) );
+ rsdt = phys_to_virt ( le32_to_cpu ( rsdp->rsdt ) );
DBGC ( rsdt, "RSDT %#08lx found via RSDP %#08lx\n",
- user_to_phys ( rsdt, 0 ),
- user_to_phys ( start, offset ) );
+ virt_to_phys ( rsdt ),
+ ( virt_to_phys ( start ) + offset ) );
return rsdt;
}
- return UNULL;
+ return NULL;
}
/**
* Locate ACPI root system description table
*
- * @ret rsdt ACPI root system description table, or UNULL
+ * @ret rsdt ACPI root system description table, or NULL
*/
-static userptr_t rsdp_find_rsdt ( void ) {
- static userptr_t rsdt;
+static const struct acpi_rsdt * rsdp_find_rsdt ( void ) {
+ static const struct acpi_rsdt *rsdt;
+ const void *ebda;
uint16_t ebda_seg;
- userptr_t ebda;
size_t ebda_len;
/* Return existing RSDT if already found */
@@ -106,7 +108,7 @@ static userptr_t rsdp_find_rsdt ( void ) {
/* Search EBDA */
get_real ( ebda_seg, BDA_SEG, BDA_EBDA );
if ( ebda_seg < RSDP_EBDA_END_SEG ) {
- ebda = real_to_user ( ebda_seg, 0 );
+ ebda = real_to_virt ( ebda_seg, 0 );
ebda_len = ( ( RSDP_EBDA_END_SEG - ebda_seg ) * 16 );
rsdt = rsdp_find_rsdt_range ( ebda, ebda_len );
if ( rsdt )
@@ -114,12 +116,12 @@ static userptr_t rsdp_find_rsdt ( void ) {
}
/* Search fixed BIOS area */
- rsdt = rsdp_find_rsdt_range ( phys_to_user ( RSDP_BIOS_START ),
+ rsdt = rsdp_find_rsdt_range ( phys_to_virt ( RSDP_BIOS_START ),
RSDP_BIOS_LEN );
if ( rsdt )
return rsdt;
- return UNULL;
+ return NULL;
}
PROVIDE_ACPI ( rsdp, acpi_find_rsdt, rsdp_find_rsdt );
diff --git a/src/arch/x86/interface/pcbios/rtc_entropy.c b/src/arch/x86/interface/pcbios/rtc_entropy.c
index 8f47ff6b8..7c98019b6 100644
--- a/src/arch/x86/interface/pcbios/rtc_entropy.c
+++ b/src/arch/x86/interface/pcbios/rtc_entropy.c
@@ -53,6 +53,12 @@ extern void rtc_isr ( void );
/** Previous RTC interrupt handler */
static struct segoff rtc_old_handler;
+/** Previous RTC interrupt enabled state */
+static uint8_t rtc_irq_enabled;
+
+/** Previous RTC periodic interrupt enabled state */
+static uint8_t rtc_int_enabled;
+
/** Flag set by RTC interrupt handler */
extern volatile uint8_t __text16 ( rtc_flag );
#define rtc_flag __use_text16 ( rtc_flag )
@@ -107,8 +113,9 @@ static void rtc_unhook_isr ( void ) {
/**
* Enable RTC interrupts
*
+ * @ret enabled Periodic interrupt was previously enabled
*/
-static void rtc_enable_int ( void ) {
+static int rtc_enable_int ( void ) {
uint8_t status_b;
/* Clear any stale pending interrupts via status register C */
@@ -124,6 +131,9 @@ static void rtc_enable_int ( void ) {
/* Re-enable NMI and reset to default address */
outb ( CMOS_DEFAULT_ADDRESS, CMOS_ADDRESS );
inb ( CMOS_DATA ); /* Discard; may be needed on some platforms */
+
+ /* Return previous state */
+ return ( status_b & RTC_STATUS_B_PIE );
}
/**
@@ -198,8 +208,11 @@ static int rtc_entropy_enable ( void ) {
/* Hook ISR and enable RTC interrupts */
rtc_hook_isr();
- enable_irq ( RTC_IRQ );
- rtc_enable_int();
+ rtc_irq_enabled = enable_irq ( RTC_IRQ );
+ rtc_int_enabled = rtc_enable_int();
+ DBGC ( &rtc_flag, "RTC had IRQ%d %sabled, interrupt %sabled\n",
+ RTC_IRQ, ( rtc_irq_enabled ? "en" : "dis" ),
+ ( rtc_int_enabled ? "en" : "dis" ) );
/* Check that RTC interrupts are working */
if ( ( rc = rtc_entropy_check() ) != 0 )
@@ -223,8 +236,10 @@ static int rtc_entropy_enable ( void ) {
return 0;
err_check:
- rtc_disable_int();
- disable_irq ( RTC_IRQ );
+ if ( ! rtc_int_enabled )
+ rtc_disable_int();
+ if ( ! rtc_irq_enabled )
+ disable_irq ( RTC_IRQ );
rtc_unhook_isr();
err_no_tsc:
return rc;
@@ -236,9 +251,11 @@ static int rtc_entropy_enable ( void ) {
*/
static void rtc_entropy_disable ( void ) {
- /* Disable RTC interrupts and unhook ISR */
- rtc_disable_int();
- disable_irq ( RTC_IRQ );
+ /* Restore RTC interrupt state and unhook ISR */
+ if ( ! rtc_int_enabled )
+ rtc_disable_int();
+ if ( ! rtc_irq_enabled )
+ disable_irq ( RTC_IRQ );
rtc_unhook_isr();
}
diff --git a/src/arch/x86/interface/pcbios/vesafb.c b/src/arch/x86/interface/pcbios/vesafb.c
index 3ca15271a..48394bdd9 100644
--- a/src/arch/x86/interface/pcbios/vesafb.c
+++ b/src/arch/x86/interface/pcbios/vesafb.c
@@ -103,7 +103,7 @@ struct vesafb {
/** Font definition */
struct fbcon_font font;
/** Character glyphs */
- struct segoff glyphs;
+ const uint8_t *glyphs;
/** Saved VGA mode */
uint8_t saved_mode;
};
@@ -140,11 +140,10 @@ static int vesafb_rc ( unsigned int status ) {
* Get character glyph
*
* @v character Unicode character
- * @v glyph Character glyph to fill in
+ * @ret glyph Character glyph
*/
-static void vesafb_glyph ( unsigned int character, uint8_t *glyph ) {
+static const uint8_t * vesafb_glyph ( unsigned int character ) {
unsigned int index;
- size_t offset;
/* Identify glyph */
if ( character < VESAFB_ASCII ) {
@@ -287,10 +286,8 @@ static void vesafb_glyph ( unsigned int character, uint8_t *glyph ) {
}
}
- /* Copy glyph from BIOS font table */
- offset = ( index * VESAFB_CHAR_HEIGHT );
- copy_from_real ( glyph, vesafb.glyphs.segment,
- ( vesafb.glyphs.offset + offset ), VESAFB_CHAR_HEIGHT);
+ /* Return glyph in BIOS font table */
+ return &vesafb.glyphs[ index * VESAFB_CHAR_HEIGHT ];
}
/**
@@ -298,6 +295,7 @@ static void vesafb_glyph ( unsigned int character, uint8_t *glyph ) {
*
*/
static void vesafb_font ( void ) {
+ struct segoff glyphs;
/* Get font information
*
@@ -318,12 +316,13 @@ static void vesafb_font ( void ) {
"movw %%es, %%cx\n\t"
"movw %%bp, %%dx\n\t"
"popw %%bp\n\t" /* gcc bug */ )
- : "=c" ( vesafb.glyphs.segment ),
- "=d" ( vesafb.glyphs.offset )
+ : "=c" ( glyphs.segment ),
+ "=d" ( glyphs.offset )
: "a" ( VBE_GET_FONT ),
"b" ( VESAFB_FONT ) );
DBGC ( &vbe_buf, "VESAFB has font %04x at %04x:%04x\n",
- VESAFB_FONT, vesafb.glyphs.segment, vesafb.glyphs.offset );
+ VESAFB_FONT, glyphs.segment, glyphs.offset );
+ vesafb.glyphs = real_to_virt ( glyphs.segment, glyphs.offset );
vesafb.font.height = VESAFB_CHAR_HEIGHT;
vesafb.font.glyph = vesafb_glyph;
}
@@ -338,8 +337,8 @@ static void vesafb_font ( void ) {
*/
static int vesafb_mode_list ( uint16_t **mode_numbers ) {
struct vbe_controller_info *controller = &vbe_buf.controller;
- userptr_t video_mode_ptr;
- uint16_t mode_number;
+ const uint16_t *video_mode_ptr;
+ const uint16_t *mode_number;
uint16_t status;
size_t len;
int rc;
@@ -375,20 +374,18 @@ static int vesafb_mode_list ( uint16_t **mode_numbers ) {
controller->video_mode_ptr.offset );
/* Calculate length of mode list */
- video_mode_ptr = real_to_user ( controller->video_mode_ptr.segment,
+ video_mode_ptr = real_to_virt ( controller->video_mode_ptr.segment,
controller->video_mode_ptr.offset );
- len = 0;
- do {
- copy_from_user ( &mode_number, video_mode_ptr, len,
- sizeof ( mode_number ) );
- len += sizeof ( mode_number );
- } while ( mode_number != VBE_MODE_END );
+ mode_number = video_mode_ptr;
+ while ( *(mode_number++) != VBE_MODE_END ) {}
+ len = ( ( ( const void * ) mode_number ) -
+ ( ( const void * ) video_mode_ptr ) );
/* Allocate and fill mode list */
*mode_numbers = malloc ( len );
if ( ! *mode_numbers )
return -ENOMEM;
- copy_from_user ( *mode_numbers, video_mode_ptr, 0, len );
+ memcpy ( *mode_numbers, video_mode_ptr, len );
return 0;
}
@@ -607,7 +604,7 @@ static int vesafb_init ( struct console_configuration *config ) {
}
/* Initialise frame buffer console */
- if ( ( rc = fbcon_init ( &vesafb.fbcon, phys_to_user ( vesafb.start ),
+ if ( ( rc = fbcon_init ( &vesafb.fbcon, phys_to_virt ( vesafb.start ),
&vesafb.pixel, &vesafb.map, &vesafb.font,
config ) ) != 0 )
goto err_fbcon_init;
diff --git a/src/arch/x86/interface/pxe/pxe_call.c b/src/arch/x86/interface/pxe/pxe_call.c
index 0e8d5c5a8..9a6a20dd3 100644
--- a/src/arch/x86/interface/pxe/pxe_call.c
+++ b/src/arch/x86/interface/pxe/pxe_call.c
@@ -55,12 +55,12 @@ extern void pxe_int_1a ( void );
static int int_1a_hooked = 0;
/** Real-mode code segment size */
-extern char _text16_memsz[];
-#define _text16_memsz ( ( size_t ) _text16_memsz )
+extern size_t ABS_SYMBOL ( _text16_memsz );
+#define _text16_memsz ABS_VALUE ( _text16_memsz )
/** Real-mode data segment size */
-extern char _data16_memsz[];
-#define _data16_memsz ( ( size_t ) _data16_memsz )
+extern size_t ABS_SYMBOL (_data16_memsz );
+#define _data16_memsz ABS_VALUE ( _data16_memsz )
/** PXENV_UNDI_TRANSMIT API call profiler */
static struct profiler pxe_api_tx_profiler __profiler =
@@ -144,10 +144,10 @@ static struct profiler * pxe_api_profiler ( unsigned int opcode ) {
*/
__asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
uint16_t opcode = ix86->regs.bx;
- userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di );
struct profiler *profiler = pxe_api_profiler ( opcode );
+ union u_PXENV_ANY *params =
+ real_to_virt ( ix86->segs.es, ix86->regs.di );
struct pxe_api_call *call;
- union u_PXENV_ANY params;
PXENV_EXIT_t ret;
/* Start profiling */
@@ -160,17 +160,13 @@ __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
call = &pxenv_unknown_api;
}
- /* Copy parameter block from caller */
- copy_from_user ( &params, uparams, 0, call->params_len );
-
/* Set default status in case child routine fails to do so */
- params.Status = PXENV_STATUS_FAILURE;
+ params->Status = PXENV_STATUS_FAILURE;
/* Hand off to relevant API routine */
- ret = call->entry ( &params );
+ ret = call->entry ( params );
- /* Copy modified parameter block back to caller and return */
- copy_to_user ( uparams, 0, &params, call->params_len );
+ /* Return exit code in %ax */
ix86->regs.ax = ret;
/* Stop profiling, if applicable */
@@ -195,24 +191,20 @@ int pxe_api_call_weak ( struct i386_all_regs *ix86 ) {
* @ret ax PXE exit code
*/
__asmcall void pxe_loader_call ( struct i386_all_regs *ix86 ) {
- userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di );
- struct s_UNDI_LOADER params;
+ struct s_UNDI_LOADER *params =
+ real_to_virt ( ix86->segs.es, ix86->regs.di );
PXENV_EXIT_t ret;
- /* Copy parameter block from caller */
- copy_from_user ( &params, uparams, 0, sizeof ( params ) );
-
/* Fill in ROM segment address */
ppxe.UNDIROMID.segment = ix86->segs.ds;
/* Set default status in case child routine fails to do so */
- params.Status = PXENV_STATUS_FAILURE;
+ params->Status = PXENV_STATUS_FAILURE;
/* Call UNDI loader */
- ret = undi_loader ( &params );
+ ret = undi_loader ( params );
- /* Copy modified parameter block back to caller and return */
- copy_to_user ( uparams, 0, &params, sizeof ( params ) );
+ /* Return exit code in %ax */
ix86->regs.ax = ret;
}
@@ -265,6 +257,7 @@ static void pxe_init_structures ( void ) {
/** PXE structure initialiser */
struct init_fn pxe_init_fn __init_fn ( INIT_NORMAL ) = {
+ .name = "pxe",
.initialise = pxe_init_structures,
};
diff --git a/src/arch/x86/interface/pxe/pxe_file.c b/src/arch/x86/interface/pxe/pxe_file.c
index 456ffb5fd..997667ccf 100644
--- a/src/arch/x86/interface/pxe/pxe_file.c
+++ b/src/arch/x86/interface/pxe/pxe_file.c
@@ -8,7 +8,6 @@
#include <stdio.h>
#include <errno.h>
#include <byteswap.h>
-#include <ipxe/uaccess.h>
#include <ipxe/posix_io.h>
#include <ipxe/features.h>
#include <pxe.h>
@@ -53,30 +52,20 @@ FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 );
*
*/
static PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) {
- userptr_t filename;
- size_t filename_len;
+ const char *filename;
int fd;
DBG ( "PXENV_FILE_OPEN" );
- /* Copy name from external program, and open it */
- filename = real_to_user ( file_open->FileName.segment,
- file_open->FileName.offset );
- filename_len = strlen_user ( filename, 0 );
- {
- char uri_string[ filename_len + 1 ];
-
- copy_from_user ( uri_string, filename, 0,
- sizeof ( uri_string ) );
- DBG ( " %s", uri_string );
- fd = open ( uri_string );
- }
-
+ /* Open specified filename */
+ filename = real_to_virt ( file_open->FileName.segment,
+ file_open->FileName.offset );
+ DBG ( " %s", filename );
+ fd = open ( filename );
if ( fd < 0 ) {
file_open->Status = PXENV_STATUS ( fd );
return PXENV_EXIT_FAILURE;
}
-
DBG ( " as file %d", fd );
file_open->FileHandle = fd;
@@ -148,17 +137,17 @@ pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) {
*
*/
static PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) {
- userptr_t buffer;
+ void *buffer;
ssize_t len;
DBG ( "PXENV_FILE_READ %d to %04x:%04x+%04x", file_read->FileHandle,
file_read->Buffer.segment, file_read->Buffer.offset,
file_read->BufferSize );
- buffer = real_to_user ( file_read->Buffer.segment,
+ buffer = real_to_virt ( file_read->Buffer.segment,
file_read->Buffer.offset );
- if ( ( len = read_user ( file_read->FileHandle, buffer, 0,
- file_read->BufferSize ) ) < 0 ) {
+ if ( ( len = read ( file_read->FileHandle, buffer,
+ file_read->BufferSize ) ) < 0 ) {
file_read->Status = PXENV_STATUS ( len );
return PXENV_EXIT_FAILURE;
}
@@ -210,27 +199,18 @@ pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE *get_file_size ) {
*
*/
static PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
- userptr_t command;
- size_t command_len;
+ const char *command;
int rc;
DBG ( "PXENV_FILE_EXEC" );
- /* Copy name from external program, and exec it */
- command = real_to_user ( file_exec->Command.segment,
+ /* Execute specified command */
+ command = real_to_virt ( file_exec->Command.segment,
file_exec->Command.offset );
- command_len = strlen_user ( command, 0 );
- {
- char command_string[ command_len + 1 ];
-
- copy_from_user ( command_string, command, 0,
- sizeof ( command_string ) );
- DBG ( " %s", command_string );
-
- if ( ( rc = system ( command_string ) ) != 0 ) {
- file_exec->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
+ DBG ( " %s", command );
+ if ( ( rc = system ( command ) ) != 0 ) {
+ file_exec->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
}
file_exec->Status = PXENV_STATUS_SUCCESS;
@@ -251,23 +231,22 @@ static PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
*/
static PXENV_EXIT_t
pxenv_file_cmdline ( struct s_PXENV_FILE_CMDLINE *file_cmdline ) {
- userptr_t buffer;
- size_t max_len;
+ char *buffer;
size_t len;
DBG ( "PXENV_FILE_CMDLINE to %04x:%04x+%04x \"%s\"\n",
file_cmdline->Buffer.segment, file_cmdline->Buffer.offset,
file_cmdline->BufferSize, pxe_cmdline );
- buffer = real_to_user ( file_cmdline->Buffer.segment,
+ buffer = real_to_virt ( file_cmdline->Buffer.segment,
file_cmdline->Buffer.offset );
len = file_cmdline->BufferSize;
- max_len = ( pxe_cmdline ?
- ( strlen ( pxe_cmdline ) + 1 /* NUL */ ) : 0 );
- if ( len > max_len )
- len = max_len;
- copy_to_user ( buffer, 0, pxe_cmdline, len );
- file_cmdline->BufferSize = max_len;
+ if ( pxe_cmdline ) {
+ len = snprintf ( buffer, len, "%s", pxe_cmdline );
+ file_cmdline->BufferSize = ( len + 1 /* NUL */ );
+ } else {
+ file_cmdline->BufferSize = 0;
+ }
file_cmdline->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
diff --git a/src/arch/x86/interface/pxe/pxe_preboot.c b/src/arch/x86/interface/pxe/pxe_preboot.c
index 09e721b34..863aaae9a 100644
--- a/src/arch/x86/interface/pxe/pxe_preboot.c
+++ b/src/arch/x86/interface/pxe/pxe_preboot.c
@@ -33,7 +33,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
-#include <ipxe/uaccess.h>
#include <ipxe/dhcp.h>
#include <ipxe/fakedhcp.h>
#include <ipxe/device.h>
@@ -48,7 +47,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include "pxe_call.h"
/* Avoid dragging in isapnp.o unnecessarily */
-uint16_t isapnp_read_port;
+uint16_t isapnp_read_port __attribute__ (( weak ));
/** Zero-based versions of PXENV_GET_CACHED_INFO::PacketType */
enum pxe_cached_info_indices {
@@ -184,7 +183,7 @@ pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
union pxe_cached_info *info;
unsigned int idx;
size_t len;
- userptr_t buffer;
+ void *buffer;
DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
pxenv_get_cached_info_name ( get_cached_info->PacketType ),
@@ -243,9 +242,9 @@ pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
len = sizeof ( *info );
if ( len < sizeof ( *info ) )
DBGC ( &pxe_netdev, " buffer may be too short" );
- buffer = real_to_user ( get_cached_info->Buffer.segment,
+ buffer = real_to_virt ( get_cached_info->Buffer.segment,
get_cached_info->Buffer.offset );
- copy_to_user ( buffer, 0, info, len );
+ memcpy ( buffer, info, len );
get_cached_info->BufferSize = len;
}
diff --git a/src/arch/x86/interface/pxe/pxe_tftp.c b/src/arch/x86/interface/pxe/pxe_tftp.c
index 3b4c6d847..aa675fd13 100644
--- a/src/arch/x86/interface/pxe/pxe_tftp.c
+++ b/src/arch/x86/interface/pxe/pxe_tftp.c
@@ -33,7 +33,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdio.h>
#include <errno.h>
#include <byteswap.h>
-#include <ipxe/uaccess.h>
#include <ipxe/in.h>
#include <ipxe/tftp.h>
#include <ipxe/iobuf.h>
@@ -49,7 +48,7 @@ struct pxe_tftp_connection {
/** Data transfer interface */
struct interface xfer;
/** Data buffer */
- userptr_t buffer;
+ void *buffer;
/** Size of data buffer */
size_t size;
/** Starting offset of data buffer */
@@ -121,9 +120,8 @@ static int pxe_tftp_xfer_deliver ( struct pxe_tftp_connection *pxe_tftp,
( pxe_tftp->start + pxe_tftp->size ) );
rc = -ENOBUFS;
} else {
- copy_to_user ( pxe_tftp->buffer,
- ( pxe_tftp->offset - pxe_tftp->start ),
- iobuf->data, len );
+ memcpy ( ( pxe_tftp->buffer + pxe_tftp->offset -
+ pxe_tftp->start ), iobuf->data, len );
}
/* Calculate new buffer position */
@@ -378,14 +376,14 @@ static PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) {
tftp_read->Buffer.segment, tftp_read->Buffer.offset );
/* Read single block into buffer */
- pxe_tftp.buffer = real_to_user ( tftp_read->Buffer.segment,
+ pxe_tftp.buffer = real_to_virt ( tftp_read->Buffer.segment,
tftp_read->Buffer.offset );
pxe_tftp.size = pxe_tftp.blksize;
pxe_tftp.start = pxe_tftp.offset;
while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
( pxe_tftp.offset == pxe_tftp.start ) )
step();
- pxe_tftp.buffer = UNULL;
+ pxe_tftp.buffer = NULL;
tftp_read->BufferSize = ( pxe_tftp.offset - pxe_tftp.start );
tftp_read->PacketNumber = ++pxe_tftp.blkidx;
@@ -492,11 +490,11 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
}
/* Read entire file */
- pxe_tftp.buffer = phys_to_user ( tftp_read_file->Buffer );
+ pxe_tftp.buffer = phys_to_virt ( tftp_read_file->Buffer );
pxe_tftp.size = tftp_read_file->BufferSize;
while ( ( rc = pxe_tftp.rc ) == -EINPROGRESS )
step();
- pxe_tftp.buffer = UNULL;
+ pxe_tftp.buffer = NULL;
tftp_read_file->BufferSize = pxe_tftp.max_offset;
/* Close TFTP file */
diff --git a/src/arch/x86/interface/pxe/pxe_udp.c b/src/arch/x86/interface/pxe/pxe_udp.c
index a5d5eb77b..61c858dde 100644
--- a/src/arch/x86/interface/pxe/pxe_udp.c
+++ b/src/arch/x86/interface/pxe/pxe_udp.c
@@ -9,7 +9,6 @@
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/udp.h>
-#include <ipxe/uaccess.h>
#include <ipxe/process.h>
#include <ipxe/netdevice.h>
#include <ipxe/malloc.h>
@@ -296,7 +295,7 @@ pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
};
size_t len;
struct io_buffer *iobuf;
- userptr_t buffer;
+ const void *buffer;
int rc;
DBG ( "PXENV_UDP_WRITE" );
@@ -328,9 +327,9 @@ pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
pxenv_udp_write->Status = PXENV_STATUS_OUT_OF_RESOURCES;
return PXENV_EXIT_FAILURE;
}
- buffer = real_to_user ( pxenv_udp_write->buffer.segment,
+ buffer = real_to_virt ( pxenv_udp_write->buffer.segment,
pxenv_udp_write->buffer.offset );
- copy_from_user ( iob_put ( iobuf, len ), buffer, 0, len );
+ memcpy ( iob_put ( iobuf, len ), buffer, len );
DBG ( " %04x:%04x+%x %d->%s:%d\n", pxenv_udp_write->buffer.segment,
pxenv_udp_write->buffer.offset, pxenv_udp_write->buffer_size,
@@ -400,7 +399,7 @@ static PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
struct pxe_udp_pseudo_header *pshdr;
uint16_t d_port_wanted = pxenv_udp_read->d_port;
uint16_t d_port;
- userptr_t buffer;
+ void *buffer;
size_t len;
/* Try receiving a packet, if the queue is empty */
@@ -438,12 +437,12 @@ static PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
}
/* Copy packet to buffer and record length */
- buffer = real_to_user ( pxenv_udp_read->buffer.segment,
+ buffer = real_to_virt ( pxenv_udp_read->buffer.segment,
pxenv_udp_read->buffer.offset );
len = iob_len ( iobuf );
if ( len > pxenv_udp_read->buffer_size )
len = pxenv_udp_read->buffer_size;
- copy_to_user ( buffer, 0, iobuf->data, len );
+ memcpy ( buffer, iobuf->data, len );
pxenv_udp_read->buffer_size = len;
/* Fill in source/dest information */
diff --git a/src/arch/x86/interface/syslinux/com32_call.c b/src/arch/x86/interface/syslinux/com32_call.c
index 19fdbaff9..a23f46436 100644
--- a/src/arch/x86/interface/syslinux/com32_call.c
+++ b/src/arch/x86/interface/syslinux/com32_call.c
@@ -49,9 +49,8 @@ void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physad
DBGC ( &com32_regs, "COM32 INT%x in %#08lx out %#08lx\n",
interrupt, inregs_phys, outregs_phys );
- memcpy_user ( virt_to_user( &com32_regs ), 0,
- phys_to_user ( inregs_phys ), 0,
- sizeof(com32sys_t) );
+ memcpy ( &com32_regs, phys_to_virt ( inregs_phys ),
+ sizeof ( com32sys_t ) );
com32_int_vector = interrupt;
@@ -108,9 +107,8 @@ void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physad
: : );
if ( outregs_phys ) {
- memcpy_user ( phys_to_user ( outregs_phys ), 0,
- virt_to_user( &com32_regs ), 0,
- sizeof(com32sys_t) );
+ memcpy ( phys_to_virt ( outregs_phys ),
+ &com32_regs, sizeof ( com32sys_t ) );
}
}
@@ -122,9 +120,8 @@ void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t
DBGC ( &com32_regs, "COM32 farcall %04x:%04x in %#08lx out %#08lx\n",
( proc >> 16 ), ( proc & 0xffff ), inregs_phys, outregs_phys );
- memcpy_user ( virt_to_user( &com32_regs ), 0,
- phys_to_user ( inregs_phys ), 0,
- sizeof(com32sys_t) );
+ memcpy ( &com32_regs, phys_to_virt ( inregs_phys ),
+ sizeof ( com32sys_t ) );
com32_farcall_proc = proc;
@@ -170,9 +167,8 @@ void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t
: : );
if ( outregs_phys ) {
- memcpy_user ( phys_to_user ( outregs_phys ), 0,
- virt_to_user( &com32_regs ), 0,
- sizeof(com32sys_t) );
+ memcpy ( phys_to_virt ( outregs_phys ),
+ &com32_regs, sizeof ( com32sys_t ) );
}
}
@@ -185,7 +181,7 @@ int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz )
DBGC ( &com32_regs, "COM32 cfarcall %04x:%04x params %#08lx+%#zx\n",
( proc >> 16 ), ( proc & 0xffff ), stack, stacksz );
- copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz );
+ copy_to_rm_stack ( phys_to_virt ( stack ), stacksz );
com32_farcall_proc = proc;
__asm__ __volatile__ (
@@ -194,7 +190,7 @@ int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz )
:
: "ecx", "edx" );
- remove_user_from_rm_stack ( 0, stacksz );
+ remove_from_rm_stack ( NULL, stacksz );
return eax;
}
diff --git a/src/arch/x86/interface/syslinux/comboot_call.c b/src/arch/x86/interface/syslinux/comboot_call.c
index b75e8ef7c..c3e921075 100644
--- a/src/arch/x86/interface/syslinux/comboot_call.c
+++ b/src/arch/x86/interface/syslinux/comboot_call.c
@@ -37,6 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/posix_io.h>
#include <ipxe/process.h>
#include <ipxe/serial.h>
+#include <ipxe/ns16550.h>
#include <ipxe/init.h>
#include <ipxe/image.h>
#include <ipxe/version.h>
@@ -88,14 +89,9 @@ static uint16_t comboot_graphics_mode = 0;
* Print a string with a particular terminator
*/
static void print_user_string ( unsigned int segment, unsigned int offset, char terminator ) {
- int i = 0;
- char c;
- userptr_t str = real_to_user ( segment, offset );
- for ( ; ; ) {
- copy_from_user ( &c, str, i, 1 );
- if ( c == terminator ) break;
- putchar ( c );
- i++;
+ char *c;
+ for ( c = real_to_virt ( segment, offset ) ; *c != terminator ; c++ ) {
+ putchar ( *c );
}
}
@@ -109,26 +105,26 @@ static void shuffle ( unsigned int list_segment, unsigned int list_offset, unsig
unsigned int i;
/* Copy shuffle descriptor list so it doesn't get overwritten */
- copy_from_user ( shuf, real_to_user ( list_segment, list_offset ), 0,
- count * sizeof( comboot_shuffle_descriptor ) );
+ memcpy ( shuf, real_to_virt ( list_segment, list_offset ),
+ count * sizeof( comboot_shuffle_descriptor ) );
/* Do the copies */
for ( i = 0; i < count; i++ ) {
- userptr_t src_u = phys_to_user ( shuf[ i ].src );
- userptr_t dest_u = phys_to_user ( shuf[ i ].dest );
+ const void *src = phys_to_virt ( shuf[ i ].src );
+ void *dest = phys_to_virt ( shuf[ i ].dest );
if ( shuf[ i ].src == 0xFFFFFFFF ) {
/* Fill with 0 instead of copying */
- memset_user ( dest_u, 0, 0, shuf[ i ].len );
+ memset ( dest, 0, shuf[ i ].len );
} else if ( shuf[ i ].dest == 0xFFFFFFFF ) {
/* Copy new list of descriptors */
count = shuf[ i ].len / sizeof( comboot_shuffle_descriptor );
assert ( count <= COMBOOT_MAX_SHUFFLE_DESCRIPTORS );
- copy_from_user ( shuf, src_u, 0, shuf[ i ].len );
+ memcpy ( shuf, src, shuf[ i ].len );
i = -1;
} else {
/* Regular copy */
- memmove_user ( dest_u, 0, src_u, 0, shuf[ i ].len );
+ memmove ( dest, src, shuf[ i ].len );
}
}
}
@@ -164,7 +160,7 @@ void comboot_force_text_mode ( void ) {
/**
* Fetch kernel and optional initrd
*/
-static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
+static int comboot_fetch_kernel ( const char *kernel_file, char *cmdline ) {
struct image *kernel;
struct image *initrd;
char *initrd_file;
@@ -258,8 +254,8 @@ static __asmcall __used void int21 ( struct i386_all_regs *ix86 ) {
break;
case 0x04: /* Write Character to Serial Port */
- if ( serial_console.base ) {
- uart_transmit ( &serial_console, ix86->regs.dl );
+ if ( serial_console ) {
+ uart_transmit ( serial_console, ix86->regs.dl );
ix86->flags &= ~CF;
}
break;
@@ -346,10 +342,8 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
case 0x0003: /* Run command */
{
- userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
- int len = strlen_user ( cmd_u, 0 );
- char cmd[len + 1];
- copy_from_user ( cmd, cmd_u, 0, len + 1 );
+ const char *cmd = real_to_virt ( ix86->segs.es,
+ ix86->regs.bx );
DBG ( "COMBOOT: executing command '%s'\n", cmd );
system ( cmd );
DBG ( "COMBOOT: exiting after executing command...\n" );
@@ -370,11 +364,8 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
case 0x0006: /* Open file */
{
int fd;
- userptr_t file_u = real_to_user ( ix86->segs.es, ix86->regs.si );
- int len = strlen_user ( file_u, 0 );
- char file[len + 1];
-
- copy_from_user ( file, file_u, 0, len + 1 );
+ const char *file = real_to_virt ( ix86->segs.es,
+ ix86->regs.si );
if ( file[0] == '\0' ) {
DBG ( "COMBOOT: attempted open with empty file name\n" );
@@ -410,7 +401,8 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
int len = ix86->regs.cx * COMBOOT_FILE_BLOCKSZ;
int rc;
fd_set fds;
- userptr_t buf = real_to_user ( ix86->segs.es, ix86->regs.bx );
+ void *buf = real_to_virt ( ix86->segs.es,
+ ix86->regs.bx );
/* Wait for data ready to read */
FD_ZERO ( &fds );
@@ -418,7 +410,7 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
select ( &fds, 1 );
- rc = read_user ( fd, buf, 0, len );
+ rc = read ( fd, buf, len );
if ( rc < 0 ) {
DBG ( "COMBOOT: read failed\n" );
ix86->regs.si = 0;
@@ -454,9 +446,11 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
break;
case 0x000B: /* Get Serial Console Configuration */
- if ( serial_console.base ) {
- ix86->regs.dx = ( ( intptr_t ) serial_console.base );
- ix86->regs.cx = serial_console.divisor;
+ if ( serial_console ) {
+ struct ns16550_uart *comport = serial_console->priv;
+
+ ix86->regs.dx = ( ( intptr_t ) comport->base );
+ ix86->regs.cx = comport->divisor;
ix86->regs.bx = 0;
ix86->flags &= ~CF;
}
@@ -483,13 +477,10 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
case 0x0010: /* Resolve hostname */
{
- userptr_t hostname_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
- int len = strlen_user ( hostname_u, 0 );
- char hostname[len];
+ const char *hostname = real_to_virt ( ix86->segs.es,
+ ix86->regs.bx );
struct in_addr addr;
- copy_from_user ( hostname, hostname_u, 0, len + 1 );
-
/* TODO:
* "If the hostname does not contain a dot (.), the
* local domain name is automatically appended."
@@ -526,8 +517,8 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
"lret\n\t"
)
:
- : "r" ( ix86->segs.ds ),
- "r" ( ix86->regs.ebp ),
+ : "R" ( ix86->segs.ds ),
+ "R" ( ix86->regs.ebp ),
"d" ( ix86->regs.ebx ),
"S" ( ix86->regs.esi ) );
@@ -549,15 +540,10 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
case 0x0016: /* Run kernel image */
{
- userptr_t file_u = real_to_user ( ix86->segs.ds, ix86->regs.si );
- userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
- int file_len = strlen_user ( file_u, 0 );
- int cmd_len = strlen_user ( cmd_u, 0 );
- char file[file_len + 1];
- char cmd[cmd_len + 1];
-
- copy_from_user ( file, file_u, 0, file_len + 1 );
- copy_from_user ( cmd, cmd_u, 0, cmd_len + 1 );
+ const char *file = real_to_virt ( ix86->segs.ds,
+ ix86->regs.si );
+ char *cmd = real_to_virt ( ix86->segs.es,
+ ix86->regs.bx );
DBG ( "COMBOOT: run kernel %s %s\n", file, cmd );
comboot_fetch_kernel ( file, cmd );
@@ -595,9 +581,9 @@ static __asmcall __used void int22 ( struct i386_all_regs *ix86 ) {
shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx );
/* Copy initial register values to .text16 */
- memcpy_user ( real_to_user ( rm_cs, (unsigned) __from_text16 ( &comboot_initial_regs ) ), 0,
- real_to_user ( ix86->segs.ds, ix86->regs.si ), 0,
- sizeof(syslinux_rm_regs) );
+ memcpy ( real_to_virt ( rm_cs, (unsigned) __from_text16 ( &comboot_initial_regs ) ),
+ real_to_virt ( ix86->segs.ds, ix86->regs.si ),
+ sizeof(syslinux_rm_regs) );
/* Load initial register values */
__asm__ __volatile__ (
@@ -702,4 +688,4 @@ void unhook_comboot_interrupts ( ) {
}
/* Avoid dragging in serial console support unconditionally */
-struct uart serial_console __attribute__ (( weak ));
+struct uart *serial_console __attribute__ (( weak ));
diff --git a/src/arch/x86/interface/vmware/guestinfo.c b/src/arch/x86/interface/vmware/guestinfo.c
index 4134515c1..c181d96e9 100644
--- a/src/arch/x86/interface/vmware/guestinfo.c
+++ b/src/arch/x86/interface/vmware/guestinfo.c
@@ -200,6 +200,7 @@ static void guestinfo_init ( void ) {
/** GuestInfo settings initialiser */
struct init_fn guestinfo_init_fn __init_fn ( INIT_NORMAL ) = {
+ .name = "guestinfo",
.initialise = guestinfo_init,
};
diff --git a/src/arch/x86/interface/vmware/vmconsole.c b/src/arch/x86/interface/vmware/vmconsole.c
index f7df4f75b..3b892c837 100644
--- a/src/arch/x86/interface/vmware/vmconsole.c
+++ b/src/arch/x86/interface/vmware/vmconsole.c
@@ -134,5 +134,6 @@ static void vmconsole_init ( void ) {
* VMware logfile console initialisation function
*/
struct init_fn vmconsole_init_fn __init_fn ( INIT_CONSOLE ) = {
+ .name = "vmconsole",
.initialise = vmconsole_init,
};
diff --git a/src/arch/x86/prefix/lkrnprefix.S b/src/arch/x86/prefix/lkrnprefix.S
index c8a04c9d7..19d30141b 100644
--- a/src/arch/x86/prefix/lkrnprefix.S
+++ b/src/arch/x86/prefix/lkrnprefix.S
@@ -104,6 +104,7 @@ hardware_subarch:
hardware_subarch_data:
.byte 0, 0, 0, 0, 0, 0, 0, 0
+ .section ".prefix.data", "aw", @progbits
version_string:
.asciz VERSION
@@ -113,6 +114,7 @@ version_string:
*
*/
+ .section ".prefix", "ax", @progbits
setup:
/* Fix up code segment */
pushw %ds
diff --git a/src/arch/x86/prefix/pxeprefix.S b/src/arch/x86/prefix/pxeprefix.S
index 5181ef618..067af99fa 100644
--- a/src/arch/x86/prefix/pxeprefix.S
+++ b/src/arch/x86/prefix/pxeprefix.S
@@ -1,6 +1,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PXENV_UNDI_SHUTDOWN 0x0005
+#define PXENV_UNDI_GET_INFORMATION 0x000c
#define PXENV_UNDI_GET_NIC_TYPE 0x0012
#define PXENV_UNDI_GET_IFACE_INFO 0x0013
#define PXENV_STOP_UNDI 0x0015
@@ -325,18 +326,37 @@ print_structure_information:
*****************************************************************************
*/
get_physical_device:
+ /* Allow for devices that fail to set the physical device type */
+ movb $0xeb, %al
+ movb %al, ( pxe_parameter_structure + 0x02 )
/* Issue PXENV_UNDI_GET_NIC_TYPE */
movw $PXENV_UNDI_GET_NIC_TYPE, %bx
call pxe_call
jnc 1f
call print_pxe_error
+ movw $10f, %si
+ call print_message
jmp no_physical_device
1: /* Determine physical device type */
+ movw $10f, %si
+ call print_message
movb ( pxe_parameter_structure + 0x02 ), %al
cmpb $2, %al
je pci_physical_device
+ cmpb $0xeb, %al
+ je probably_pci_physical_device
jmp no_physical_device
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " UNDI device is "
+ .previous
+probably_pci_physical_device:
+ /* Device did not write the type byte: assume PCI */
+ movw $10f, %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz "probably "
+ .previous
pci_physical_device:
/* Record PCI bus:dev.fn and vendor/device IDs */
movl ( pxe_parameter_structure + 0x03 ), %eax
@@ -346,9 +366,17 @@ pci_physical_device:
movw $10f, %si
call print_message
call print_pci_busdevfn
+ movb $( ' ' ), %al
+ call print_character
+ movw pci_vendor, %ax
+ call print_hex_word
+ movb $( ':' ), %al
+ call print_character
+ movw pci_device, %ax
+ call print_hex_word
jmp 99f
.section ".prefix.data", "aw", @progbits
-10: .asciz " UNDI device is PCI "
+10: .asciz "PCI "
.previous
no_physical_device:
@@ -356,12 +384,39 @@ no_physical_device:
movw $10f, %si
call print_message
.section ".prefix.data", "aw", @progbits
-10: .asciz " Unable to determine UNDI physical device"
+10: .asciz "unknown"
.previous
99:
/*****************************************************************************
+ * Get IRQ number
+ *****************************************************************************
+ */
+get_irq:
+ /* Issue PXENV_UNDI_GET_INFORMATION */
+ movw $PXENV_UNDI_GET_INFORMATION, %bx
+ call pxe_call
+ jnc 1f
+ call print_pxe_error
+ jmp 99f
+1: /* Check for a valid IRQ number */
+ movw ( pxe_parameter_structure + 0x04 ), %ax
+ testw %ax, %ax
+ jz 99f
+ cmpw $15, %ax
+ ja 99f
+ /* Store IRQ number */
+ movw %ax, undi_irq
+ movw $10f, %si
+ call print_message
+ call print_word
+ .section ".prefix.data", "aw", @progbits
+10: .asciz ", IRQ "
+ .previous
+99:
+
+/*****************************************************************************
* Determine interface type
*****************************************************************************
*/
@@ -452,6 +507,30 @@ pxe_cmdline:
.previous
/*****************************************************************************
+ * Ensure NIC interrupt is disabled
+ *****************************************************************************
+ */
+disable_irq:
+ /* Check for a recorded IRQ number */
+ movw undi_irq, %cx
+ testw %cx, %cx
+ jz 99f
+ /* Calculate IMR */
+ movw %cx, %dx
+ shlw $4, %dx
+ andb $0x80, %dl
+ orb $0x21, %dl
+ /* Calculate mask value */
+ movb $0x01, %bl
+ andb $0x07, %cl
+ shlb %cl, %bl
+ /* Mask interrupt */
+ inb %dx, %al
+ orb %bl, %al
+ outb %al, %dx
+99:
+
+/*****************************************************************************
* Leave NIC in a safe state
*****************************************************************************
*/
@@ -740,6 +819,8 @@ undi_data_segoff:
undi_data_size: .word 0
undi_data_segment: .word 0
+undi_irq: .word 0
+
pxe_hacks: .word 0
/* The following fields are part of a struct undi_device */
diff --git a/src/arch/x86/prefix/unlzma.S b/src/arch/x86/prefix/unlzma.S
index e4d1e190d..6ab3222e2 100644
--- a/src/arch/x86/prefix/unlzma.S
+++ b/src/arch/x86/prefix/unlzma.S
@@ -45,7 +45,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
.section ".note.GNU-stack", "", @progbits
.code32
- .arch i486
+ .arch i386
.section ".prefix.lib", "ax", @progbits
#ifdef CODE16
@@ -962,7 +962,9 @@ decompress:
ADDR32 lodsb /* discard initial byte */
print_hex_byte %al
ADDR32 lodsl
- bswapl %eax
+ xchgb %al, %ah
+ roll $16, %eax
+ xchgb %al, %ah
print_hex_dword %eax
print_character $('\n')
movl %eax, rc_code(%ebp)
diff --git a/src/arch/x86/scripts/pcbios.lds b/src/arch/x86/scripts/pcbios.lds
index e208b174b..f8c137283 100644
--- a/src/arch/x86/scripts/pcbios.lds
+++ b/src/arch/x86/scripts/pcbios.lds
@@ -130,8 +130,12 @@ SECTIONS {
. += 1; /* Prevent NULL being valid */
*(.text)
*(.text.*)
+ *(.srodata)
+ *(.srodata.*)
*(.rodata)
*(.rodata.*)
+ *(.sdata)
+ *(.sdata.*)
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
@@ -139,6 +143,8 @@ SECTIONS {
KEEP(*(.provided.*))
_mtextdata = .;
} .bss.textdata (NOLOAD) : AT ( _bss_textdata_lma ) {
+ *(.sbss)
+ *(.sbss.*)
*(.bss)
*(.bss.*)
*(COMMON)
diff --git a/src/arch/x86/transitions/librm_mgmt.c b/src/arch/x86/transitions/librm_mgmt.c
index b3820589c..89feec96a 100644
--- a/src/arch/x86/transitions/librm_mgmt.c
+++ b/src/arch/x86/transitions/librm_mgmt.c
@@ -58,35 +58,36 @@ static struct profiler timer_irq_profiler __profiler = { .name = "irq.timer" };
static struct profiler other_irq_profiler __profiler = { .name = "irq.other" };
/**
- * Allocate space on the real-mode stack and copy data there from a
- * user buffer
+ * Allocate space on the real-mode stack and copy data there
*
- * @v data User buffer
+ * @v data Stack data
* @v size Size of stack data
* @ret sp New value of real-mode stack pointer
*/
-uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) {
- userptr_t rm_stack;
+uint16_t copy_to_rm_stack ( const void *data, size_t size ) {
+ void *rm_stack;
+
rm_sp -= size;
- rm_stack = real_to_user ( rm_ss, rm_sp );
- memcpy_user ( rm_stack, 0, data, 0, size );
+ rm_stack = real_to_virt ( rm_ss, rm_sp );
+ memcpy ( rm_stack, data, size );
return rm_sp;
-};
+}
/**
- * Deallocate space on the real-mode stack, optionally copying back
- * data to a user buffer.
+ * Deallocate space on the real-mode stack, optionally copying back data
*
- * @v data User buffer
+ * @v data Stack data buffer, or NULL
* @v size Size of stack data
*/
-void remove_user_from_rm_stack ( userptr_t data, size_t size ) {
+void remove_from_rm_stack ( void *data, size_t size ) {
+ const void *rm_stack;
+
if ( data ) {
- userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );
- memcpy_user ( rm_stack, 0, data, 0, size );
+ rm_stack = real_to_virt ( rm_ss, rm_sp );
+ memcpy ( data, rm_stack, size );
}
rm_sp += size;
-};
+}
/**
* Set interrupt vector
@@ -302,17 +303,14 @@ static void * ioremap_pages ( unsigned long bus_addr, size_t len ) {
/* Calculate number of pages required */
count = ( ( offset + len + IO_PAGE_SIZE - 1 ) / IO_PAGE_SIZE );
assert ( count != 0 );
- assert ( count < ( sizeof ( io_pages.page ) /
- sizeof ( io_pages.page[0] ) ) );
+ assert ( count <= IO_PAGE_COUNT );
/* Round up number of pages to a power of two */
- stride = ( 1 << ( fls ( count ) - 1 ) );
+ stride = ( 1 << fls ( count - 1 ) );
assert ( count <= stride );
/* Allocate pages */
- for ( first = 0 ; first < ( sizeof ( io_pages.page ) /
- sizeof ( io_pages.page[0] ) ) ;
- first += stride ) {
+ for ( first = 0 ; first < IO_PAGE_COUNT ; first += stride ) {
/* Calculate I/O address */
io_addr = ( IO_BASE + ( first * IO_PAGE_SIZE ) + offset );
@@ -365,6 +363,10 @@ static void iounmap_pages ( volatile const void *io_addr ) {
/* Calculate first page table entry */
first = ( ( io_addr - IO_BASE ) / IO_PAGE_SIZE );
+ /* Ignore unmappings outside of the I/O range */
+ if ( first >= IO_PAGE_COUNT )
+ return;
+
/* Clear page table entries */
for ( i = first ; ; i++ ) {
@@ -425,19 +427,9 @@ void setup_sipi ( unsigned int vector, uint32_t handler,
memcpy ( &sipi_regs, regs, sizeof ( sipi_regs ) );
/* Copy real-mode handler */
- copy_to_real ( ( vector << 8 ), 0, sipi, ( ( size_t ) sipi_len ) );
+ copy_to_real ( ( vector << 8 ), 0, sipi, sipi_len );
}
-PROVIDE_UACCESS_INLINE ( librm, phys_to_user );
-PROVIDE_UACCESS_INLINE ( librm, user_to_phys );
-PROVIDE_UACCESS_INLINE ( librm, virt_to_user );
-PROVIDE_UACCESS_INLINE ( librm, user_to_virt );
-PROVIDE_UACCESS_INLINE ( librm, userptr_add );
-PROVIDE_UACCESS_INLINE ( librm, memcpy_user );
-PROVIDE_UACCESS_INLINE ( librm, memmove_user );
-PROVIDE_UACCESS_INLINE ( librm, memset_user );
-PROVIDE_UACCESS_INLINE ( librm, strlen_user );
-PROVIDE_UACCESS_INLINE ( librm, memchr_user );
PROVIDE_IOMAP_INLINE ( pages, io_to_bus );
PROVIDE_IOMAP ( pages, ioremap, ioremap_pages );
PROVIDE_IOMAP ( pages, iounmap, iounmap_pages );