summaryrefslogtreecommitdiffstats
path: root/src/arch/x86/interface
diff options
context:
space:
mode:
authorSimon Rettberg2026-01-28 12:53:53 +0100
committerSimon Rettberg2026-01-28 12:53:53 +0100
commit8e82785c584dc13e20f9229decb95bd17bbe9cd1 (patch)
treea8b359e59196be5b2e3862bed189107f4bc9975f /src/arch/x86/interface
parentMerge branch 'master' into openslx (diff)
parent[prefix] Make unlzma.S compatible with 386 class CPUs (diff)
downloadipxe-openslx.tar.gz
ipxe-openslx.tar.xz
ipxe-openslx.zip
Merge branch 'master' into openslxopenslx
Diffstat (limited to 'src/arch/x86/interface')
-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
29 files changed, 366 insertions, 834 deletions
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,
};