summaryrefslogtreecommitdiff
path: root/roms/ipxe/src/arch/x86
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-09-05 20:35:53 +0900
committerChanho Park <chanho61.park@samsung.com>2014-09-05 20:35:53 +0900
commit16b1353a36171ae06d63fd309f4772dbfb1da113 (patch)
treecf6c297ee81aba0d9b47f23d78a889667e7bce48 /roms/ipxe/src/arch/x86
parenta15119db2ff5c2fdfdeb913b297bf8aa3399132e (diff)
downloadqemu-16b1353a36171ae06d63fd309f4772dbfb1da113.tar.gz
qemu-16b1353a36171ae06d63fd309f4772dbfb1da113.tar.bz2
qemu-16b1353a36171ae06d63fd309f4772dbfb1da113.zip
Imported Upstream version 2.1.0upstream/2.1.0
Diffstat (limited to 'roms/ipxe/src/arch/x86')
-rw-r--r--roms/ipxe/src/arch/x86/Makefile.efi10
-rw-r--r--roms/ipxe/src/arch/x86/core/cpuid.c20
-rw-r--r--roms/ipxe/src/arch/x86/core/cpuid_settings.c274
-rw-r--r--roms/ipxe/src/arch/x86/core/debugcon.c2
-rw-r--r--roms/ipxe/src/arch/x86/core/linux/linux_api.c4
-rw-r--r--roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c3
-rw-r--r--roms/ipxe/src/arch/x86/include/bits/errfile.h4
-rw-r--r--roms/ipxe/src/arch/x86/include/ipxe/cpuid.h25
-rw-r--r--roms/ipxe/src/arch/x86/include/valgrind/memcheck.h2
-rw-r--r--roms/ipxe/src/arch/x86/include/valgrind/valgrind.h2
-rw-r--r--roms/ipxe/src/arch/x86/prefix/efidrvprefix.c6
-rw-r--r--roms/ipxe/src/arch/x86/prefix/efiprefix.c14
-rw-r--r--roms/ipxe/src/arch/x86/scripts/efi.lds2
13 files changed, 342 insertions, 26 deletions
diff --git a/roms/ipxe/src/arch/x86/Makefile.efi b/roms/ipxe/src/arch/x86/Makefile.efi
index bef8d59d8..3e3fbe3ca 100644
--- a/roms/ipxe/src/arch/x86/Makefile.efi
+++ b/roms/ipxe/src/arch/x86/Makefile.efi
@@ -12,6 +12,8 @@ LDFLAGS += -q -S
#
NON_AUTO_MEDIA += efi
NON_AUTO_MEDIA += efidrv
+NON_AUTO_MEDIA += drv.efi
+NON_AUTO_MEDIA += efirom
# Rules for building EFI files
#
@@ -23,6 +25,14 @@ $(BIN)/%.efidrv : $(BIN)/%.efidrv.tmp $(ELF2EFI)
$(QM)$(ECHO) " [FINISH] $@"
$(Q)$(ELF2EFI) --subsystem=11 $< $@
+$(BIN)/%.drv.efi : $(BIN)/%.efidrv
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)$(CP) $< $@
+
$(BIN)/%.efirom : $(BIN)/%.efidrv $(EFIROM)
$(QM)$(ECHO) " [FINISH] $@"
$(Q)$(EFIROM) -v $(TGT_PCI_VENDOR) -d $(TGT_PCI_DEVICE) $< $@
+
+$(BIN)/efidrv.cab : $(BIN)/alldrv.efis # $(ALL_drv.efi) is not yet defined
+ $(QM)$(ECHO) " [CAB] $@"
+ $(Q)$(LCAB) -n -q $(ALL_drv.efi) $@
diff --git a/roms/ipxe/src/arch/x86/core/cpuid.c b/roms/ipxe/src/arch/x86/core/cpuid.c
index 96f794095..5908f4419 100644
--- a/roms/ipxe/src/arch/x86/core/cpuid.c
+++ b/roms/ipxe/src/arch/x86/core/cpuid.c
@@ -33,7 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
*
* @ret is_supported CPUID instruction is supported
*/
-static int cpuid_is_supported ( void ) {
+int cpuid_is_supported ( void ) {
unsigned long original;
unsigned long inverted;
@@ -53,24 +53,6 @@ static int cpuid_is_supported ( void ) {
}
/**
- * Issue CPUID instruction
- *
- * @v operation CPUID operation
- * @v eax Output via %eax
- * @v ebx Output via %ebx
- * @v ecx Output via %ecx
- * @v edx Output via %edx
- */
-static inline __attribute__ (( always_inline )) void
-cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
- uint32_t *edx ) {
-
- __asm__ ( "cpuid"
- : "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
- : "0" ( operation ) );
-}
-
-/**
* Get Intel-defined x86 CPU features
*
* @v features x86 CPU features to fill in
diff --git a/roms/ipxe/src/arch/x86/core/cpuid_settings.c b/roms/ipxe/src/arch/x86/core/cpuid_settings.c
new file mode 100644
index 000000000..42dea9336
--- /dev/null
+++ b/roms/ipxe/src/arch/x86/core/cpuid_settings.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/init.h>
+#include <ipxe/settings.h>
+#include <ipxe/cpuid.h>
+
+/** @file
+ *
+ * x86 CPUID settings
+ *
+ * CPUID settings are numerically encoded as:
+ *
+ * Bit 31 Extended function
+ * Bits 30-28 Unused
+ * Bits 27-24 Number of consecutive functions to call, minus one
+ * Bit 23 Return result as little-endian (used for strings)
+ * Bits 22-18 Unused
+ * Bits 17-16 Number of registers in register array, minus one
+ * Bits 15-8 Array of register indices. First entry in array is in
+ * bits 9-8. Indices are 0-%eax, 1-%ebx, 2-%ecx, 3-%edx.
+ * Bits 7-0 Starting function number (excluding "extended" bit)
+ *
+ * This encoding scheme is designed to allow the common case of
+ * extracting a single register from a single function to be encoded
+ * using "cpuid/<register>.<function>", e.g. "cpuid/2.0x80000001" to
+ * retrieve the value of %ecx from calling CPUID with %eax=0x80000001.
+ */
+
+/** CPUID setting tag register indices */
+enum cpuid_registers {
+ CPUID_EAX = 0,
+ CPUID_EBX = 1,
+ CPUID_ECX = 2,
+ CPUID_EDX = 3,
+};
+
+/**
+ * Construct CPUID setting tag
+ *
+ * @v function Starting function number
+ * @v num_functions Number of consecutive functions
+ * @v little_endian Return result as little-endian
+ * @v num_registers Number of registers in register array
+ * @v register1 First register in register array (or zero, if empty)
+ * @v register2 Second register in register array (or zero, if empty)
+ * @v register3 Third register in register array (or zero, if empty)
+ * @v register4 Fourth register in register array (or zero, if empty)
+ * @ret tag Setting tag
+ */
+#define CPUID_TAG( function, num_functions, little_endian, num_registers, \
+ register1, register2, register3, register4 ) \
+ ( (function) | ( ( (num_functions) - 1 ) << 24 ) | \
+ ( (little_endian) << 23 ) | ( ( (num_registers) - 1) << 16 ) | \
+ ( (register1) << 8 ) | ( (register2) << 10 ) | \
+ ( (register3) << 12 ) | ( (register4) << 14 ) )
+
+/**
+ * Extract endianness from CPUID setting tag
+ *
+ * @v tag Setting tag
+ * @ret little_endian Result should be returned as little-endian
+ */
+#define CPUID_LITTLE_ENDIAN( tag ) ( (tag) & 0x00800000UL )
+
+/**
+ * Extract starting function number from CPUID setting tag
+ *
+ * @v tag Setting tag
+ * @ret function Starting function number
+ */
+#define CPUID_FUNCTION( tag ) ( (tag) & 0x800000ffUL )
+
+/**
+ * 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 ) & 0xf ) + 1 )
+
+/**
+ * Extract register array from CPUID setting tag
+ *
+ * @v tag Setting tag
+ * @ret registers Register array
+ */
+#define CPUID_REGISTERS( tag ) ( ( (tag) >> 8 ) & 0xff )
+
+/**
+ * Extract number of registers from CPUID setting tag
+ *
+ * @v tag Setting tag
+ * @ret num_registers Number of registers within register array
+ */
+#define CPUID_NUM_REGISTERS( tag ) ( ( ( (tag) >> 16 ) & 0x3 ) + 1 )
+
+/** CPUID settings scope */
+static const struct settings_scope cpuid_settings_scope;
+
+/**
+ * Check applicability of CPUID setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+static int cpuid_settings_applies ( struct settings *settings __unused,
+ const struct setting *setting ) {
+
+ return ( setting->scope == &cpuid_settings_scope );
+}
+
+/**
+ * Fetch value of CPUID setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int cpuid_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ uint32_t function;
+ uint32_t max_function;
+ uint32_t num_functions;
+ uint32_t registers;
+ uint32_t num_registers;
+ uint32_t buf[4];
+ uint32_t output;
+ uint32_t discard_b;
+ uint32_t discard_c;
+ uint32_t discard_d;
+ size_t frag_len;
+ size_t result_len = 0;
+
+ /* Fail unless CPUID is supported */
+ if ( ! cpuid_is_supported() ) {
+ DBGC ( settings, "CPUID not supported\n" );
+ return -ENOTSUP;
+ }
+
+ /* Find highest supported function number within this set */
+ function = CPUID_FUNCTION ( setting->tag );
+ cpuid ( function & CPUID_EXTENDED, &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
+ * does not support them).
+ */
+ if ( ( max_function & CPUID_AMD_CHECK_MASK ) !=
+ ( function & CPUID_AMD_CHECK_MASK ) ) {
+ DBGC ( settings, "CPUID invalid maximum function\n" );
+ return -ENOTSUP;
+ }
+
+ /* Call each function in turn */
+ num_functions = CPUID_NUM_FUNCTIONS ( setting->tag );
+ for ( ; num_functions-- ; function++ ) {
+
+ /* Fail if this function is not supported */
+ if ( function > max_function ) {
+ DBGC ( settings, "CPUID function %#08x not supported\n",
+ function );
+ return -ENOTSUP;
+ }
+
+ /* Issue CPUID */
+ cpuid ( function, &buf[CPUID_EAX], &buf[CPUID_EBX],
+ &buf[CPUID_ECX], &buf[CPUID_EDX] );
+ DBGC ( settings, "CPUID %#08x => %#08x:%#08x:%#08x:%#08x\n",
+ function, buf[0], buf[1], buf[2], buf[3] );
+
+ /* Copy results to buffer */
+ registers = CPUID_REGISTERS ( setting->tag );
+ num_registers = CPUID_NUM_REGISTERS ( setting->tag );
+ for ( ; num_registers-- ; registers >>= 2 ) {
+ output = buf[ registers & 0x3 ];
+ if ( ! CPUID_LITTLE_ENDIAN ( setting->tag ) )
+ output = cpu_to_be32 ( output );
+ frag_len = sizeof ( output );
+ if ( frag_len > len )
+ frag_len = len;
+ memcpy ( data, &output, frag_len );
+ data += frag_len;
+ len -= frag_len;
+ result_len += sizeof ( output );
+ }
+ }
+
+ /* Set type if not already specified */
+ if ( ! setting->type )
+ setting->type = &setting_type_hexraw;
+
+ return result_len;
+}
+
+/** CPUID settings operations */
+static struct settings_operations cpuid_settings_operations = {
+ .applies = cpuid_settings_applies,
+ .fetch = cpuid_settings_fetch,
+};
+
+/** CPUID settings */
+static struct settings cpuid_settings = {
+ .refcnt = NULL,
+ .siblings = LIST_HEAD_INIT ( cpuid_settings.siblings ),
+ .children = LIST_HEAD_INIT ( cpuid_settings.children ),
+ .op = &cpuid_settings_operations,
+ .default_scope = &cpuid_settings_scope,
+};
+
+/** Initialise CPUID settings */
+static void cpuid_settings_init ( void ) {
+ int rc;
+
+ if ( ( rc = register_settings ( &cpuid_settings, NULL,
+ "cpuid" ) ) != 0 ) {
+ DBG ( "CPUID could not register settings: %s\n",
+ strerror ( rc ) );
+ return;
+ }
+}
+
+/** CPUID settings initialiser */
+struct init_fn cpuid_settings_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = cpuid_settings_init,
+};
+
+/** CPU vendor setting */
+const struct setting cpuvendor_setting __setting ( SETTING_HOST_EXTRA,
+ cpuvendor ) = {
+ .name = "cpuvendor",
+ .description = "CPU vendor",
+ .tag = CPUID_TAG ( CPUID_VENDOR_ID, 1, 1, 3,
+ CPUID_EBX, CPUID_EDX, CPUID_ECX, 0 ),
+ .type = &setting_type_string,
+ .scope = &cpuid_settings_scope,
+};
+
+/** CPU model setting */
+const struct setting cpumodel_setting __setting ( SETTING_HOST_EXTRA,
+ cpumodel ) = {
+ .name = "cpumodel",
+ .description = "CPU model",
+ .tag = CPUID_TAG ( CPUID_MODEL, 3, 1, 4,
+ CPUID_EAX, CPUID_EBX, CPUID_ECX, CPUID_EDX ),
+ .type = &setting_type_string,
+ .scope = &cpuid_settings_scope,
+};
diff --git a/roms/ipxe/src/arch/x86/core/debugcon.c b/roms/ipxe/src/arch/x86/core/debugcon.c
index b89480aa5..263cb4af1 100644
--- a/roms/ipxe/src/arch/x86/core/debugcon.c
+++ b/roms/ipxe/src/arch/x86/core/debugcon.c
@@ -74,7 +74,7 @@ static void debugcon_init ( void ) {
check = inb ( DEBUG_PORT );
if ( check != DEBUG_PORT_CHECK ) {
DBG ( "Debug port not present; disabling console\n" );
- debugcon_console.disabled = 1;
+ debugcon_console.disabled = CONSOLE_DISABLED;
}
}
diff --git a/roms/ipxe/src/arch/x86/core/linux/linux_api.c b/roms/ipxe/src/arch/x86/core/linux/linux_api.c
index c8a09b7d8..0bed9fd57 100644
--- a/roms/ipxe/src/arch/x86/core/linux/linux_api.c
+++ b/roms/ipxe/src/arch/x86/core/linux/linux_api.c
@@ -37,6 +37,10 @@ int linux_close ( int fd ) {
return linux_syscall ( __NR_close, fd );
}
+off_t linux_lseek ( int fd, off_t offset, int whence ) {
+ return linux_syscall ( __NR_lseek, fd, offset, whence );
+}
+
__kernel_ssize_t linux_read ( int fd, void *buf, __kernel_size_t count ) {
return linux_syscall ( __NR_read, fd, buf, count );
}
diff --git a/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c b/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c
index 981143308..c4e35d179 100644
--- a/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c
+++ b/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c
@@ -54,8 +54,7 @@ static struct option_descriptor cpuid_opts[] = {
/** "cpuid" command descriptor */
static struct command_descriptor cpuid_cmd =
- COMMAND_DESC ( struct cpuid_options, cpuid_opts, 1, 1,
- "[--ext] [--ecx] <bit>" );
+ COMMAND_DESC ( struct cpuid_options, cpuid_opts, 1, 1, "<bit>" );
/**
* The "cpuid" command
diff --git a/roms/ipxe/src/arch/x86/include/bits/errfile.h b/roms/ipxe/src/arch/x86/include/bits/errfile.h
index 7b9f3702e..acf8c3e39 100644
--- a/roms/ipxe/src/arch/x86/include/bits/errfile.h
+++ b/roms/ipxe/src/arch/x86/include/bits/errfile.h
@@ -19,6 +19,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_vmware ( ERRFILE_ARCH | ERRFILE_CORE | 0x00080000 )
#define ERRFILE_guestrpc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00090000 )
#define ERRFILE_guestinfo ( ERRFILE_ARCH | ERRFILE_CORE | 0x000a0000 )
+#define ERRFILE_apm ( ERRFILE_ARCH | ERRFILE_CORE | 0x000b0000 )
+#define ERRFILE_vesafb ( ERRFILE_ARCH | ERRFILE_CORE | 0x000c0000 )
#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
@@ -33,6 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#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_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )
@@ -44,6 +47,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
#define ERRFILE_cpuid_cmd ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 )
+#define ERRFILE_cpuid_settings ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00010000 )
/** @} */
diff --git a/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h b/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h
index 9705137c6..2f78dfca1 100644
--- a/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h
+++ b/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h
@@ -30,6 +30,9 @@ struct x86_features {
/** CPUID support flag */
#define CPUID_FLAG 0x00200000UL
+/** CPUID extended function */
+#define CPUID_EXTENDED 0x80000000UL
+
/** Get vendor ID and largest standard function */
#define CPUID_VENDOR_ID 0x00000000UL
@@ -48,6 +51,28 @@ struct x86_features {
/** Get extended features */
#define CPUID_AMD_FEATURES 0x80000001UL
+/** Get CPU model */
+#define CPUID_MODEL 0x80000002UL
+
+/**
+ * Issue CPUID instruction
+ *
+ * @v operation CPUID operation
+ * @v eax Output via %eax
+ * @v ebx Output via %ebx
+ * @v ecx Output via %ecx
+ * @v edx Output via %edx
+ */
+static inline __attribute__ (( always_inline )) void
+cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
+ uint32_t *edx ) {
+
+ __asm__ ( "cpuid"
+ : "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
+ : "0" ( operation ) );
+}
+
+extern int cpuid_is_supported ( void );
extern void x86_features ( struct x86_features *features );
#endif /* _IPXE_CPUID_H */
diff --git a/roms/ipxe/src/arch/x86/include/valgrind/memcheck.h b/roms/ipxe/src/arch/x86/include/valgrind/memcheck.h
index 46d234324..7d4b56d31 100644
--- a/roms/ipxe/src/arch/x86/include/valgrind/memcheck.h
+++ b/roms/ipxe/src/arch/x86/include/valgrind/memcheck.h
@@ -60,6 +60,8 @@
#ifndef __MEMCHECK_H
#define __MEMCHECK_H
+FILE_LICENCE ( BSD3 );
+
/* This file is for inclusion into client (your!) code.
diff --git a/roms/ipxe/src/arch/x86/include/valgrind/valgrind.h b/roms/ipxe/src/arch/x86/include/valgrind/valgrind.h
index d72754b05..d48bbccae 100644
--- a/roms/ipxe/src/arch/x86/include/valgrind/valgrind.h
+++ b/roms/ipxe/src/arch/x86/include/valgrind/valgrind.h
@@ -73,6 +73,8 @@
#ifndef __VALGRIND_H
#define __VALGRIND_H
+FILE_LICENCE ( BSD3 );
+
/* ------------------------------------------------------------------ */
/* VERSION NUMBER OF VALGRIND */
diff --git a/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c b/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c
index 8a31df56d..280e33535 100644
--- a/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c
+++ b/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c
@@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stdlib.h>
#include <ipxe/init.h>
#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_snp.h>
/**
* EFI entry point
@@ -42,7 +43,8 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
initialise();
startup();
+ /* Release network devices for use via SNP */
+ efi_snp_release();
+
return 0;
}
-
-REQUIRE_OBJECT ( efi_snp );
diff --git a/roms/ipxe/src/arch/x86/prefix/efiprefix.c b/roms/ipxe/src/arch/x86/prefix/efiprefix.c
index bfa94d404..eb8aa738a 100644
--- a/roms/ipxe/src/arch/x86/prefix/efiprefix.c
+++ b/roms/ipxe/src/arch/x86/prefix/efiprefix.c
@@ -20,6 +20,7 @@
FILE_LICENCE ( GPL2_OR_LATER );
#include <stdlib.h>
+#include <errno.h>
#include <ipxe/efi/efi.h>
/**
@@ -32,11 +33,20 @@ FILE_LICENCE ( GPL2_OR_LATER );
EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
EFI_SYSTEM_TABLE *systab ) {
EFI_STATUS efirc;
+ int rc;
/* Initialise EFI environment */
if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
- return efirc;
+ goto err_init;
/* Call to main() */
- return RC_TO_EFIRC ( main () );
+ if ( ( rc = main() ) != 0 ) {
+ efirc = EFIRC ( rc );
+ goto err_main;
+ }
+
+ err_main:
+ efi_loaded_image->Unload ( image_handle );
+ err_init:
+ return efirc;
}
diff --git a/roms/ipxe/src/arch/x86/scripts/efi.lds b/roms/ipxe/src/arch/x86/scripts/efi.lds
index 1a16c29bd..f1049f24b 100644
--- a/roms/ipxe/src/arch/x86/scripts/efi.lds
+++ b/roms/ipxe/src/arch/x86/scripts/efi.lds
@@ -55,6 +55,8 @@ SECTIONS {
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
+ KEEP(*(.provided))
+ KEEP(*(.provided.*))
_edata = .;
}