diff options
author | RajithaY <rajithax.yerrumsetty@intel.com> | 2017-04-25 03:31:15 -0700 |
---|---|---|
committer | Rajitha Yerrumchetty <rajithax.yerrumsetty@intel.com> | 2017-05-22 06:48:08 +0000 |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/roms/ipxe/src/interface/efi | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/roms/ipxe/src/interface/efi')
23 files changed, 0 insertions, 7519 deletions
diff --git a/qemu/roms/ipxe/src/interface/efi/efi_autoboot.c b/qemu/roms/ipxe/src/interface/efi/efi_autoboot.c deleted file mode 100644 index a9e807e23..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_autoboot.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2014 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/efi/efi.h> -#include <ipxe/efi/efi_autoboot.h> -#include <ipxe/efi/Protocol/SimpleNetwork.h> -#include <usr/autoboot.h> - -/** @file - * - * EFI autoboot device - * - */ - -/** - * Identify autoboot device - * - */ -void efi_set_autoboot ( void ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - union { - EFI_SIMPLE_NETWORK_PROTOCOL *snp; - void *interface; - } snp; - EFI_SIMPLE_NETWORK_MODE *mode; - EFI_STATUS efirc; - - /* Look for an SNP instance on the image's device handle */ - if ( ( efirc = bs->OpenProtocol ( efi_loaded_image->DeviceHandle, - &efi_simple_network_protocol_guid, - &snp.interface, efi_image_handle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - DBGC ( efi_loaded_image, "EFI found no autoboot device\n" ); - return; - } - - /* Record autoboot device */ - mode = snp.snp->Mode; - set_autoboot_ll_addr ( &mode->CurrentAddress, mode->HwAddressSize ); - DBGC ( efi_loaded_image, "EFI found autoboot link-layer address:\n" ); - DBGC_HDA ( efi_loaded_image, 0, &mode->CurrentAddress, - mode->HwAddressSize ); - - /* Close protocol */ - bs->CloseProtocol ( efi_loaded_image->DeviceHandle, - &efi_simple_network_protocol_guid, - efi_image_handle, NULL ); -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_bofm.c b/qemu/roms/ipxe/src/interface/efi/efi_bofm.c deleted file mode 100644 index ea0e15f7f..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_bofm.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2011 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 <errno.h> -#include <ipxe/bofm.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_pci.h> -#include <ipxe/efi/efi_driver.h> - -/** @file - * - * IBM BladeCenter Open Fabric Manager (BOFM) EFI interface - * - */ - -/*************************************************************************** - * - * EFI BOFM definitions - * - *************************************************************************** - * - * Taken from the BOFM UEFI Vendor Specification document - * - */ - -#define IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID \ - { 0x03207ce2, 0xd9c7, 0x11dc, \ - { 0xa9, 0x4d, 0x00, 0x19, 0x7d, 0x89, 0x02, 0x38 } } - -#define IBM_BOFM_DRIVER_CONFIGURATION2_PROTOCOL_GUID \ - { 0xe82a9763, 0x0584, 0x4e41, \ - { 0xbb, 0x39, 0xe0, 0xcd, 0xb8, 0xc1, 0xf0, 0xfc } } - -typedef struct { - UINT8 Id; - UINT8 ResultByte; -} __attribute__ (( packed )) BOFM_EPID_Results_t; - -typedef struct { - UINT8 Version; - UINT8 Level; - UINT16 Length; - UINT8 Checksum; - UINT8 Profile[32]; - UINT8 GlobalOption0; - UINT8 GlobalOption1; - UINT8 GlobalOption2; - UINT8 GlobalOption3; - UINT32 SequenceStamp; - UINT8 Regions[911]; // For use by BOFM Driver - UINT32 Reserved1; -} __attribute__ (( packed )) BOFM_Parameters_t; - -typedef struct { - UINT32 Reserved1; - UINT8 Version; - UINT8 Level; - UINT8 Checksum; - UINT32 SequenceStamp; - UINT8 SUIDResults; - UINT8 EntryResults[32]; - UINT8 Reserved2; - UINT8 Reserved3; - UINT8 FCTgtResults[2]; - UINT8 SASTgtResults[2]; - BOFM_EPID_Results_t EPIDResults[2]; - UINT8 Results4[10]; -} __attribute__ (( packed )) BOFM_Results_t; - -typedef struct { - UINT32 Signature; - UINT32 SubSignature; - BOFM_Parameters_t Parameters; - BOFM_Results_t Results; -} __attribute__ (( packed )) BOFM_DataStructure_t; - -#define IBM_BOFM_TABLE BOFM_DataStructure_t - -typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL - IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL; - -typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 - IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2; - -typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT ) ( - IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This, - EFI_HANDLE ControllerHandle, - UINT8 SupporttedOptions, - UINT8 iSCSI_Parameter_Version, - UINT8 BOFM_Parameter_Version -); - -typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS ) ( - IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This, - EFI_HANDLE ControllerHandle, - BOOLEAN ResetRequired, - UINT8 BOFMReturnCode -); - -typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS2 ) ( - IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *This, - EFI_HANDLE ControllerHandle, - BOOLEAN ResetRequired, - UINT8 BOFMReturnCode -); - -struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL { - IBM_BOFM_TABLE BofmTable; - IBM_BOFM_DRIVER_CONFIGURATION_STATUS SetStatus; - IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport; -}; - -struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 { - UINT32 Signature; - UINT32 Reserved1; - UINT64 Reserved2; - IBM_BOFM_DRIVER_CONFIGURATION_STATUS2 SetStatus; - IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport; - IBM_BOFM_TABLE BofmTable; -}; - -/*************************************************************************** - * - * EFI BOFM interface - * - *************************************************************************** - */ - -/** BOFM1 protocol GUID */ -static EFI_GUID bofm1_protocol_guid = - IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID; - -/** BOFM2 protocol GUID */ -static EFI_GUID bofm2_protocol_guid = - IBM_BOFM_DRIVER_CONFIGURATION2_PROTOCOL_GUID; - -/** - * Check if device is supported - * - * @v device EFI device handle - * @ret rc Return status code - */ -static int efi_bofm_supported ( EFI_HANDLE device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct pci_device pci; - union { - IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1; - void *interface; - } bofm1; - EFI_STATUS efirc; - int rc; - - /* Get PCI device information */ - if ( ( rc = efipci_info ( device, &pci ) ) != 0 ) - return rc; - - /* Look for a BOFM driver */ - if ( ( rc = bofm_find_driver ( &pci ) ) != 0 ) { - DBGCP ( device, "EFIBOFM %p %s has no driver\n", - device, efi_handle_name ( device ) ); - return rc; - } - - /* Locate BOFM protocol */ - if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, - &bofm1.interface ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n", - device, efi_handle_name ( device ) ); - return rc; - } - - /* Register support for this device */ - if ( ( efirc = bofm1.bofm1->RegisterSupport ( bofm1.bofm1, device, - 0x04 /* Can change MAC */, - 0x00 /* No iSCSI */, - 0x02 /* Version */ ))!=0){ - rc = -EEFI ( efirc ); - DBGC ( device, "EFIBOFM %p %s could not register support: %s\n", - device, efi_handle_name ( device ), strerror ( rc ) ); - return rc; - } - - DBGC ( device, "EFIBOFM %p %s has driver \"%s\"\n", - device, efi_handle_name ( device ), pci.id->name ); - return 0; -} - -/** - * Attach driver to device - * - * @v efidev EFI device - * @ret rc Return status code - */ -static int efi_bofm_start ( struct efi_device *efidev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE device = efidev->device; - union { - IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1; - void *interface; - } bofm1; - union { - IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *bofm2; - void *interface; - } bofm2; - struct pci_device pci; - IBM_BOFM_TABLE *bofmtab; - IBM_BOFM_TABLE *bofmtab2; - int bofmrc; - EFI_STATUS efirc; - int rc; - - /* Open PCI device, if possible */ - if ( ( rc = efipci_open ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL, - &pci ) ) != 0 ) - goto err_open; - - /* Locate BOFM protocol */ - if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, - &bofm1.interface ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n", - device, efi_handle_name ( device ) ); - goto err_locate_bofm; - } - bofmtab = &bofm1.bofm1->BofmTable; - DBGC ( device, "EFIBOFM %p %s found version 1 BOFM table at %p+%04x\n", - device, efi_handle_name ( device ), bofmtab, - bofmtab->Parameters.Length ); - - /* Locate BOFM2 protocol, if available */ - if ( ( efirc = bs->LocateProtocol ( &bofm2_protocol_guid, NULL, - &bofm2.interface ) ) == 0 ) { - bofmtab2 = &bofm2.bofm2->BofmTable; - DBGC ( device, "EFIBOFM %p %s found version 2 BOFM table at " - "%p+%04x\n", device, efi_handle_name ( device ), - bofmtab2, bofmtab2->Parameters.Length ); - assert ( bofm2.bofm2->RegisterSupport == - bofm1.bofm1->RegisterSupport ); - } else { - DBGC ( device, "EFIBOFM %p %s cannot find BOFM2 protocol\n", - device, efi_handle_name ( device ) ); - /* Not a fatal error; may be a BOFM1-only system */ - bofmtab2 = NULL; - } - - /* Process BOFM table */ - DBGC2 ( device, "EFIBOFM %p %s version 1 before processing:\n", - device, efi_handle_name ( device ) ); - DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length ); - if ( bofmtab2 ) { - DBGC2 ( device, "EFIBOFM %p %s version 2 before processing:\n", - device, efi_handle_name ( device ) ); - DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length ); - } - bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ), &pci ); - DBGC ( device, "EFIBOFM %p %s status %08x\n", - device, efi_handle_name ( device ), bofmrc ); - DBGC2 ( device, "EFIBOFM %p %s version 1 after processing:\n", - device, efi_handle_name ( device ) ); - DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length ); - if ( bofmtab2 ) { - DBGC2 ( device, "EFIBOFM %p %s version 2 after processing:\n", - device, efi_handle_name ( device ) ); - DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length ); - } - - /* Return BOFM status */ - if ( bofmtab2 ) { - if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device, - FALSE, bofmrc ) ) != 0){ - rc = -EEFI ( efirc ); - DBGC ( device, "EFIBOFM %p %s could not set BOFM2 " - "status: %s\n", device, - efi_handle_name ( device ), strerror ( rc ) ); - goto err_set_status; - } - } else { - if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device, - FALSE, bofmrc ) ) != 0){ - rc = -EEFI ( efirc ); - DBGC ( device, "EFIBOFM %p %s could not set BOFM " - "status: %s\n", device, - efi_handle_name ( device ), strerror ( rc ) ); - goto err_set_status; - } - } - - /* BOFM (ab)uses the "start" method to mean "process and exit" */ - rc = -EAGAIN; - - err_set_status: - err_locate_bofm: - efipci_close ( device ); - err_open: - return rc; -} - -/** - * Detach driver from device - * - * @v device EFI device - */ -static void efi_bofm_stop ( struct efi_device *efidev __unused ) { - - /* Should never happen */ - assert ( 0 ); -} - -/** EFI BOFM driver */ -struct efi_driver efi_bofm_driver __efi_driver ( EFI_DRIVER_EARLY ) = { - .name = "BOFM", - .supported = efi_bofm_supported, - .start = efi_bofm_start, - .stop = efi_bofm_stop, -}; diff --git a/qemu/roms/ipxe/src/interface/efi/efi_console.c b/qemu/roms/ipxe/src/interface/efi/efi_console.c deleted file mode 100644 index 3b30f3097..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_console.c +++ /dev/null @@ -1,360 +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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stddef.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/Protocol/ConsoleControl/ConsoleControl.h> -#include <ipxe/ansiesc.h> -#include <ipxe/console.h> -#include <ipxe/init.h> -#include <config/console.h> - -#define ATTR_BOLD 0x08 - -#define ATTR_FCOL_MASK 0x07 -#define ATTR_FCOL_BLACK 0x00 -#define ATTR_FCOL_BLUE 0x01 -#define ATTR_FCOL_GREEN 0x02 -#define ATTR_FCOL_CYAN 0x03 -#define ATTR_FCOL_RED 0x04 -#define ATTR_FCOL_MAGENTA 0x05 -#define ATTR_FCOL_YELLOW 0x06 -#define ATTR_FCOL_WHITE 0x07 - -#define ATTR_BCOL_MASK 0x70 -#define ATTR_BCOL_BLACK 0x00 -#define ATTR_BCOL_BLUE 0x10 -#define ATTR_BCOL_GREEN 0x20 -#define ATTR_BCOL_CYAN 0x30 -#define ATTR_BCOL_RED 0x40 -#define ATTR_BCOL_MAGENTA 0x50 -#define ATTR_BCOL_YELLOW 0x60 -#define ATTR_BCOL_WHITE 0x70 - -#define ATTR_DEFAULT ATTR_FCOL_WHITE - -/* Set default console usage if applicable */ -#if ! ( defined ( CONSOLE_EFI ) && CONSOLE_EXPLICIT ( CONSOLE_EFI ) ) -#undef CONSOLE_EFI -#define CONSOLE_EFI ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG ) -#endif - -/** Current character attribute */ -static unsigned int efi_attr = ATTR_DEFAULT; - -/** Console control protocol */ -static EFI_CONSOLE_CONTROL_PROTOCOL *conctrl; -EFI_REQUEST_PROTOCOL ( EFI_CONSOLE_CONTROL_PROTOCOL, &conctrl ); - -/** - * Handle ANSI CUP (cursor position) - * - * @v ctx ANSI escape sequence context - * @v count Parameter count - * @v params[0] Row (1 is top) - * @v params[1] Column (1 is left) - */ -static void efi_handle_cup ( struct ansiesc_context *ctx __unused, - unsigned int count __unused, int params[] ) { - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; - int cx = ( params[1] - 1 ); - int cy = ( params[0] - 1 ); - - if ( cx < 0 ) - cx = 0; - if ( cy < 0 ) - cy = 0; - - conout->SetCursorPosition ( conout, cx, cy ); -} - -/** - * Handle ANSI ED (erase in page) - * - * @v ctx ANSI escape sequence context - * @v count Parameter count - * @v params[0] Region to erase - */ -static void efi_handle_ed ( struct ansiesc_context *ctx __unused, - unsigned int count __unused, - int params[] __unused ) { - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; - - /* We assume that we always clear the whole screen */ - assert ( params[0] == ANSIESC_ED_ALL ); - - conout->ClearScreen ( conout ); -} - -/** - * Handle ANSI SGR (set graphics rendition) - * - * @v ctx ANSI escape sequence context - * @v count Parameter count - * @v params List of graphic rendition aspects - */ -static void efi_handle_sgr ( struct ansiesc_context *ctx __unused, - unsigned int count, int params[] ) { - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; - static const uint8_t efi_attr_fcols[10] = { - ATTR_FCOL_BLACK, ATTR_FCOL_RED, ATTR_FCOL_GREEN, - ATTR_FCOL_YELLOW, ATTR_FCOL_BLUE, ATTR_FCOL_MAGENTA, - ATTR_FCOL_CYAN, ATTR_FCOL_WHITE, - ATTR_FCOL_WHITE, ATTR_FCOL_WHITE /* defaults */ - }; - static const uint8_t efi_attr_bcols[10] = { - ATTR_BCOL_BLACK, ATTR_BCOL_RED, ATTR_BCOL_GREEN, - ATTR_BCOL_YELLOW, ATTR_BCOL_BLUE, ATTR_BCOL_MAGENTA, - ATTR_BCOL_CYAN, ATTR_BCOL_WHITE, - ATTR_BCOL_BLACK, ATTR_BCOL_BLACK /* defaults */ - }; - unsigned int i; - int aspect; - - for ( i = 0 ; i < count ; i++ ) { - aspect = params[i]; - if ( aspect == 0 ) { - efi_attr = ATTR_DEFAULT; - } else if ( aspect == 1 ) { - efi_attr |= ATTR_BOLD; - } else if ( aspect == 22 ) { - efi_attr &= ~ATTR_BOLD; - } else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) { - efi_attr &= ~ATTR_FCOL_MASK; - efi_attr |= efi_attr_fcols[ aspect - 30 ]; - } else if ( ( aspect >= 40 ) && ( aspect <= 49 ) ) { - efi_attr &= ~ATTR_BCOL_MASK; - efi_attr |= efi_attr_bcols[ aspect - 40 ]; - } - } - - conout->SetAttribute ( conout, efi_attr ); -} - -/** - * Handle ANSI DECTCEM set (show cursor) - * - * @v ctx ANSI escape sequence context - * @v count Parameter count - * @v params List of graphic rendition aspects - */ -static void efi_handle_dectcem_set ( struct ansiesc_context *ctx __unused, - unsigned int count __unused, - int params[] __unused ) { - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; - - conout->EnableCursor ( conout, TRUE ); -} - -/** - * Handle ANSI DECTCEM reset (hide cursor) - * - * @v ctx ANSI escape sequence context - * @v count Parameter count - * @v params List of graphic rendition aspects - */ -static void efi_handle_dectcem_reset ( struct ansiesc_context *ctx __unused, - unsigned int count __unused, - int params[] __unused ) { - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; - - conout->EnableCursor ( conout, FALSE ); -} - -/** EFI console ANSI escape sequence handlers */ -static struct ansiesc_handler efi_ansiesc_handlers[] = { - { ANSIESC_CUP, efi_handle_cup }, - { ANSIESC_ED, efi_handle_ed }, - { ANSIESC_SGR, efi_handle_sgr }, - { ANSIESC_DECTCEM_SET, efi_handle_dectcem_set }, - { ANSIESC_DECTCEM_RESET, efi_handle_dectcem_reset }, - { 0, NULL } -}; - -/** EFI console ANSI escape sequence context */ -static struct ansiesc_context efi_ansiesc_ctx = { - .handlers = efi_ansiesc_handlers, -}; - -/** - * Print a character to EFI console - * - * @v character Character to be printed - */ -static void efi_putchar ( int character ) { - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; - wchar_t wstr[] = { character, 0 }; - - /* Intercept ANSI escape sequences */ - character = ansiesc_process ( &efi_ansiesc_ctx, character ); - if ( character < 0 ) - return; - - conout->OutputString ( conout, wstr ); -} - -/** - * Pointer to current ANSI output sequence - * - * While we are in the middle of returning an ANSI sequence for a - * special key, this will point to the next character to return. When - * not in the middle of such a sequence, this will point to a NUL - * (note: not "will be NULL"). - */ -static const char *ansi_input = ""; - -/** Mapping from EFI scan codes to ANSI escape sequences */ -static const char *ansi_sequences[] = { - [SCAN_UP] = "[A", - [SCAN_DOWN] = "[B", - [SCAN_RIGHT] = "[C", - [SCAN_LEFT] = "[D", - [SCAN_HOME] = "[H", - [SCAN_END] = "[F", - [SCAN_INSERT] = "[2~", - /* EFI translates an incoming backspace via the serial console - * into a SCAN_DELETE. There's not much we can do about this. - */ - [SCAN_DELETE] = "[3~", - [SCAN_PAGE_UP] = "[5~", - [SCAN_PAGE_DOWN] = "[6~", - /* EFI translates some (but not all) incoming escape sequences - * via the serial console into equivalent scancodes. When it - * doesn't recognise a sequence, it helpfully(!) translates - * the initial ESC and passes the remainder through verbatim. - * Treating SCAN_ESC as equivalent to an empty escape sequence - * works around this bug. - */ - [SCAN_ESC] = "", -}; - -/** - * Get ANSI escape sequence corresponding to EFI scancode - * - * @v scancode EFI scancode - * @ret ansi_seq ANSI escape sequence, if any, otherwise NULL - */ -static const char * scancode_to_ansi_seq ( unsigned int scancode ) { - if ( scancode < ( sizeof ( ansi_sequences ) / - sizeof ( ansi_sequences[0] ) ) ) { - return ansi_sequences[scancode]; - } - return NULL; -} - -/** - * Get character from EFI console - * - * @ret character Character read from console - */ -static int efi_getchar ( void ) { - EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn; - const char *ansi_seq; - EFI_INPUT_KEY key; - EFI_STATUS efirc; - int rc; - - /* If we are mid-sequence, pass out the next byte */ - if ( *ansi_input ) - return *(ansi_input++); - - /* Read key from real EFI console */ - if ( ( efirc = conin->ReadKeyStroke ( conin, &key ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBG ( "EFI could not read keystroke: %s\n", strerror ( rc ) ); - return 0; - } - DBG2 ( "EFI read key stroke with unicode %04x scancode %04x\n", - key.UnicodeChar, key.ScanCode ); - - /* If key has a Unicode representation, return it */ - if ( key.UnicodeChar ) - return key.UnicodeChar; - - /* Otherwise, check for a special key that we know about */ - if ( ( ansi_seq = scancode_to_ansi_seq ( key.ScanCode ) ) ) { - /* Start of escape sequence: return ESC (0x1b) */ - ansi_input = ansi_seq; - return 0x1b; - } - - return 0; -} - -/** - * Check for character ready to read from EFI console - * - * @ret True Character available to read - * @ret False No character available to read - */ -static int efi_iskey ( void ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn; - EFI_STATUS efirc; - - /* If we are mid-sequence, we are always ready */ - if ( *ansi_input ) - return 1; - - /* Check to see if the WaitForKey event has fired */ - if ( ( efirc = bs->CheckEvent ( conin->WaitForKey ) ) == 0 ) - return 1; - - return 0; -} - -/** EFI console driver */ -struct console_driver efi_console __console_driver = { - .putchar = efi_putchar, - .getchar = efi_getchar, - .iskey = efi_iskey, - .usage = CONSOLE_EFI, -}; - -/** - * Initialise EFI console - * - */ -static void efi_console_init ( void ) { - EFI_CONSOLE_CONTROL_SCREEN_MODE mode; - - /* On some older EFI 1.10 implementations, we must use the - * (now obsolete) EFI_CONSOLE_CONTROL_PROTOCOL to switch the - * console into text mode. - */ - if ( conctrl ) { - conctrl->GetMode ( conctrl, &mode, NULL, NULL ); - if ( mode != EfiConsoleControlScreenText ) { - conctrl->SetMode ( conctrl, - EfiConsoleControlScreenText ); - } - } -} - -/** - * EFI console initialisation function - */ -struct init_fn efi_console_init_fn __init_fn ( INIT_EARLY ) = { - .initialise = efi_console_init, -}; diff --git a/qemu/roms/ipxe/src/interface/efi/efi_debug.c b/qemu/roms/ipxe/src/interface/efi/efi_debug.c deleted file mode 100644 index 473803951..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_debug.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - * 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. - * - * 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 - * - * EFI debugging utilities - * - */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <ipxe/uuid.h> -#include <ipxe/base16.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_utils.h> -#include <ipxe/efi/Protocol/ComponentName.h> -#include <ipxe/efi/Protocol/ComponentName2.h> -#include <ipxe/efi/Protocol/DevicePathToText.h> -#include <ipxe/efi/IndustryStandard/PeImage.h> - -/** Device path to text protocol */ -static EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *efidpt; -EFI_REQUEST_PROTOCOL ( EFI_DEVICE_PATH_TO_TEXT_PROTOCOL, &efidpt ); - -/** Iscsi4Dxe module GUID */ -static EFI_GUID efi_iscsi4_dxe_guid = { - 0x4579b72d, 0x7ec4, 0x4dd4, - { 0x84, 0x86, 0x08, 0x3c, 0x86, 0xb1, 0x82, 0xa7 } -}; - -/** VlanConfigDxe module GUID */ -static EFI_GUID efi_vlan_config_dxe_guid = { - 0xe4f61863, 0xfe2c, 0x4b56, - { 0xa8, 0xf4, 0x08, 0x51, 0x9b, 0xc4, 0x39, 0xdf } -}; - -/** A well-known GUID */ -struct efi_well_known_guid { - /** GUID */ - EFI_GUID *guid; - /** Name */ - const char *name; -}; - -/** Well-known GUIDs */ -static struct efi_well_known_guid efi_well_known_guids[] = { - { &efi_arp_protocol_guid, - "Arp" }, - { &efi_arp_service_binding_protocol_guid, - "ArpSb" }, - { &efi_block_io_protocol_guid, - "BlockIo" }, - { &efi_bus_specific_driver_override_protocol_guid, - "BusSpecificDriverOverride" }, - { &efi_component_name_protocol_guid, - "ComponentName" }, - { &efi_component_name2_protocol_guid, - "ComponentName2" }, - { &efi_device_path_protocol_guid, - "DevicePath" }, - { &efi_driver_binding_protocol_guid, - "DriverBinding" }, - { &efi_dhcp4_protocol_guid, - "Dhcp4" }, - { &efi_dhcp4_service_binding_protocol_guid, - "Dhcp4Sb" }, - { &efi_disk_io_protocol_guid, - "DiskIo" }, - { &efi_graphics_output_protocol_guid, - "GraphicsOutput" }, - { &efi_hii_config_access_protocol_guid, - "HiiConfigAccess" }, - { &efi_ip4_protocol_guid, - "Ip4" }, - { &efi_ip4_config_protocol_guid, - "Ip4Config" }, - { &efi_ip4_service_binding_protocol_guid, - "Ip4Sb" }, - { &efi_iscsi4_dxe_guid, - "IScsi4Dxe" }, - { &efi_load_file_protocol_guid, - "LoadFile" }, - { &efi_load_file2_protocol_guid, - "LoadFile2" }, - { &efi_loaded_image_protocol_guid, - "LoadedImage" }, - { &efi_loaded_image_device_path_protocol_guid, - "LoadedImageDevicePath"}, - { &efi_managed_network_protocol_guid, - "ManagedNetwork" }, - { &efi_managed_network_service_binding_protocol_guid, - "ManagedNetworkSb" }, - { &efi_mtftp4_protocol_guid, - "Mtftp4" }, - { &efi_mtftp4_service_binding_protocol_guid, - "Mtftp4Sb" }, - { &efi_nii_protocol_guid, - "Nii" }, - { &efi_nii31_protocol_guid, - "Nii31" }, - { &efi_pci_io_protocol_guid, - "PciIo" }, - { &efi_pci_root_bridge_io_protocol_guid, - "PciRootBridgeIo" }, - { &efi_pxe_base_code_protocol_guid, - "PxeBaseCode" }, - { &efi_simple_file_system_protocol_guid, - "SimpleFileSystem" }, - { &efi_simple_network_protocol_guid, - "SimpleNetwork" }, - { &efi_tcg_protocol_guid, - "Tcg" }, - { &efi_tcp4_protocol_guid, - "Tcp4" }, - { &efi_tcp4_service_binding_protocol_guid, - "Tcp4Sb" }, - { &efi_udp4_protocol_guid, - "Udp4" }, - { &efi_udp4_service_binding_protocol_guid, - "Udp4Sb" }, - { &efi_vlan_config_protocol_guid, - "VlanConfig" }, - { &efi_vlan_config_dxe_guid, - "VlanConfigDxe" }, -}; - -/** - * Convert GUID to a printable string - * - * @v guid GUID - * @ret string Printable string - */ -const char * efi_guid_ntoa ( EFI_GUID *guid ) { - union { - union uuid uuid; - EFI_GUID guid; - } u; - unsigned int i; - - /* Sanity check */ - if ( ! guid ) - return NULL; - - /* Check for a match against well-known GUIDs */ - for ( i = 0 ; i < ( sizeof ( efi_well_known_guids ) / - sizeof ( efi_well_known_guids[0] ) ) ; i++ ) { - if ( memcmp ( guid, efi_well_known_guids[i].guid, - sizeof ( *guid ) ) == 0 ) { - return efi_well_known_guids[i].name; - } - } - - /* Convert GUID to standard endianness */ - memcpy ( &u.guid, guid, sizeof ( u.guid ) ); - uuid_mangle ( &u.uuid ); - return uuid_ntoa ( &u.uuid ); -} - -/** - * Name protocol open attributes - * - * @v attributes Protocol open attributes - * @ret name Protocol open attributes name - * - * Returns a (static) string with characters for each set bit - * corresponding to BY_(H)ANDLE_PROTOCOL, (G)ET_PROTOCOL, - * (T)EST_PROTOCOL, BY_(C)HILD_CONTROLLER, BY_(D)RIVER, and - * E(X)CLUSIVE. - */ -static const char * efi_open_attributes_name ( unsigned int attributes ) { - static char attribute_chars[] = "HGTCDX"; - static char name[ sizeof ( attribute_chars ) ]; - char *tmp = name; - unsigned int i; - - for ( i = 0 ; i < ( sizeof ( attribute_chars ) - 1 ) ; i++ ) { - if ( attributes & ( 1 << i ) ) - *(tmp++) = attribute_chars[i]; - } - *tmp = '\0'; - - return name; -} - -/** - * Print list of openers of a given protocol on a given handle - * - * @v handle EFI handle - * @v protocol Protocol GUID - */ -void dbg_efi_openers ( EFI_HANDLE handle, EFI_GUID *protocol ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener; - UINTN count; - unsigned int i; - EFI_STATUS efirc; - int rc; - - /* Sanity check */ - if ( ( ! handle ) || ( ! protocol ) ) { - printf ( "EFI could not retrieve openers for %s on %p\n", - efi_guid_ntoa ( protocol ), handle ); - return; - } - - /* Retrieve list of openers */ - if ( ( efirc = bs->OpenProtocolInformation ( handle, protocol, &openers, - &count ) ) != 0 ) { - rc = -EEFI ( efirc ); - printf ( "EFI could not retrieve openers for %s on %p: %s\n", - efi_guid_ntoa ( protocol ), handle, strerror ( rc ) ); - return; - } - - /* Dump list of openers */ - for ( i = 0 ; i < count ; i++ ) { - opener = &openers[i]; - printf ( "HANDLE %p %s %s opened %dx (%s)", - handle, efi_handle_name ( handle ), - efi_guid_ntoa ( protocol ), opener->OpenCount, - efi_open_attributes_name ( opener->Attributes ) ); - printf ( " by %p %s", opener->AgentHandle, - efi_handle_name ( opener->AgentHandle ) ); - if ( opener->ControllerHandle == handle ) { - printf ( "\n" ); - } else { - printf ( " for %p %s\n", opener->ControllerHandle, - efi_handle_name ( opener->ControllerHandle ) ); - } - } - - /* Free list */ - bs->FreePool ( openers ); -} - -/** - * Print list of protocol handlers attached to a handle - * - * @v handle EFI handle - */ -void dbg_efi_protocols ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_GUID **protocols; - EFI_GUID *protocol; - UINTN count; - unsigned int i; - EFI_STATUS efirc; - int rc; - - /* Sanity check */ - if ( ! handle ) { - printf ( "EFI could not retrieve protocols for %p\n", handle ); - return; - } - - /* Retrieve list of protocols */ - if ( ( efirc = bs->ProtocolsPerHandle ( handle, &protocols, - &count ) ) != 0 ) { - rc = -EEFI ( efirc ); - printf ( "EFI could not retrieve protocols for %p: %s\n", - handle, strerror ( rc ) ); - return; - } - - /* Dump list of protocols */ - for ( i = 0 ; i < count ; i++ ) { - protocol = protocols[i]; - printf ( "HANDLE %p %s %s supported\n", - handle, efi_handle_name ( handle ), - efi_guid_ntoa ( protocol ) ); - dbg_efi_openers ( handle, protocol ); - } - - /* Free list */ - bs->FreePool ( protocols ); -} - -/** - * Get textual representation of device path - * - * @v path Device path - * @ret text Textual representation of device path, or NULL - */ -const char * efi_devpath_text ( EFI_DEVICE_PATH_PROTOCOL *path ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - static char text[256]; - void *start; - void *end; - size_t max_len; - size_t len; - CHAR16 *wtext; - - /* Sanity checks */ - if ( ! path ) { - DBG ( "[NULL DevicePath]" ); - return NULL; - } - - /* If we have no DevicePathToText protocol then use a raw hex string */ - if ( ! efidpt ) { - DBG ( "[No DevicePathToText]" ); - start = path; - end = efi_devpath_end ( path ); - len = ( end - start ); - max_len = ( ( sizeof ( text ) - 1 /* NUL */ ) / 2 /* "xx" */ ); - if ( len > max_len ) - len = max_len; - base16_encode ( start, len, text, sizeof ( text ) ); - return text; - } - - /* Convert path to a textual representation */ - wtext = efidpt->ConvertDevicePathToText ( path, TRUE, FALSE ); - if ( ! wtext ) - return NULL; - - /* Store path in buffer */ - snprintf ( text, sizeof ( text ), "%ls", wtext ); - - /* Free path */ - bs->FreePool ( wtext ); - - return text; -} - -/** - * Get driver name - * - * @v wtf Component name protocol - * @ret name Driver name, or NULL - */ -static const char * efi_driver_name ( EFI_COMPONENT_NAME_PROTOCOL *wtf ) { - static char name[64]; - CHAR16 *driver_name; - EFI_STATUS efirc; - - /* Sanity check */ - if ( ! wtf ) { - DBG ( "[NULL ComponentName]" ); - return NULL; - } - - /* Try "eng" first; if that fails then try the first language */ - if ( ( ( efirc = wtf->GetDriverName ( wtf, "eng", - &driver_name ) ) != 0 ) && - ( ( efirc = wtf->GetDriverName ( wtf, wtf->SupportedLanguages, - &driver_name ) ) != 0 ) ) { - return NULL; - } - - /* Convert name from CHAR16 to char */ - snprintf ( name, sizeof ( name ), "%ls", driver_name ); - return name; -} - -/** - * Get driver name - * - * @v wtf Component name protocol - * @ret name Driver name, or NULL - */ -static const char * efi_driver_name2 ( EFI_COMPONENT_NAME2_PROTOCOL *wtf ) { - static char name[64]; - CHAR16 *driver_name; - EFI_STATUS efirc; - - /* Sanity check */ - if ( ! wtf ) { - DBG ( "[NULL ComponentName2]" ); - return NULL; - } - - /* Try "en" first; if that fails then try the first language */ - if ( ( ( efirc = wtf->GetDriverName ( wtf, "en", - &driver_name ) ) != 0 ) && - ( ( efirc = wtf->GetDriverName ( wtf, wtf->SupportedLanguages, - &driver_name ) ) != 0 ) ) { - return NULL; - } - - /* Convert name from CHAR16 to char */ - snprintf ( name, sizeof ( name ), "%ls", driver_name ); - return name; -} - -/** - * Get PE/COFF debug filename - * - * @v loaded Loaded image - * @ret name PE/COFF debug filename, or NULL - */ -static const char * -efi_pecoff_debug_name ( EFI_LOADED_IMAGE_PROTOCOL *loaded ) { - static char buf[32]; - EFI_IMAGE_DOS_HEADER *dos; - EFI_IMAGE_OPTIONAL_HEADER_UNION *pe; - EFI_IMAGE_OPTIONAL_HEADER32 *opt32; - EFI_IMAGE_OPTIONAL_HEADER64 *opt64; - EFI_IMAGE_DATA_DIRECTORY *datadir; - EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *debug; - EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *codeview_nb10; - EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *codeview_rsds; - EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY *codeview_mtoc; - uint16_t dos_magic; - uint32_t pe_magic; - uint16_t opt_magic; - uint32_t codeview_magic; - size_t max_len; - char *name; - char *tmp; - - /* Sanity check */ - if ( ! loaded ) { - DBG ( "[NULL LoadedImage]" ); - return NULL; - } - - /* Parse DOS header */ - dos = loaded->ImageBase; - if ( ! dos ) { - DBG ( "[Missing DOS header]" ); - return NULL; - } - dos_magic = dos->e_magic; - if ( dos_magic != EFI_IMAGE_DOS_SIGNATURE ) { - DBG ( "[Bad DOS signature %#04x]", dos_magic ); - return NULL; - } - pe = ( loaded->ImageBase + dos->e_lfanew ); - - /* Parse PE header */ - pe_magic = pe->Pe32.Signature; - if ( pe_magic != EFI_IMAGE_NT_SIGNATURE ) { - DBG ( "[Bad PE signature %#08x]", pe_magic ); - return NULL; - } - opt32 = &pe->Pe32.OptionalHeader; - opt64 = &pe->Pe32Plus.OptionalHeader; - opt_magic = opt32->Magic; - if ( opt_magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) { - datadir = opt32->DataDirectory; - } else if ( opt_magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC ) { - datadir = opt64->DataDirectory; - } else { - DBG ( "[Bad optional header signature %#04x]", opt_magic ); - return NULL; - } - - /* Parse data directory entry */ - if ( ! datadir[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress ) { - DBG ( "[Empty debug directory entry]" ); - return NULL; - } - debug = ( loaded->ImageBase + - datadir[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress ); - - /* Parse debug directory entry */ - if ( debug->Type != EFI_IMAGE_DEBUG_TYPE_CODEVIEW ) { - DBG ( "[Not a CodeView debug directory entry (type %d)]", - debug->Type ); - return NULL; - } - codeview_nb10 = ( loaded->ImageBase + debug->RVA ); - codeview_rsds = ( loaded->ImageBase + debug->RVA ); - codeview_mtoc = ( loaded->ImageBase + debug->RVA ); - codeview_magic = codeview_nb10->Signature; - - /* Parse CodeView entry */ - if ( codeview_magic == CODEVIEW_SIGNATURE_NB10 ) { - name = ( ( void * ) ( codeview_nb10 + 1 ) ); - } else if ( codeview_magic == CODEVIEW_SIGNATURE_RSDS ) { - name = ( ( void * ) ( codeview_rsds + 1 ) ); - } else if ( codeview_magic == CODEVIEW_SIGNATURE_MTOC ) { - name = ( ( void * ) ( codeview_mtoc + 1 ) ); - } else { - DBG ( "[Bad CodeView signature %#08x]", codeview_magic ); - return NULL; - } - - /* Sanity check - avoid scanning endlessly through memory */ - max_len = EFI_PAGE_SIZE; /* Reasonably sane */ - if ( strnlen ( name, max_len ) == max_len ) { - DBG ( "[Excessively long or invalid CodeView name]" ); - return NULL; - } - - /* Skip any directory components. We cannot modify this data - * or create a temporary buffer, so do not use basename(). - */ - while ( ( ( tmp = strchr ( name, '/' ) ) != NULL ) || - ( ( tmp = strchr ( name, '\\' ) ) != NULL ) ) { - name = ( tmp + 1 ); - } - - /* Copy base name to buffer */ - snprintf ( buf, sizeof ( buf ), "%s", name ); - - /* Strip file suffix, if present */ - if ( ( tmp = strrchr ( name, '.' ) ) != NULL ) - *tmp = '\0'; - - return name; -} - -/** - * Get initial loaded image name - * - * @v loaded Loaded image - * @ret name Initial loaded image name, or NULL - */ -static const char * -efi_first_loaded_image_name ( EFI_LOADED_IMAGE_PROTOCOL *loaded ) { - - /* Sanity check */ - if ( ! loaded ) { - DBG ( "[NULL LoadedImage]" ); - return NULL; - } - - return ( ( loaded->ParentHandle == NULL ) ? "DxeCore(?)" : NULL ); -} - -/** - * Get loaded image name from file path - * - * @v loaded Loaded image - * @ret name Loaded image name, or NULL - */ -static const char * -efi_loaded_image_filepath_name ( EFI_LOADED_IMAGE_PROTOCOL *loaded ) { - - /* Sanity check */ - if ( ! loaded ) { - DBG ( "[NULL LoadedImage]" ); - return NULL; - } - - return efi_devpath_text ( loaded->FilePath ); -} - -/** An EFI handle name type */ -struct efi_handle_name_type { - /** Protocol */ - EFI_GUID *protocol; - /** - * Get name - * - * @v interface Protocol interface - * @ret name Name of handle, or NULL on failure - */ - const char * ( * name ) ( void *interface ); -}; - -/** - * Define an EFI handle name type - * - * @v protocol Protocol interface - * @v name Method to get name - * @ret type EFI handle name type - */ -#define EFI_HANDLE_NAME_TYPE( protocol, name ) { \ - (protocol), \ - ( const char * ( * ) ( void * ) ) (name), \ - } - -/** EFI handle name types */ -static struct efi_handle_name_type efi_handle_name_types[] = { - /* Device path */ - EFI_HANDLE_NAME_TYPE ( &efi_device_path_protocol_guid, - efi_devpath_text ), - /* Driver name (for driver image handles) */ - EFI_HANDLE_NAME_TYPE ( &efi_component_name2_protocol_guid, - efi_driver_name2 ), - /* Driver name (via obsolete original ComponentName protocol) */ - EFI_HANDLE_NAME_TYPE ( &efi_component_name_protocol_guid, - efi_driver_name ), - /* PE/COFF debug filename (for image handles) */ - EFI_HANDLE_NAME_TYPE ( &efi_loaded_image_protocol_guid, - efi_pecoff_debug_name ), - /* Loaded image device path (for image handles) */ - EFI_HANDLE_NAME_TYPE ( &efi_loaded_image_device_path_protocol_guid, - efi_devpath_text ), - /* First loaded image name (for the DxeCore image) */ - EFI_HANDLE_NAME_TYPE ( &efi_loaded_image_protocol_guid, - efi_first_loaded_image_name ), - /* Handle's loaded image file path (for image handles) */ - EFI_HANDLE_NAME_TYPE ( &efi_loaded_image_protocol_guid, - efi_loaded_image_filepath_name ), -}; - -/** - * Get name of an EFI handle - * - * @v handle EFI handle - * @ret text Name of handle, or NULL - */ -const char * efi_handle_name ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct efi_handle_name_type *type; - unsigned int i; - void *interface; - const char *name; - EFI_STATUS efirc; - - /* Fail immediately for NULL handles */ - if ( ! handle ) - return NULL; - - /* Try each name type in turn */ - for ( i = 0 ; i < ( sizeof ( efi_handle_name_types ) / - sizeof ( efi_handle_name_types[0] ) ) ; i++ ) { - type = &efi_handle_name_types[i]; - DBG2 ( "<%d", i ); - - /* Try to open the applicable protocol */ - efirc = bs->OpenProtocol ( handle, type->protocol, &interface, - efi_image_handle, handle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ); - if ( efirc != 0 ) { - DBG2 ( ">" ); - continue; - } - - /* Try to get name from this protocol */ - DBG2 ( "-" ); - name = type->name ( interface ); - DBG2 ( "%c", ( name ? ( name[0] ? 'Y' : 'E' ) : 'N' ) ); - - /* Close protocol */ - bs->CloseProtocol ( handle, type->protocol, - efi_image_handle, handle ); - DBG2 ( ">" ); - - /* Use this name, if possible */ - if ( name && name[0] ) - return name; - } - - return "UNKNOWN"; -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_download.c b/qemu/roms/ipxe/src/interface/efi/efi_download.c deleted file mode 100644 index 1218852e2..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_download.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2010 VMware, Inc. All Rights Reserved. - * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <ipxe/open.h> -#include <ipxe/process.h> -#include <ipxe/iobuf.h> -#include <ipxe/xfer.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_snp.h> -#include <ipxe/efi/efi_download.h> - -/** iPXE download protocol GUID */ -static EFI_GUID ipxe_download_protocol_guid - = IPXE_DOWNLOAD_PROTOCOL_GUID; - -/** A single in-progress file */ -struct efi_download_file { - /** Data transfer interface that provides downloaded data */ - struct interface xfer; - - /** Current file position */ - size_t pos; - - /** Data callback */ - IPXE_DOWNLOAD_DATA_CALLBACK data_callback; - - /** Finish callback */ - IPXE_DOWNLOAD_FINISH_CALLBACK finish_callback; - - /** Callback context */ - void *context; -}; - -/* xfer interface */ - -/** - * Transfer finished or was aborted - * - * @v file Data transfer file - * @v rc Reason for close - */ -static void efi_download_close ( struct efi_download_file *file, int rc ) { - - file->finish_callback ( file->context, EFIRC ( rc ) ); - - intf_shutdown ( &file->xfer, rc ); - - efi_snp_release(); -} - -/** - * Process received data - * - * @v file Data transfer file - * @v iobuf I/O buffer - * @v meta Data transfer metadata - * @ret rc Return status code - */ -static int efi_download_deliver_iob ( struct efi_download_file *file, - struct io_buffer *iobuf, - struct xfer_metadata *meta ) { - EFI_STATUS efirc; - size_t len = iob_len ( iobuf ); - int rc; - - /* Calculate new buffer position */ - if ( meta->flags & XFER_FL_ABS_OFFSET ) - file->pos = 0; - file->pos += meta->offset; - - /* Call out to the data handler */ - if ( ( efirc = file->data_callback ( file->context, iobuf->data, - len, file->pos ) ) != 0 ) { - rc = -EEFI ( efirc ); - goto err_callback; - } - - /* Update current buffer position */ - file->pos += len; - - /* Success */ - rc = 0; - - err_callback: - free_iob ( iobuf ); - return rc; -} - -/** Data transfer interface operations */ -static struct interface_operation efi_xfer_operations[] = { - INTF_OP ( xfer_deliver, struct efi_download_file *, efi_download_deliver_iob ), - INTF_OP ( intf_close, struct efi_download_file *, efi_download_close ), -}; - -/** EFI download data transfer interface descriptor */ -static struct interface_descriptor efi_download_file_xfer_desc = - INTF_DESC ( struct efi_download_file, xfer, efi_xfer_operations ); - -/** - * Start downloading a file, and register callback functions to handle the - * download. - * - * @v This iPXE Download Protocol instance - * @v Url URL to download from - * @v DataCallback Callback that will be invoked when data arrives - * @v FinishCallback Callback that will be invoked when the download ends - * @v Context Context passed to the Data and Finish callbacks - * @v File Token that can be used to abort the download - * @ret Status EFI status code - */ -static EFI_STATUS EFIAPI -efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused, - CHAR8 *Url, - IPXE_DOWNLOAD_DATA_CALLBACK DataCallback, - IPXE_DOWNLOAD_FINISH_CALLBACK FinishCallback, - VOID *Context, - IPXE_DOWNLOAD_FILE *File ) { - struct efi_download_file *file; - int rc; - - file = malloc ( sizeof ( struct efi_download_file ) ); - if ( file == NULL ) { - return EFI_OUT_OF_RESOURCES; - } - - intf_init ( &file->xfer, &efi_download_file_xfer_desc, NULL ); - rc = xfer_open ( &file->xfer, LOCATION_URI_STRING, Url ); - if ( rc ) { - free ( file ); - return EFIRC ( rc ); - } - - efi_snp_claim(); - file->pos = 0; - file->data_callback = DataCallback; - file->finish_callback = FinishCallback; - file->context = Context; - *File = file; - return EFI_SUCCESS; -} - -/** - * Forcibly abort downloading a file that is currently in progress. - * - * It is not safe to call this function after the Finish callback has executed. - * - * @v This iPXE Download Protocol instance - * @v File Token obtained from Start - * @v Status Reason for aborting the download - * @ret Status EFI status code - */ -static EFI_STATUS EFIAPI -efi_download_abort ( IPXE_DOWNLOAD_PROTOCOL *This __unused, - IPXE_DOWNLOAD_FILE File, - EFI_STATUS Status ) { - struct efi_download_file *file = File; - - efi_download_close ( file, -EEFI ( Status ) ); - return EFI_SUCCESS; -} - -/** - * Poll for more data from iPXE. This function will invoke the registered - * callbacks if data is available or if downloads complete. - * - * @v This iPXE Download Protocol instance - * @ret Status EFI status code - */ -static EFI_STATUS EFIAPI -efi_download_poll ( IPXE_DOWNLOAD_PROTOCOL *This __unused ) { - step(); - return EFI_SUCCESS; -} - -/** Publicly exposed iPXE download protocol */ -static IPXE_DOWNLOAD_PROTOCOL ipxe_download_protocol_interface = { - .Start = efi_download_start, - .Abort = efi_download_abort, - .Poll = efi_download_poll -}; - -/** - * Install iPXE download protocol - * - * @v handle EFI handle - * @ret rc Return status code - */ -int efi_download_install ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_STATUS efirc; - int rc; - - efirc = bs->InstallMultipleProtocolInterfaces ( - &handle, - &ipxe_download_protocol_guid, - &ipxe_download_protocol_interface, - NULL ); - if ( efirc ) { - rc = -EEFI ( efirc ); - DBG ( "Could not install download protocol: %s\n", - strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Uninstall iPXE download protocol - * - * @v handle EFI handle - */ -void efi_download_uninstall ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - bs->UninstallMultipleProtocolInterfaces ( - handle, - &ipxe_download_protocol_guid, - &ipxe_download_protocol_interface, NULL ); -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_driver.c b/qemu/roms/ipxe/src/interface/efi/efi_driver.c deleted file mode 100644 index ba7784cd7..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_driver.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (C) 2011 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 <stddef.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <ipxe/version.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/Protocol/DriverBinding.h> -#include <ipxe/efi/Protocol/ComponentName2.h> -#include <ipxe/efi/Protocol/DevicePath.h> -#include <ipxe/efi/efi_strings.h> -#include <ipxe/efi/efi_driver.h> - -/** @file - * - * EFI driver interface - * - */ - -static EFI_DRIVER_BINDING_PROTOCOL efi_driver_binding; - -/** List of controlled EFI devices */ -static LIST_HEAD ( efi_devices ); - -/** - * Find EFI device - * - * @v device EFI device handle - * @ret efidev EFI device, or NULL if not found - */ -static struct efi_device * efidev_find ( EFI_HANDLE device ) { - struct efi_device *efidev; - - /* Look for an existing EFI device */ - list_for_each_entry ( efidev, &efi_devices, dev.siblings ) { - if ( efidev->device == device ) - return efidev; - } - - return NULL; -} - -/** - * Get parent EFI device - * - * @v dev Generic device - * @ret efidev Parent EFI device, or NULL - */ -struct efi_device * efidev_parent ( struct device *dev ) { - struct device *parent = dev->parent; - struct efi_device *efidev; - - /* Check that parent exists and is an EFI device */ - if ( ! parent ) - return NULL; - if ( parent->desc.bus_type != BUS_TYPE_EFI ) - return NULL; - - /* Get containing EFI device */ - efidev = container_of ( parent, struct efi_device, dev ); - return efidev; -} - -/** - * Check to see if driver supports a device - * - * @v driver EFI driver - * @v device EFI device - * @v child Path to child device, if any - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused, - EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) { - struct efi_driver *efidrv; - int rc; - - DBGCP ( device, "EFIDRV %p %s DRIVER_SUPPORTED", - device, efi_handle_name ( device ) ); - if ( child ) - DBGCP ( device, " (child %s)", efi_devpath_text ( child ) ); - DBGCP ( device, "\n" ); - - /* Do nothing if we are already driving this device */ - if ( efidev_find ( device ) != NULL ) { - DBGCP ( device, "EFIDRV %p %s is already started\n", - device, efi_handle_name ( device ) ); - return EFI_ALREADY_STARTED; - } - - /* Look for a driver claiming to support this device */ - for_each_table_entry ( efidrv, EFI_DRIVERS ) { - if ( ( rc = efidrv->supported ( device ) ) == 0 ) { - DBGC ( device, "EFIDRV %p %s has driver \"%s\"\n", - device, efi_handle_name ( device ), - efidrv->name ); - return 0; - } - } - DBGCP ( device, "EFIDRV %p %s has no driver\n", - device, efi_handle_name ( device ) ); - - return EFI_UNSUPPORTED; -} - -/** - * Attach driver to device - * - * @v driver EFI driver - * @v device EFI device - * @v child Path to child device, if any - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused, - EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) { - struct efi_driver *efidrv; - struct efi_device *efidev; - EFI_STATUS efirc; - int rc; - - DBGC ( device, "EFIDRV %p %s DRIVER_START", - device, efi_handle_name ( device ) ); - if ( child ) - DBGC ( device, " (child %s)", efi_devpath_text ( child ) ); - DBGC ( device, "\n" ); - - /* Do nothing if we are already driving this device */ - efidev = efidev_find ( device ); - if ( efidev ) { - DBGCP ( device, "EFIDRV %p %s is already started\n", - device, efi_handle_name ( device ) ); - efirc = EFI_ALREADY_STARTED; - goto err_already_started; - } - - /* Allocate and initialise structure */ - efidev = zalloc ( sizeof ( *efidev ) ); - if ( ! efidev ) { - efirc = EFI_OUT_OF_RESOURCES; - goto err_alloc; - } - efidev->device = device; - efidev->dev.desc.bus_type = BUS_TYPE_EFI; - INIT_LIST_HEAD ( &efidev->dev.children ); - list_add ( &efidev->dev.siblings, &efi_devices ); - - /* Try to start this device */ - for_each_table_entry ( efidrv, EFI_DRIVERS ) { - if ( ( rc = efidrv->supported ( device ) ) != 0 ) { - DBGC ( device, "EFIDRV %p %s is not supported by " - "driver \"%s\": %s\n", device, - efi_handle_name ( device ), efidrv->name, - strerror ( rc ) ); - continue; - } - if ( ( rc = efidrv->start ( efidev ) ) == 0 ) { - efidev->driver = efidrv; - DBGC ( device, "EFIDRV %p %s using driver \"%s\"\n", - device, efi_handle_name ( device ), - efidev->driver->name ); - return 0; - } - DBGC ( device, "EFIDRV %p %s could not start driver \"%s\": " - "%s\n", device, efi_handle_name ( device ), - efidrv->name, strerror ( rc ) ); - } - efirc = EFI_UNSUPPORTED; - - list_del ( &efidev->dev.siblings ); - free ( efidev ); - err_alloc: - err_already_started: - return efirc; -} - -/** - * Detach driver from device - * - * @v driver EFI driver - * @v device EFI device - * @v pci PCI device - * @v num_children Number of child devices - * @v children List of child devices - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused, - EFI_HANDLE device, UINTN num_children, - EFI_HANDLE *children ) { - struct efi_driver *efidrv; - struct efi_device *efidev; - UINTN i; - - DBGC ( device, "EFIDRV %p %s DRIVER_STOP", - device, efi_handle_name ( device ) ); - for ( i = 0 ; i < num_children ; i++ ) { - DBGC ( device, "%s%p %s", ( i ? ", " : " child " ), - children[i], efi_handle_name ( children[i] ) ); - } - DBGC ( device, "\n" ); - - /* Do nothing unless we are driving this device */ - efidev = efidev_find ( device ); - if ( ! efidev ) { - DBGCP ( device, "EFIDRV %p %s is not started\n", - device, efi_handle_name ( device ) ); - return 0; - } - - /* Stop this device */ - efidrv = efidev->driver; - assert ( efidrv != NULL ); - efidrv->stop ( efidev ); - list_del ( &efidev->dev.siblings ); - free ( efidev ); - - return 0; -} - -/** EFI driver binding protocol */ -static EFI_DRIVER_BINDING_PROTOCOL efi_driver_binding = { - .Supported = efi_driver_supported, - .Start = efi_driver_start, - .Stop = efi_driver_stop, -}; - -/** - * Look up driver name - * - * @v wtf Component name protocol - * @v language Language to use - * @v driver_name Driver name to fill in - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused, - CHAR8 *language __unused, CHAR16 **driver_name ) { - const wchar_t *name; - - name = ( product_wname[0] ? product_wname : build_wname ); - *driver_name = ( ( wchar_t * ) name ); - return 0; -} - -/** - * Look up controller name - * - * @v wtf Component name protocol - * @v device Device - * @v child Child device, or NULL - * @v language Language to use - * @v driver_name Device name to fill in - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_driver_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused, - EFI_HANDLE device, EFI_HANDLE child, - CHAR8 *language, CHAR16 **controller_name ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - union { - EFI_COMPONENT_NAME2_PROTOCOL *name2; - void *interface; - } name2; - EFI_STATUS efirc; - - /* Delegate to the EFI_COMPONENT_NAME2_PROTOCOL instance - * installed on child handle, if present. - */ - if ( ( child != NULL ) && - ( ( efirc = bs->OpenProtocol ( - child, &efi_component_name2_protocol_guid, - &name2.interface, NULL, NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) == 0 ) ) { - return name2.name2->GetControllerName ( name2.name2, device, - child, language, - controller_name ); - } - - /* Otherwise, let EFI use the default Device Path Name */ - return EFI_UNSUPPORTED; -} - -/** EFI component name protocol */ -static EFI_COMPONENT_NAME2_PROTOCOL efi_wtf = { - .GetDriverName = efi_driver_name, - .GetControllerName = efi_driver_controller_name, - .SupportedLanguages = "en", -}; - -/** - * Install EFI driver - * - * @ret rc Return status code - */ -int efi_driver_install ( void ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_STATUS efirc; - int rc; - - /* Calculate driver version number. We use the build - * timestamp (in seconds since the Epoch) shifted right by six - * bits: this gives us an approximately one-minute resolution - * and a scheme which will last until the year 10680. - */ - efi_driver_binding.Version = ( build_timestamp >> 6 ); - - /* Install protocols on image handle */ - efi_driver_binding.ImageHandle = efi_image_handle; - efi_driver_binding.DriverBindingHandle = efi_image_handle; - if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( - &efi_image_handle, - &efi_driver_binding_protocol_guid, &efi_driver_binding, - &efi_component_name2_protocol_guid, &efi_wtf, - NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( &efi_driver_binding, "EFIDRV could not install " - "protocols: %s\n", strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Uninstall EFI driver - * - */ -void efi_driver_uninstall ( void ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - /* Uninstall protocols */ - bs->UninstallMultipleProtocolInterfaces ( - efi_image_handle, - &efi_driver_binding_protocol_guid, &efi_driver_binding, - &efi_component_name2_protocol_guid, &efi_wtf, NULL ); -} - -/** - * Try to connect EFI driver - * - * @v device EFI device - * @ret rc Return status code - */ -static int efi_driver_connect ( EFI_HANDLE device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE drivers[2] = - { efi_driver_binding.DriverBindingHandle, NULL }; - EFI_STATUS efirc; - int rc; - - /* Check if we want to drive this device */ - if ( ( efirc = efi_driver_supported ( &efi_driver_binding, device, - NULL ) ) != 0 ) { - /* Not supported; not an error */ - return 0; - } - - /* Disconnect any existing drivers */ - DBGC2 ( device, "EFIDRV %p %s before disconnecting:\n", - device, efi_handle_name ( device ) ); - DBGC2_EFI_PROTOCOLS ( device, device ); - DBGC ( device, "EFIDRV %p %s disconnecting existing drivers\n", - device, efi_handle_name ( device ) ); - if ( ( efirc = bs->DisconnectController ( device, NULL, - NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( device, "EFIDRV %p %s could not disconnect existing " - "drivers: %s\n", device, efi_handle_name ( device ), - strerror ( rc ) ); - /* Ignore the error and attempt to connect our drivers */ - } - DBGC2 ( device, "EFIDRV %p %s after disconnecting:\n", - device, efi_handle_name ( device ) ); - DBGC2_EFI_PROTOCOLS ( device, device ); - - /* Connect our driver */ - DBGC ( device, "EFIDRV %p %s connecting new drivers\n", - device, efi_handle_name ( device ) ); - if ( ( efirc = bs->ConnectController ( device, drivers, NULL, - FALSE ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( device, "EFIDRV %p %s could not connect new drivers: " - "%s\n", device, efi_handle_name ( device ), - strerror ( rc ) ); - return rc; - } - DBGC2 ( device, "EFIDRV %p %s after connecting:\n", - device, efi_handle_name ( device ) ); - DBGC2_EFI_PROTOCOLS ( device, device ); - - return 0; -} - -/** - * Try to disconnect EFI driver - * - * @v device EFI device - * @ret rc Return status code - */ -static int efi_driver_disconnect ( EFI_HANDLE device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - /* Disconnect our driver */ - bs->DisconnectController ( device, - efi_driver_binding.DriverBindingHandle, - NULL ); - return 0; -} - -/** - * Reconnect original EFI driver - * - * @v device EFI device - * @ret rc Return status code - */ -static int efi_driver_reconnect ( EFI_HANDLE device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - /* Reconnect any available driver */ - bs->ConnectController ( device, NULL, NULL, FALSE ); - - return 0; -} - -/** - * Connect/disconnect EFI driver from all handles - * - * @v method Connect/disconnect method - * @ret rc Return status code - */ -static int efi_driver_handles ( int ( * method ) ( EFI_HANDLE handle ) ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE *handles; - UINTN num_handles; - EFI_STATUS efirc; - UINTN i; - int rc; - - /* Enumerate all handles */ - if ( ( efirc = bs->LocateHandleBuffer ( AllHandles, NULL, NULL, - &num_handles, - &handles ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( &efi_driver_binding, "EFIDRV could not list handles: " - "%s\n", strerror ( rc ) ); - goto err_locate; - } - - /* Connect/disconnect driver from all handles */ - for ( i = 0 ; i < num_handles ; i++ ) { - if ( ( rc = method ( handles[i] ) ) != 0 ) - goto err_method; - } - - /* Success */ - rc = 0; - - err_method: - bs->FreePool ( handles ); - err_locate: - return rc; -} - -/** - * Connect EFI driver to all possible devices - * - * @ret rc Return status code - */ -int efi_driver_connect_all ( void ) { - - DBGC ( &efi_driver_binding, "EFIDRV connecting our drivers\n" ); - return efi_driver_handles ( efi_driver_connect ); -} - -/** - * Disconnect EFI driver from all possible devices - * - * @ret rc Return status code - */ -void efi_driver_disconnect_all ( void ) { - - DBGC ( &efi_driver_binding, "EFIDRV disconnecting our drivers\n" ); - efi_driver_handles ( efi_driver_disconnect ); -} - -/** - * Reconnect original EFI drivers to all possible devices - * - * @ret rc Return status code - */ -void efi_driver_reconnect_all ( void ) { - - DBGC ( &efi_driver_binding, "EFIDRV reconnecting old drivers\n" ); - efi_driver_handles ( efi_driver_reconnect ); -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_file.c b/qemu/roms/ipxe/src/interface/efi/efi_file.c deleted file mode 100644 index 3715b70bf..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_file.c +++ /dev/null @@ -1,718 +0,0 @@ -/* - * 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. - * - * 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 - * - * EFI file protocols - * - */ - -#include <stddef.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <strings.h> -#include <errno.h> -#include <wchar.h> -#include <ipxe/image.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/Protocol/SimpleFileSystem.h> -#include <ipxe/efi/Protocol/BlockIo.h> -#include <ipxe/efi/Protocol/DiskIo.h> -#include <ipxe/efi/Guid/FileInfo.h> -#include <ipxe/efi/Guid/FileSystemInfo.h> -#include <ipxe/efi/efi_strings.h> -#include <ipxe/efi/efi_file.h> - -/** EFI file information GUID */ -static EFI_GUID efi_file_info_id = EFI_FILE_INFO_ID; - -/** EFI file system information GUID */ -static EFI_GUID efi_file_system_info_id = EFI_FILE_SYSTEM_INFO_ID; - -/** EFI media ID */ -#define EFI_MEDIA_ID_MAGIC 0x69505845 - -/** An image exposed as an EFI file */ -struct efi_file { - /** EFI file protocol */ - EFI_FILE_PROTOCOL file; - /** Image */ - struct image *image; - /** Current file position */ - size_t pos; -}; - -static struct efi_file efi_file_root; - -/** - * Get EFI file name (for debugging) - * - * @v file EFI file - * @ret name Name - */ -static const char * efi_file_name ( struct efi_file *file ) { - - return ( file->image ? file->image->name : "<root>" ); -} - -/** - * Find EFI file image - * - * @v wname Filename - * @ret image Image, or NULL - */ -static struct image * efi_file_find ( const CHAR16 *wname ) { - char name[ wcslen ( wname ) + 1 /* NUL */ ]; - struct image *image; - - /* Find image */ - snprintf ( name, sizeof ( name ), "%ls", wname ); - list_for_each_entry ( image, &images, list ) { - if ( strcasecmp ( image->name, name ) == 0 ) - return image; - } - - return NULL; - -} - -/** - * Open file - * - * @v this EFI file - * @ret new New EFI file - * @v wname Filename - * @v mode File mode - * @v attributes File attributes (for newly-created files) - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new, - CHAR16 *wname, UINT64 mode __unused, - UINT64 attributes __unused ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - struct efi_file *new_file; - struct image *image; - - /* Initial '\' indicates opening from the root directory */ - while ( *wname == L'\\' ) { - file = &efi_file_root; - wname++; - } - - /* Allow root directory itself to be opened */ - if ( ( wname[0] == L'\0' ) || ( wname[0] == L'.' ) ) { - *new = &efi_file_root.file; - return 0; - } - - /* Fail unless opening from the root */ - if ( file->image ) { - DBGC ( file, "EFIFILE %s is not a directory\n", - efi_file_name ( file ) ); - return EFI_NOT_FOUND; - } - - /* Identify image */ - image = efi_file_find ( wname ); - if ( ! image ) { - DBGC ( file, "EFIFILE \"%ls\" does not exist\n", wname ); - return EFI_NOT_FOUND; - } - - /* Fail unless opening read-only */ - if ( mode != EFI_FILE_MODE_READ ) { - DBGC ( file, "EFIFILE %s cannot be opened in mode %#08llx\n", - image->name, mode ); - return EFI_WRITE_PROTECTED; - } - - /* Allocate and initialise file */ - new_file = zalloc ( sizeof ( *new_file ) ); - memcpy ( &new_file->file, &efi_file_root.file, - sizeof ( new_file->file ) ); - new_file->image = image_get ( image ); - *new = &new_file->file; - DBGC ( new_file, "EFIFILE %s opened\n", efi_file_name ( new_file ) ); - - return 0; -} - -/** - * Close file - * - * @v this EFI file - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI efi_file_close ( EFI_FILE_PROTOCOL *this ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - - /* Do nothing if this is the root */ - if ( ! file->image ) - return 0; - - /* Close file */ - DBGC ( file, "EFIFILE %s closed\n", efi_file_name ( file ) ); - image_put ( file->image ); - free ( file ); - - return 0; -} - -/** - * Close and delete file - * - * @v this EFI file - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI efi_file_delete ( EFI_FILE_PROTOCOL *this ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - - DBGC ( file, "EFIFILE %s cannot be deleted\n", efi_file_name ( file ) ); - - /* Close file */ - efi_file_close ( this ); - - /* Warn of failure to delete */ - return EFI_WARN_DELETE_FAILURE; -} - -/** - * Return variable-length data structure - * - * @v base Base data structure (starting with UINT64) - * @v base_len Length of base data structure - * @v name Name to append to base data structure - * @v len Length of data buffer - * @v data Data buffer - * @ret efirc EFI status code - */ -static EFI_STATUS efi_file_varlen ( UINT64 *base, size_t base_len, - const char *name, UINTN *len, VOID *data ) { - size_t name_len; - - /* Calculate structure length */ - name_len = strlen ( name ); - *base = ( base_len + ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) ); - if ( *len < *base ) { - *len = *base; - return EFI_BUFFER_TOO_SMALL; - } - - /* Copy data to buffer */ - *len = *base; - memcpy ( data, base, base_len ); - efi_snprintf ( ( data + base_len ), ( name_len + 1 /* NUL */ ), - "%s", name ); - - return 0; -} - -/** - * Return file information structure - * - * @v image Image, or NULL for the root directory - * @v len Length of data buffer - * @v data Data buffer - * @ret efirc EFI status code - */ -static EFI_STATUS efi_file_info ( struct image *image, UINTN *len, - VOID *data ) { - EFI_FILE_INFO info; - const char *name; - - /* Populate file information */ - memset ( &info, 0, sizeof ( info ) ); - if ( image ) { - info.FileSize = image->len; - info.PhysicalSize = image->len; - info.Attribute = EFI_FILE_READ_ONLY; - name = image->name; - } else { - info.Attribute = ( EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY ); - name = ""; - } - - return efi_file_varlen ( &info.Size, SIZE_OF_EFI_FILE_INFO, name, - len, data ); -} - -/** - * Read directory entry - * - * @v file EFI file - * @v len Length to read - * @v data Data buffer - * @ret efirc EFI status code - */ -static EFI_STATUS efi_file_read_dir ( struct efi_file *file, UINTN *len, - VOID *data ) { - EFI_STATUS efirc; - struct image *image; - unsigned int index; - - /* Construct directory entry at current position */ - index = file->pos; - for_each_image ( image ) { - if ( index-- == 0 ) { - efirc = efi_file_info ( image, len, data ); - if ( efirc == 0 ) - file->pos++; - return efirc; - } - } - - /* No more entries */ - *len = 0; - return 0; -} - -/** - * Read from file - * - * @v this EFI file - * @v len Length to read - * @v data Data buffer - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI efi_file_read ( EFI_FILE_PROTOCOL *this, - UINTN *len, VOID *data ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - size_t remaining; - - /* If this is the root directory, then construct a directory entry */ - if ( ! file->image ) - return efi_file_read_dir ( file, len, data ); - - /* Read from the file */ - remaining = ( file->image->len - file->pos ); - if ( *len > remaining ) - *len = remaining; - DBGC ( file, "EFIFILE %s read [%#08zx,%#08zx)\n", - efi_file_name ( file ), file->pos, - ( ( size_t ) ( file->pos + *len ) ) ); - copy_from_user ( data, file->image->data, file->pos, *len ); - file->pos += *len; - return 0; -} - -/** - * Write to file - * - * @v this EFI file - * @v len Length to write - * @v data Data buffer - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI efi_file_write ( EFI_FILE_PROTOCOL *this, - UINTN *len, VOID *data __unused ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - - DBGC ( file, "EFIFILE %s cannot write [%#08zx, %#08zx)\n", - efi_file_name ( file ), file->pos, - ( ( size_t ) ( file->pos + *len ) ) ); - return EFI_WRITE_PROTECTED; -} - -/** - * Set file position - * - * @v this EFI file - * @v position New file position - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI efi_file_set_position ( EFI_FILE_PROTOCOL *this, - UINT64 position ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - - /* If this is the root directory, reset to the start */ - if ( ! file->image ) { - DBGC ( file, "EFIFILE root directory rewound\n" ); - file->pos = 0; - return 0; - } - - /* Check for the magic end-of-file value */ - if ( position == 0xffffffffffffffffULL ) - position = file->image->len; - - /* Fail if we attempt to seek past the end of the file (since - * we do not support writes). - */ - if ( position > file->image->len ) { - DBGC ( file, "EFIFILE %s cannot seek to %#08llx of %#08zx\n", - efi_file_name ( file ), position, file->image->len ); - return EFI_UNSUPPORTED; - } - - /* Set position */ - file->pos = position; - DBGC ( file, "EFIFILE %s position set to %#08zx\n", - efi_file_name ( file ), file->pos ); - - return 0; -} - -/** - * Get file position - * - * @v this EFI file - * @ret position New file position - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI efi_file_get_position ( EFI_FILE_PROTOCOL *this, - UINT64 *position ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - - *position = file->pos; - return 0; -} - -/** - * Get file information - * - * @v this EFI file - * @v type Type of information - * @v len Buffer size - * @v data Buffer - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI efi_file_get_info ( EFI_FILE_PROTOCOL *this, - EFI_GUID *type, - UINTN *len, VOID *data ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - EFI_FILE_SYSTEM_INFO fsinfo; - struct image *image; - - /* Determine information to return */ - if ( memcmp ( type, &efi_file_info_id, sizeof ( *type ) ) == 0 ) { - - /* Get file information */ - DBGC ( file, "EFIFILE %s get file information\n", - efi_file_name ( file ) ); - return efi_file_info ( file->image, len, data ); - - } else if ( memcmp ( type, &efi_file_system_info_id, - sizeof ( *type ) ) == 0 ) { - - /* Get file system information */ - DBGC ( file, "EFIFILE %s get file system information\n", - efi_file_name ( file ) ); - memset ( &fsinfo, 0, sizeof ( fsinfo ) ); - fsinfo.ReadOnly = 1; - for_each_image ( image ) - fsinfo.VolumeSize += image->len; - return efi_file_varlen ( &fsinfo.Size, - SIZE_OF_EFI_FILE_SYSTEM_INFO, "iPXE", - len, data ); - } else { - - DBGC ( file, "EFIFILE %s cannot get information of type %s\n", - efi_file_name ( file ), efi_guid_ntoa ( type ) ); - return EFI_UNSUPPORTED; - } -} - -/** - * Set file information - * - * @v this EFI file - * @v type Type of information - * @v len Buffer size - * @v data Buffer - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_file_set_info ( EFI_FILE_PROTOCOL *this, EFI_GUID *type, - UINTN len __unused, VOID *data __unused ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - - DBGC ( file, "EFIFILE %s cannot set information of type %s\n", - efi_file_name ( file ), efi_guid_ntoa ( type ) ); - return EFI_WRITE_PROTECTED; -} - -/** - * Flush file modified data - * - * @v this EFI file - * @v type Type of information - * @v len Buffer size - * @v data Buffer - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI efi_file_flush ( EFI_FILE_PROTOCOL *this ) { - struct efi_file *file = container_of ( this, struct efi_file, file ); - - DBGC ( file, "EFIFILE %s flushed\n", efi_file_name ( file ) ); - return 0; -} - -/** Root directory */ -static struct efi_file efi_file_root = { - .file = { - .Revision = EFI_FILE_PROTOCOL_REVISION, - .Open = efi_file_open, - .Close = efi_file_close, - .Delete = efi_file_delete, - .Read = efi_file_read, - .Write = efi_file_write, - .GetPosition = efi_file_get_position, - .SetPosition = efi_file_set_position, - .GetInfo = efi_file_get_info, - .SetInfo = efi_file_set_info, - .Flush = efi_file_flush, - }, - .image = NULL, -}; - -/** - * Open root directory - * - * @v filesystem EFI simple file system - * @ret file EFI file handle - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_file_open_volume ( EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *filesystem __unused, - EFI_FILE_PROTOCOL **file ) { - - DBGC ( &efi_file_root, "EFIFILE open volume\n" ); - *file = &efi_file_root.file; - return 0; -} - -/** EFI simple file system protocol */ -static EFI_SIMPLE_FILE_SYSTEM_PROTOCOL efi_simple_file_system_protocol = { - .Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, - .OpenVolume = efi_file_open_volume, -}; - -/** Dummy block I/O reset */ -static EFI_STATUS EFIAPI -efi_block_io_reset ( EFI_BLOCK_IO_PROTOCOL *this __unused, BOOLEAN extended ) { - - DBGC ( &efi_file_root, "EFIFILE block %sreset\n", - ( extended ? "extended " : "" ) ); - return 0; -} - -/** Dummy block I/O read */ -static EFI_STATUS EFIAPI -efi_block_io_read_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused, UINT32 MediaId, - EFI_LBA lba, UINTN len, VOID *data ) { - - DBGC ( &efi_file_root, "EFIFILE block read ID %#08x LBA %#08llx -> " - "%p+%zx\n", MediaId, ( ( unsigned long long ) lba ), - data, ( ( size_t ) len ) ); - return EFI_NO_MEDIA; -} - -/** Dummy block I/O write */ -static EFI_STATUS EFIAPI -efi_block_io_write_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused, - UINT32 MediaId, EFI_LBA lba, UINTN len, - VOID *data ) { - - DBGC ( &efi_file_root, "EFIFILE block write ID %#08x LBA %#08llx <- " - "%p+%zx\n", MediaId, ( ( unsigned long long ) lba ), - data, ( ( size_t ) len ) ); - return EFI_NO_MEDIA; -} - -/** Dummy block I/O flush */ -static EFI_STATUS EFIAPI -efi_block_io_flush_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused ) { - - DBGC ( &efi_file_root, "EFIFILE block flush\n" ); - return 0; -} - -/** Dummy block I/O media */ -static EFI_BLOCK_IO_MEDIA efi_block_io_media = { - .MediaId = EFI_MEDIA_ID_MAGIC, - .MediaPresent = TRUE, - .ReadOnly = TRUE, - .BlockSize = 1, -}; - -/** Dummy EFI block I/O protocol */ -static EFI_BLOCK_IO_PROTOCOL efi_block_io_protocol = { - .Revision = EFI_BLOCK_IO_PROTOCOL_REVISION, - .Media = &efi_block_io_media, - .Reset = efi_block_io_reset, - .ReadBlocks = efi_block_io_read_blocks, - .WriteBlocks = efi_block_io_write_blocks, - .FlushBlocks = efi_block_io_flush_blocks, -}; - -/** Dummy disk I/O read */ -static EFI_STATUS EFIAPI -efi_disk_io_read_disk ( EFI_DISK_IO_PROTOCOL *this __unused, UINT32 MediaId, - UINT64 offset, UINTN len, VOID *data ) { - - DBGC ( &efi_file_root, "EFIFILE disk read ID %#08x offset %#08llx -> " - "%p+%zx\n", MediaId, ( ( unsigned long long ) offset ), - data, ( ( size_t ) len ) ); - return EFI_NO_MEDIA; -} - -/** Dummy disk I/O write */ -static EFI_STATUS EFIAPI -efi_disk_io_write_disk ( EFI_DISK_IO_PROTOCOL *this __unused, UINT32 MediaId, - UINT64 offset, UINTN len, VOID *data ) { - - DBGC ( &efi_file_root, "EFIFILE disk write ID %#08x offset %#08llx <- " - "%p+%zx\n", MediaId, ( ( unsigned long long ) offset ), - data, ( ( size_t ) len ) ); - return EFI_NO_MEDIA; -} - -/** Dummy EFI disk I/O protocol */ -static EFI_DISK_IO_PROTOCOL efi_disk_io_protocol = { - .Revision = EFI_DISK_IO_PROTOCOL_REVISION, - .ReadDisk = efi_disk_io_read_disk, - .WriteDisk = efi_disk_io_write_disk, -}; - -/** - * Install EFI simple file system protocol - * - * @v handle EFI handle - * @ret rc Return status code - */ -int efi_file_install ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - union { - EFI_DISK_IO_PROTOCOL *diskio; - void *interface; - } diskio; - EFI_STATUS efirc; - int rc; - - /* Install the simple file system protocol, block I/O - * protocol, and disk I/O protocol. We don't have a block - * device, but large parts of the EDK2 codebase make the - * assumption that file systems are normally attached to block - * devices, and so we create a dummy block device on the same - * handle just to keep things looking normal. - */ - if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( - &handle, - &efi_block_io_protocol_guid, - &efi_block_io_protocol, - &efi_disk_io_protocol_guid, - &efi_disk_io_protocol, - &efi_simple_file_system_protocol_guid, - &efi_simple_file_system_protocol, NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( handle, "Could not install simple file system " - "protocols: %s\n", strerror ( rc ) ); - goto err_install; - } - - /* The FAT filesystem driver has a bug: if a block device - * contains no FAT filesystem but does have an - * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL instance, the FAT driver - * will assume that it must have previously installed the - * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. This causes the FAT - * driver to claim control of our device, and to refuse to - * stop driving it, which prevents us from later uninstalling - * correctly. - * - * Work around this bug by opening the disk I/O protocol - * ourselves, thereby preventing the FAT driver from opening - * it. - * - * Note that the alternative approach of opening the block I/O - * protocol (and thereby in theory preventing DiskIo from - * attaching to the block I/O protocol) causes an endless loop - * of calls to our DRIVER_STOP method when starting the EFI - * shell. I have no idea why this is. - */ - if ( ( efirc = bs->OpenProtocol ( handle, &efi_disk_io_protocol_guid, - &diskio.interface, efi_image_handle, - handle, - EFI_OPEN_PROTOCOL_BY_DRIVER ) ) != 0){ - rc = -EEFI ( efirc ); - DBGC ( handle, "Could not open disk I/O protocol: %s\n", - strerror ( rc ) ); - DBGC_EFI_OPENERS ( handle, handle, &efi_disk_io_protocol_guid ); - goto err_open; - } - assert ( diskio.diskio == &efi_disk_io_protocol ); - - return 0; - - bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid, - efi_image_handle, handle ); - err_open: - bs->UninstallMultipleProtocolInterfaces ( - handle, - &efi_simple_file_system_protocol_guid, - &efi_simple_file_system_protocol, - &efi_disk_io_protocol_guid, - &efi_disk_io_protocol, - &efi_block_io_protocol_guid, - &efi_block_io_protocol, NULL ); - err_install: - return rc; -} - -/** - * Uninstall EFI simple file system protocol - * - * @v handle EFI handle - */ -void efi_file_uninstall ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_STATUS efirc; - int rc; - - /* Close our own disk I/O protocol */ - bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid, - efi_image_handle, handle ); - - /* We must install the file system protocol first, since - * otherwise the EDK2 code will attempt to helpfully uninstall - * it when the block I/O protocol is uninstalled, leading to a - * system lock-up. - */ - if ( ( efirc = bs->UninstallMultipleProtocolInterfaces ( - handle, - &efi_simple_file_system_protocol_guid, - &efi_simple_file_system_protocol, - &efi_disk_io_protocol_guid, - &efi_disk_io_protocol, - &efi_block_io_protocol_guid, - &efi_block_io_protocol, NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( handle, "Could not uninstall simple file system " - "protocols: %s\n", strerror ( rc ) ); - /* Oh dear */ - } -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_guid.c b/qemu/roms/ipxe/src/interface/efi/efi_guid.c deleted file mode 100644 index ab1c91e9f..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_guid.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2014 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/efi/efi.h> -#include <ipxe/efi/Protocol/Arp.h> -#include <ipxe/efi/Protocol/BlockIo.h> -#include <ipxe/efi/Protocol/BusSpecificDriverOverride.h> -#include <ipxe/efi/Protocol/ComponentName.h> -#include <ipxe/efi/Protocol/ComponentName2.h> -#include <ipxe/efi/Protocol/DevicePath.h> -#include <ipxe/efi/Protocol/DevicePathToText.h> -#include <ipxe/efi/Protocol/Dhcp4.h> -#include <ipxe/efi/Protocol/DiskIo.h> -#include <ipxe/efi/Protocol/DriverBinding.h> -#include <ipxe/efi/Protocol/GraphicsOutput.h> -#include <ipxe/efi/Protocol/HiiConfigAccess.h> -#include <ipxe/efi/Protocol/Ip4.h> -#include <ipxe/efi/Protocol/Ip4Config.h> -#include <ipxe/efi/Protocol/LoadFile.h> -#include <ipxe/efi/Protocol/LoadFile2.h> -#include <ipxe/efi/Protocol/LoadedImage.h> -#include <ipxe/efi/Protocol/ManagedNetwork.h> -#include <ipxe/efi/Protocol/Mtftp4.h> -#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h> -#include <ipxe/efi/Protocol/PciIo.h> -#include <ipxe/efi/Protocol/PciRootBridgeIo.h> -#include <ipxe/efi/Protocol/PxeBaseCode.h> -#include <ipxe/efi/Protocol/SimpleFileSystem.h> -#include <ipxe/efi/Protocol/SimpleNetwork.h> -#include <ipxe/efi/Protocol/TcgService.h> -#include <ipxe/efi/Protocol/Tcp4.h> -#include <ipxe/efi/Protocol/Udp4.h> -#include <ipxe/efi/Protocol/VlanConfig.h> - -/** @file - * - * EFI GUIDs - * - */ - -/** ARP protocol GUID */ -EFI_GUID efi_arp_protocol_guid - = EFI_ARP_PROTOCOL_GUID; - -/** ARP service binding protocol GUID */ -EFI_GUID efi_arp_service_binding_protocol_guid - = EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID; - -/** Block I/O protocol GUID */ -EFI_GUID efi_block_io_protocol_guid - = EFI_BLOCK_IO_PROTOCOL_GUID; - -/** Bus specific driver override protocol GUID */ -EFI_GUID efi_bus_specific_driver_override_protocol_guid - = EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID; - -/** Component name protocol GUID */ -EFI_GUID efi_component_name_protocol_guid - = EFI_COMPONENT_NAME_PROTOCOL_GUID; - -/** Component name 2 protocol GUID */ -EFI_GUID efi_component_name2_protocol_guid - = EFI_COMPONENT_NAME2_PROTOCOL_GUID; - -/** Device path protocol GUID */ -EFI_GUID efi_device_path_protocol_guid - = EFI_DEVICE_PATH_PROTOCOL_GUID; - -/** DHCPv4 protocol GUID */ -EFI_GUID efi_dhcp4_protocol_guid - = EFI_DHCP4_PROTOCOL_GUID; - -/** DHCPv4 service binding protocol GUID */ -EFI_GUID efi_dhcp4_service_binding_protocol_guid - = EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID; - -/** Disk I/O protocol GUID */ -EFI_GUID efi_disk_io_protocol_guid - = EFI_DISK_IO_PROTOCOL_GUID; - -/** Driver binding protocol GUID */ -EFI_GUID efi_driver_binding_protocol_guid - = EFI_DRIVER_BINDING_PROTOCOL_GUID; - -/** Graphics output protocol GUID */ -EFI_GUID efi_graphics_output_protocol_guid - = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; - -/** HII configuration access protocol GUID */ -EFI_GUID efi_hii_config_access_protocol_guid - = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; - -/** IPv4 protocol GUID */ -EFI_GUID efi_ip4_protocol_guid - = EFI_IP4_PROTOCOL_GUID; - -/** IPv4 configuration protocol GUID */ -EFI_GUID efi_ip4_config_protocol_guid - = EFI_IP4_CONFIG_PROTOCOL_GUID; - -/** IPv4 service binding protocol GUID */ -EFI_GUID efi_ip4_service_binding_protocol_guid - = EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID; - -/** Load file protocol GUID */ -EFI_GUID efi_load_file_protocol_guid - = EFI_LOAD_FILE_PROTOCOL_GUID; - -/** Load file 2 protocol GUID */ -EFI_GUID efi_load_file2_protocol_guid - = EFI_LOAD_FILE2_PROTOCOL_GUID; - -/** Loaded image protocol GUID */ -EFI_GUID efi_loaded_image_protocol_guid - = EFI_LOADED_IMAGE_PROTOCOL_GUID; - -/** Loaded image device path protocol GUID */ -EFI_GUID efi_loaded_image_device_path_protocol_guid - = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID; - -/** Managed network protocol GUID */ -EFI_GUID efi_managed_network_protocol_guid - = EFI_MANAGED_NETWORK_PROTOCOL_GUID; - -/** Managed network service binding protocol GUID */ -EFI_GUID efi_managed_network_service_binding_protocol_guid - = EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID; - -/** MTFTPv4 protocol GUID */ -EFI_GUID efi_mtftp4_protocol_guid - = EFI_MTFTP4_PROTOCOL_GUID; - -/** MTFTPv4 service binding protocol GUID */ -EFI_GUID efi_mtftp4_service_binding_protocol_guid - = EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID; - -/** Network interface identifier protocol GUID (old version) */ -EFI_GUID efi_nii_protocol_guid - = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID; - -/** Network interface identifier protocol GUID (new version) */ -EFI_GUID efi_nii31_protocol_guid - = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31; - -/** PCI I/O protocol GUID */ -EFI_GUID efi_pci_io_protocol_guid - = EFI_PCI_IO_PROTOCOL_GUID; - -/** PCI root bridge I/O protocol GUID */ -EFI_GUID efi_pci_root_bridge_io_protocol_guid - = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; - -/** PXE base code protocol GUID */ -EFI_GUID efi_pxe_base_code_protocol_guid - = EFI_PXE_BASE_CODE_PROTOCOL_GUID; - -/** Simple file system protocol GUID */ -EFI_GUID efi_simple_file_system_protocol_guid - = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; - -/** Simple network protocol GUID */ -EFI_GUID efi_simple_network_protocol_guid - = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; - -/** TCG protocol GUID */ -EFI_GUID efi_tcg_protocol_guid - = EFI_TCG_PROTOCOL_GUID; - -/** TCPv4 protocol GUID */ -EFI_GUID efi_tcp4_protocol_guid - = EFI_TCP4_PROTOCOL_GUID; - -/** TCPv4 service binding protocol GUID */ -EFI_GUID efi_tcp4_service_binding_protocol_guid - = EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID; - -/** UDPv4 protocol GUID */ -EFI_GUID efi_udp4_protocol_guid - = EFI_UDP4_PROTOCOL_GUID; - -/** UDPv4 service binding protocol GUID */ -EFI_GUID efi_udp4_service_binding_protocol_guid - = EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID; - -/** VLAN configuration protocol GUID */ -EFI_GUID efi_vlan_config_protocol_guid - = EFI_VLAN_CONFIG_PROTOCOL_GUID; diff --git a/qemu/roms/ipxe/src/interface/efi/efi_hii.c b/qemu/roms/ipxe/src/interface/efi/efi_hii.c deleted file mode 100644 index 0ea970e67..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_hii.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdlib.h> -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_strings.h> -#include <ipxe/efi/efi_hii.h> - -/** Tiano GUID */ -static const EFI_GUID tiano_guid = EFI_IFR_TIANO_GUID; - -/** - * Add string to IFR builder - * - * @v ifr IFR builder - * @v fmt Format string - * @v ... Arguments - * @ret string_id String identifier, or zero on failure - */ -unsigned int efi_ifr_string ( struct efi_ifr_builder *ifr, const char *fmt, - ... ) { - EFI_HII_STRING_BLOCK *new_strings; - EFI_HII_SIBT_STRING_UCS2_BLOCK *ucs2; - size_t new_strings_len; - va_list args; - size_t len; - unsigned int string_id; - - /* Do nothing if a previous allocation has failed */ - if ( ifr->failed ) - return 0; - - /* Calculate string length */ - va_start ( args, fmt ); - len = ( efi_vsnprintf ( NULL, 0, fmt, args ) + 1 /* wNUL */ ); - va_end ( args ); - - /* Reallocate strings */ - new_strings_len = ( ifr->strings_len + - offsetof ( typeof ( *ucs2 ), StringText ) + - ( len * sizeof ( ucs2->StringText[0] ) ) ); - new_strings = realloc ( ifr->strings, new_strings_len ); - if ( ! new_strings ) { - ifr->failed = 1; - return 0; - } - ucs2 = ( ( ( void * ) new_strings ) + ifr->strings_len ); - ifr->strings = new_strings; - ifr->strings_len = new_strings_len; - - /* Fill in string */ - ucs2->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; - va_start ( args, fmt ); - efi_vsnprintf ( ucs2->StringText, len, fmt, args ); - va_end ( args ); - - /* Allocate string ID */ - string_id = ++(ifr->string_id); - - DBGC ( ifr, "IFR %p string %#04x is \"%ls\"\n", - ifr, string_id, ucs2->StringText ); - return string_id; -} - -/** - * Add IFR opcode to IFR builder - * - * @v ifr IFR builder - * @v opcode Opcode - * @v len Opcode length - * @ret op Opcode, or NULL - */ -static void * efi_ifr_op ( struct efi_ifr_builder *ifr, unsigned int opcode, - size_t len ) { - EFI_IFR_OP_HEADER *new_ops; - EFI_IFR_OP_HEADER *op; - size_t new_ops_len; - - /* Do nothing if a previous allocation has failed */ - if ( ifr->failed ) - return NULL; - - /* Reallocate opcodes */ - new_ops_len = ( ifr->ops_len + len ); - new_ops = realloc ( ifr->ops, new_ops_len ); - if ( ! new_ops ) { - ifr->failed = 1; - return NULL; - } - op = ( ( ( void * ) new_ops ) + ifr->ops_len ); - ifr->ops = new_ops; - ifr->ops_len = new_ops_len; - - /* Fill in opcode header */ - op->OpCode = opcode; - op->Length = len; - - return op; -} - -/** - * Add end opcode to IFR builder - * - * @v ifr IFR builder - */ -void efi_ifr_end_op ( struct efi_ifr_builder *ifr ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_END *end; - - /* Add opcode */ - end = efi_ifr_op ( ifr, EFI_IFR_END_OP, sizeof ( *end ) ); - - DBGC ( ifr, "IFR %p end\n", ifr ); - DBGC2_HDA ( ifr, dispaddr, end, sizeof ( *end ) ); -} - -/** - * Add false opcode to IFR builder - * - * @v ifr IFR builder - */ -void efi_ifr_false_op ( struct efi_ifr_builder *ifr ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_FALSE *false; - - /* Add opcode */ - false = efi_ifr_op ( ifr, EFI_IFR_FALSE_OP, sizeof ( *false ) ); - - DBGC ( ifr, "IFR %p false\n", ifr ); - DBGC2_HDA ( ifr, dispaddr, false, sizeof ( *false ) ); -} - -/** - * Add form opcode to IFR builder - * - * @v ifr IFR builder - * @v title_id Title string identifier - * @ret form_id Form identifier - */ -unsigned int efi_ifr_form_op ( struct efi_ifr_builder *ifr, - unsigned int title_id ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_FORM *form; - - /* Add opcode */ - form = efi_ifr_op ( ifr, EFI_IFR_FORM_OP, sizeof ( *form ) ); - if ( ! form ) - return 0; - form->Header.Scope = 1; - form->FormId = ++(ifr->form_id); - form->FormTitle = title_id; - - DBGC ( ifr, "IFR %p name/value store %#04x title %#04x\n", - ifr, form->FormId, title_id ); - DBGC2_HDA ( ifr, dispaddr, form, sizeof ( *form ) ); - return form->FormId; -} - -/** - * Add formset opcode to IFR builder - * - * @v ifr IFR builder - * @v guid GUID - * @v title_id Title string identifier - * @v help_id Help string identifier - * @v ... Class GUIDs (terminated by NULL) - */ -void efi_ifr_form_set_op ( struct efi_ifr_builder *ifr, const EFI_GUID *guid, - unsigned int title_id, unsigned int help_id, ... ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_FORM_SET *formset; - EFI_GUID *class_guid; - unsigned int num_class_guids = 0; - size_t len; - va_list args; - - /* Count number of class GUIDs */ - va_start ( args, help_id ); - while ( va_arg ( args, const EFI_GUID * ) != NULL ) - num_class_guids++; - va_end ( args ); - - /* Add opcode */ - len = ( sizeof ( *formset ) + - ( num_class_guids * sizeof ( *class_guid ) ) ); - formset = efi_ifr_op ( ifr, EFI_IFR_FORM_SET_OP, len ); - if ( ! formset ) - return; - formset->Header.Scope = 1; - memcpy ( &formset->Guid, guid, sizeof ( formset->Guid ) ); - formset->FormSetTitle = title_id; - formset->Help = help_id; - formset->Flags = num_class_guids; - - /* Add class GUIDs */ - class_guid = ( ( ( void * ) formset ) + sizeof ( *formset ) ); - va_start ( args, help_id ); - while ( num_class_guids-- ) { - memcpy ( class_guid++, va_arg ( args, const EFI_GUID * ), - sizeof ( *class_guid ) ); - } - va_end ( args ); - - DBGC ( ifr, "IFR %p formset title %#04x help %#04x\n", - ifr, title_id, help_id ); - DBGC2_HDA ( ifr, dispaddr, formset, len ); -} - -/** - * Add get opcode to IFR builder - * - * @v ifr IFR builder - * @v varstore_id Variable store identifier - * @v varstore_info Variable string identifier or offset - * @v varstore_type Variable type - */ -void efi_ifr_get_op ( struct efi_ifr_builder *ifr, unsigned int varstore_id, - unsigned int varstore_info, unsigned int varstore_type ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_GET *get; - - /* Add opcode */ - get = efi_ifr_op ( ifr, EFI_IFR_GET_OP, sizeof ( *get ) ); - get->VarStoreId = varstore_id; - get->VarStoreInfo.VarName = varstore_info; - get->VarStoreType = varstore_type; - - DBGC ( ifr, "IFR %p get varstore %#04x:%#04x type %#02x\n", - ifr, varstore_id, varstore_info, varstore_type ); - DBGC2_HDA ( ifr, dispaddr, get, sizeof ( *get ) ); -} - -/** - * Add GUID class opcode to IFR builder - * - * @v ifr IFR builder - * @v class Class - */ -void efi_ifr_guid_class_op ( struct efi_ifr_builder *ifr, unsigned int class ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_GUID_CLASS *guid_class; - - /* Add opcode */ - guid_class = efi_ifr_op ( ifr, EFI_IFR_GUID_OP, - sizeof ( *guid_class ) ); - if ( ! guid_class ) - return; - memcpy ( &guid_class->Guid, &tiano_guid, sizeof ( guid_class->Guid ) ); - guid_class->ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS; - guid_class->Class = class; - - DBGC ( ifr, "IFR %p GUID class %#02x\n", ifr, class ); - DBGC2_HDA ( ifr, dispaddr, guid_class, sizeof ( *guid_class ) ); -} - -/** - * Add GUID subclass opcode to IFR builder - * - * @v ifr IFR builder - * @v subclass Subclass - */ -void efi_ifr_guid_subclass_op ( struct efi_ifr_builder *ifr, - unsigned int subclass ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_GUID_SUBCLASS *guid_subclass; - - /* Add opcode */ - guid_subclass = efi_ifr_op ( ifr, EFI_IFR_GUID_OP, - sizeof ( *guid_subclass ) ); - if ( ! guid_subclass ) - return; - memcpy ( &guid_subclass->Guid, &tiano_guid, - sizeof ( guid_subclass->Guid ) ); - guid_subclass->ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS; - guid_subclass->SubClass = subclass; - - DBGC ( ifr, "IFR %p GUID subclass %#02x\n", ifr, subclass ); - DBGC2_HDA ( ifr, dispaddr, guid_subclass, sizeof ( *guid_subclass ) ); -} - -/** - * Add numeric opcode to IFR builder - * - * @v ifr IFR builder - * @v prompt_id Prompt string identifier - * @v help_id Help string identifier - * @v question_id Question identifier - * @v varstore_id Variable store identifier - * @v varstore_info Variable string identifier or offset - * @v vflags Variable flags - * @v min_value Minimum value - * @v max_value Maximum value - * @v step Step - * @v flags Flags - */ -void efi_ifr_numeric_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, - unsigned int help_id, unsigned int question_id, - unsigned int varstore_id, unsigned int varstore_info, - unsigned int vflags, unsigned long min_value, - unsigned long max_value, unsigned int step, - unsigned int flags ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_NUMERIC *numeric; - unsigned int size; - - /* Add opcode */ - numeric = efi_ifr_op ( ifr, EFI_IFR_NUMERIC_OP, sizeof ( *numeric ) ); - if ( ! numeric ) - return; - numeric->Question.Header.Prompt = prompt_id; - numeric->Question.Header.Help = help_id; - numeric->Question.QuestionId = question_id; - numeric->Question.VarStoreId = varstore_id; - numeric->Question.VarStoreInfo.VarName = varstore_info; - numeric->Question.Flags = vflags; - size = ( flags & EFI_IFR_NUMERIC_SIZE ); - switch ( size ) { - case EFI_IFR_NUMERIC_SIZE_1 : - numeric->data.u8.MinValue = min_value; - numeric->data.u8.MaxValue = max_value; - numeric->data.u8.Step = step; - break; - case EFI_IFR_NUMERIC_SIZE_2 : - numeric->data.u16.MinValue = min_value; - numeric->data.u16.MaxValue = max_value; - numeric->data.u16.Step = step; - break; - case EFI_IFR_NUMERIC_SIZE_4 : - numeric->data.u32.MinValue = min_value; - numeric->data.u32.MaxValue = max_value; - numeric->data.u32.Step = step; - break; - case EFI_IFR_NUMERIC_SIZE_8 : - numeric->data.u64.MinValue = min_value; - numeric->data.u64.MaxValue = max_value; - numeric->data.u64.Step = step; - break; - } - - DBGC ( ifr, "IFR %p numeric prompt %#04x help %#04x question %#04x " - "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id, - varstore_id, varstore_info ); - DBGC2_HDA ( ifr, dispaddr, numeric, sizeof ( *numeric ) ); -} - -/** - * Add string opcode to IFR builder - * - * @v ifr IFR builder - * @v prompt_id Prompt string identifier - * @v help_id Help string identifier - * @v question_id Question identifier - * @v varstore_id Variable store identifier - * @v varstore_info Variable string identifier or offset - * @v vflags Variable flags - * @v min_size Minimum size - * @v max_size Maximum size - * @v flags Flags - */ -void efi_ifr_string_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, - unsigned int help_id, unsigned int question_id, - unsigned int varstore_id, unsigned int varstore_info, - unsigned int vflags, unsigned int min_size, - unsigned int max_size, unsigned int flags ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_STRING *string; - - /* Add opcode */ - string = efi_ifr_op ( ifr, EFI_IFR_STRING_OP, sizeof ( *string ) ); - if ( ! string ) - return; - string->Question.Header.Prompt = prompt_id; - string->Question.Header.Help = help_id; - string->Question.QuestionId = question_id; - string->Question.VarStoreId = varstore_id; - string->Question.VarStoreInfo.VarName = varstore_info; - string->Question.Flags = vflags; - string->MinSize = min_size; - string->MaxSize = max_size; - string->Flags = flags; - - DBGC ( ifr, "IFR %p string prompt %#04x help %#04x question %#04x " - "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id, - varstore_id, varstore_info ); - DBGC2_HDA ( ifr, dispaddr, string, sizeof ( *string ) ); -} - -/** - * Add suppress-if opcode to IFR builder - * - * @v ifr IFR builder - */ -void efi_ifr_suppress_if_op ( struct efi_ifr_builder *ifr ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_SUPPRESS_IF *suppress_if; - - /* Add opcode */ - suppress_if = efi_ifr_op ( ifr, EFI_IFR_SUPPRESS_IF_OP, - sizeof ( *suppress_if ) ); - suppress_if->Header.Scope = 1; - - DBGC ( ifr, "IFR %p suppress-if\n", ifr ); - DBGC2_HDA ( ifr, dispaddr, suppress_if, sizeof ( *suppress_if ) ); -} - -/** - * Add text opcode to IFR builder - * - * @v ifr IFR builder - * @v prompt_id Prompt string identifier - * @v help_id Help string identifier - * @v text_id Text string identifier - */ -void efi_ifr_text_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, - unsigned int help_id, unsigned int text_id ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_TEXT *text; - - /* Add opcode */ - text = efi_ifr_op ( ifr, EFI_IFR_TEXT_OP, sizeof ( *text ) ); - if ( ! text ) - return; - text->Statement.Prompt = prompt_id; - text->Statement.Help = help_id; - text->TextTwo = text_id; - - DBGC ( ifr, "IFR %p text prompt %#04x help %#04x text %#04x\n", - ifr, prompt_id, help_id, text_id ); - DBGC2_HDA ( ifr, dispaddr, text, sizeof ( *text ) ); -} - -/** - * Add true opcode to IFR builder - * - * @v ifr IFR builder - */ -void efi_ifr_true_op ( struct efi_ifr_builder *ifr ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_TRUE *true; - - /* Add opcode */ - true = efi_ifr_op ( ifr, EFI_IFR_TRUE_OP, sizeof ( *true ) ); - - DBGC ( ifr, "IFR %p true\n", ifr ); - DBGC2_HDA ( ifr, dispaddr, true, sizeof ( *true ) ); -} - -/** - * Add name/value store opcode to IFR builder - * - * @v ifr IFR builder - * @v guid GUID - * @ret varstore_id Variable store identifier, or 0 on failure - */ -unsigned int efi_ifr_varstore_name_value_op ( struct efi_ifr_builder *ifr, - const EFI_GUID *guid ) { - size_t dispaddr = ifr->ops_len; - EFI_IFR_VARSTORE_NAME_VALUE *varstore; - - /* Add opcode */ - varstore = efi_ifr_op ( ifr, EFI_IFR_VARSTORE_NAME_VALUE_OP, - sizeof ( *varstore ) ); - if ( ! varstore ) - return 0; - varstore->VarStoreId = ++(ifr->varstore_id); - memcpy ( &varstore->Guid, guid, sizeof ( varstore->Guid ) ); - - DBGC ( ifr, "IFR %p name/value store %#04x\n", - ifr, varstore->VarStoreId ); - DBGC2_HDA ( ifr, dispaddr, varstore, sizeof ( *varstore ) ); - return varstore->VarStoreId; -} - -/** - * Free memory used by IFR builder - * - * @v ifr IFR builder - */ -void efi_ifr_free ( struct efi_ifr_builder *ifr ) { - - free ( ifr->ops ); - free ( ifr->strings ); - memset ( ifr, 0, sizeof ( *ifr ) ); -} - -/** - * Construct package list from IFR builder - * - * @v ifr IFR builder - * @v guid Package GUID - * @v language Language - * @v language_id Language string ID - * @ret package Package list, or NULL - * - * The package list is allocated using malloc(), and must eventually - * be freed by the caller. (The caller must also call efi_ifr_free() - * to free the temporary storage used during construction.) - */ -EFI_HII_PACKAGE_LIST_HEADER * efi_ifr_package ( struct efi_ifr_builder *ifr, - const EFI_GUID *guid, - const char *language, - unsigned int language_id ) { - struct { - EFI_HII_PACKAGE_LIST_HEADER header; - struct { - EFI_HII_PACKAGE_HEADER header; - uint8_t data[ifr->ops_len]; - } __attribute__ (( packed )) ops; - struct { - union { - EFI_HII_STRING_PACKAGE_HDR header; - uint8_t pad[offsetof(EFI_HII_STRING_PACKAGE_HDR, - Language) + - strlen ( language ) + 1 /* NUL */ ]; - } __attribute__ (( packed )) header; - uint8_t data[ifr->strings_len]; - EFI_HII_STRING_BLOCK end; - } __attribute__ (( packed )) strings; - EFI_HII_PACKAGE_HEADER end; - } __attribute__ (( packed )) *package; - - /* Fail if any previous allocation failed */ - if ( ifr->failed ) - return NULL; - - /* Allocate package list */ - package = zalloc ( sizeof ( *package ) ); - if ( ! package ) - return NULL; - - /* Populate package list */ - package->header.PackageLength = sizeof ( *package ); - memcpy ( &package->header.PackageListGuid, guid, - sizeof ( package->header.PackageListGuid ) ); - package->ops.header.Length = sizeof ( package->ops ); - package->ops.header.Type = EFI_HII_PACKAGE_FORMS; - memcpy ( package->ops.data, ifr->ops, sizeof ( package->ops.data ) ); - package->strings.header.header.Header.Length = - sizeof ( package->strings ); - package->strings.header.header.Header.Type = - EFI_HII_PACKAGE_STRINGS; - package->strings.header.header.HdrSize = - sizeof ( package->strings.header ); - package->strings.header.header.StringInfoOffset = - sizeof ( package->strings.header ); - package->strings.header.header.LanguageName = language_id; - strcpy ( package->strings.header.header.Language, language ); - memcpy ( package->strings.data, ifr->strings, - sizeof ( package->strings.data ) ); - package->strings.end.BlockType = EFI_HII_SIBT_END; - package->end.Type = EFI_HII_PACKAGE_END; - package->end.Length = sizeof ( package->end ); - - return &package->header; -} - diff --git a/qemu/roms/ipxe/src/interface/efi/efi_init.c b/qemu/roms/ipxe/src/interface/efi/efi_init.c deleted file mode 100644 index 93ada21d4..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_init.c +++ /dev/null @@ -1,226 +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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <string.h> -#include <errno.h> -#include <ipxe/init.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_driver.h> -#include <ipxe/efi/Protocol/LoadedImage.h> - -/** Image handle passed to entry point */ -EFI_HANDLE efi_image_handle; - -/** Loaded image protocol for this image */ -EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; - -/** System table passed to entry point */ -EFI_SYSTEM_TABLE *efi_systab; - -/** Event used to signal shutdown */ -static EFI_EVENT efi_shutdown_event; - -/* Forward declarations */ -static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle ); - -/** - * Shut down in preparation for booting an OS. - * - * This hook gets called at ExitBootServices time in order to make - * sure that everything is properly shut down before the OS takes - * over. - */ -static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused, - void *context __unused ) { - shutdown_boot(); -} - -/** - * Look up EFI configuration table - * - * @v guid Configuration table GUID - * @ret table Configuration table, or NULL - */ -static void * efi_find_table ( EFI_GUID *guid ) { - unsigned int i; - - for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) { - if ( memcmp ( &efi_systab->ConfigurationTable[i].VendorGuid, - guid, sizeof ( *guid ) ) == 0 ) - return efi_systab->ConfigurationTable[i].VendorTable; - } - - return NULL; -} - -/** - * Initialise EFI environment - * - * @v image_handle Image handle - * @v systab System table - * @ret efirc EFI return status code - */ -EFI_STATUS efi_init ( EFI_HANDLE image_handle, - EFI_SYSTEM_TABLE *systab ) { - EFI_BOOT_SERVICES *bs; - struct efi_protocol *prot; - struct efi_config_table *tab; - void *loaded_image; - EFI_STATUS efirc; - int rc; - - /* Store image handle and system table pointer for future use */ - efi_image_handle = image_handle; - efi_systab = systab; - - /* Sanity checks */ - if ( ! systab ) { - efirc = EFI_NOT_AVAILABLE_YET; - goto err_sanity; - } - if ( ! systab->ConOut ) { - efirc = EFI_NOT_AVAILABLE_YET; - goto err_sanity; - } - if ( ! systab->BootServices ) { - DBGC ( systab, "EFI provided no BootServices entry point\n" ); - efirc = EFI_NOT_AVAILABLE_YET; - goto err_sanity; - } - if ( ! systab->RuntimeServices ) { - DBGC ( systab, "EFI provided no RuntimeServices entry " - "point\n" ); - efirc = EFI_NOT_AVAILABLE_YET; - goto err_sanity; - } - DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab ); - bs = systab->BootServices; - - /* Look up used protocols */ - for_each_table_entry ( prot, EFI_PROTOCOLS ) { - if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL, - prot->protocol ) ) == 0 ) { - DBGC ( systab, "EFI protocol %s is at %p\n", - efi_guid_ntoa ( &prot->guid ), - *(prot->protocol) ); - } else { - DBGC ( systab, "EFI does not provide protocol %s\n", - efi_guid_ntoa ( &prot->guid ) ); - /* Fail if protocol is required */ - if ( prot->required ) - goto err_missing_protocol; - } - } - - /* Look up used configuration tables */ - for_each_table_entry ( tab, EFI_CONFIG_TABLES ) { - if ( ( *(tab->table) = efi_find_table ( &tab->guid ) ) ) { - DBGC ( systab, "EFI configuration table %s is at %p\n", - efi_guid_ntoa ( &tab->guid ), *(tab->table) ); - } else { - DBGC ( systab, "EFI does not provide configuration " - "table %s\n", efi_guid_ntoa ( &tab->guid ) ); - if ( tab->required ) { - efirc = EFI_NOT_AVAILABLE_YET; - goto err_missing_table; - } - } - } - - /* Get loaded image protocol */ - if ( ( efirc = bs->OpenProtocol ( image_handle, - &efi_loaded_image_protocol_guid, - &loaded_image, image_handle, NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( systab, "EFI could not get loaded image protocol: %s", - strerror ( rc ) ); - goto err_no_loaded_image; - } - efi_loaded_image = loaded_image; - DBGC ( systab, "EFI image base address %p\n", - efi_loaded_image->ImageBase ); - - /* EFI is perfectly capable of gracefully shutting down any - * loaded devices if it decides to fall back to a legacy boot. - * For no particularly comprehensible reason, it doesn't - * bother doing so when ExitBootServices() is called. - */ - if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES, - TPL_CALLBACK, efi_shutdown_hook, - NULL, &efi_shutdown_event ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( systab, "EFI could not create ExitBootServices event: " - "%s\n", strerror ( rc ) ); - goto err_create_event; - } - - /* Install driver binding protocol */ - if ( ( rc = efi_driver_install() ) != 0 ) { - DBGC ( systab, "EFI could not install driver: %s\n", - strerror ( rc ) ); - efirc = EFIRC ( rc ); - goto err_driver_install; - } - - /* Install image unload method */ - efi_loaded_image->Unload = efi_unload; - - return 0; - - efi_driver_uninstall(); - err_driver_install: - bs->CloseEvent ( efi_shutdown_event ); - err_create_event: - err_no_loaded_image: - err_missing_table: - err_missing_protocol: - err_sanity: - return efirc; -} - -/** - * Shut down EFI environment - * - * @v image_handle Image handle - */ -static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_SYSTEM_TABLE *systab = efi_systab; - - DBGC ( systab, "EFI image unloading\n" ); - - /* Shut down */ - shutdown_exit(); - - /* Disconnect any remaining devices */ - efi_driver_disconnect_all(); - - /* Uninstall driver binding protocol */ - efi_driver_uninstall(); - - /* Uninstall exit boot services event */ - bs->CloseEvent ( efi_shutdown_event ); - - DBGC ( systab, "EFI image unloaded\n" ); - - return 0; -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_pci.c b/qemu/roms/ipxe/src/interface/efi/efi_pci.c deleted file mode 100644 index 97ea72bb9..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_pci.c +++ /dev/null @@ -1,361 +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 <stdlib.h> -#include <errno.h> -#include <ipxe/pci.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_pci.h> -#include <ipxe/efi/efi_driver.h> -#include <ipxe/efi/Protocol/PciIo.h> -#include <ipxe/efi/Protocol/PciRootBridgeIo.h> - -/** @file - * - * iPXE PCI I/O API for EFI - * - */ - -/* Disambiguate the various error causes */ -#define EINFO_EEFI_PCI \ - __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ - "Could not open PCI I/O protocol" ) -#define EINFO_EEFI_PCI_NOT_PCI \ - __einfo_platformify ( EINFO_EEFI_PCI, EFI_UNSUPPORTED, \ - "Not a PCI device" ) -#define EEFI_PCI_NOT_PCI __einfo_error ( EINFO_EEFI_PCI_NOT_PCI ) -#define EINFO_EEFI_PCI_IN_USE \ - __einfo_platformify ( EINFO_EEFI_PCI, EFI_ACCESS_DENIED, \ - "PCI device already has a driver" ) -#define EEFI_PCI_IN_USE __einfo_error ( EINFO_EEFI_PCI_IN_USE ) -#define EEFI_PCI( efirc ) \ - EPLATFORM ( EINFO_EEFI_PCI, efirc, \ - EEFI_PCI_NOT_PCI, EEFI_PCI_IN_USE ) - -/****************************************************************************** - * - * iPXE PCI API - * - ****************************************************************************** - */ - -/** PCI root bridge I/O protocol */ -static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *efipci; -EFI_REQUEST_PROTOCOL ( EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, &efipci ); - -static unsigned long efipci_address ( struct pci_device *pci, - unsigned long location ) { - return EFI_PCI_ADDRESS ( PCI_BUS ( pci->busdevfn ), - PCI_SLOT ( pci->busdevfn ), - PCI_FUNC ( pci->busdevfn ), - EFIPCI_OFFSET ( location ) ); -} - -int efipci_read ( struct pci_device *pci, unsigned long location, - void *value ) { - EFI_STATUS efirc; - int rc; - - if ( ! efipci ) - return -ENOTSUP; - - if ( ( efirc = efipci->Pci.Read ( efipci, EFIPCI_WIDTH ( location ), - efipci_address ( pci, location ), 1, - value ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBG ( "EFIPCI config read from " PCI_FMT " offset %02lx " - "failed: %s\n", PCI_ARGS ( pci ), - EFIPCI_OFFSET ( location ), strerror ( rc ) ); - return -EIO; - } - - return 0; -} - -int efipci_write ( struct pci_device *pci, unsigned long location, - unsigned long value ) { - EFI_STATUS efirc; - int rc; - - if ( ! efipci ) - return -ENOTSUP; - - if ( ( efirc = efipci->Pci.Write ( efipci, EFIPCI_WIDTH ( location ), - efipci_address ( pci, location ), 1, - &value ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBG ( "EFIPCI config write to " PCI_FMT " offset %02lx " - "failed: %s\n", PCI_ARGS ( pci ), - EFIPCI_OFFSET ( location ), strerror ( rc ) ); - return -EIO; - } - - return 0; -} - -PROVIDE_PCIAPI_INLINE ( efi, pci_num_bus ); -PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte ); -PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word ); -PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_dword ); -PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte ); -PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word ); -PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_dword ); - -/****************************************************************************** - * - * EFI PCI device instantiation - * - ****************************************************************************** - */ - -/** - * Open EFI PCI device - * - * @v device EFI device handle - * @v attributes Protocol opening attributes - * @v pci PCI device to fill in - * @ret rc Return status code - */ -int efipci_open ( EFI_HANDLE device, UINT32 attributes, - struct pci_device *pci ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - union { - EFI_PCI_IO_PROTOCOL *pci_io; - void *interface; - } pci_io; - UINTN pci_segment, pci_bus, pci_dev, pci_fn; - EFI_STATUS efirc; - int rc; - - /* See if device is a PCI device */ - if ( ( efirc = bs->OpenProtocol ( device, &efi_pci_io_protocol_guid, - &pci_io.interface, efi_image_handle, - device, attributes ) ) != 0 ) { - rc = -EEFI_PCI ( efirc ); - DBGCP ( device, "EFIPCI %p %s cannot open PCI protocols: %s\n", - device, efi_handle_name ( device ), strerror ( rc ) ); - goto err_open_protocol; - } - - /* Get PCI bus:dev.fn address */ - if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io, &pci_segment, - &pci_bus, &pci_dev, - &pci_fn ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( device, "EFIPCI %p %s could not get PCI location: %s\n", - device, efi_handle_name ( device ), strerror ( rc ) ); - goto err_get_location; - } - DBGC2 ( device, "EFIPCI %p %s is PCI %04lx:%02lx:%02lx.%lx\n", device, - efi_handle_name ( device ), ( ( unsigned long ) pci_segment ), - ( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ), - ( ( unsigned long ) pci_fn ) ); - - /* Try to enable I/O cycles, memory cycles, and bus mastering. - * Some platforms will 'helpfully' report errors if these bits - * can't be enabled (for example, if the card doesn't actually - * support I/O cycles). Work around any such platforms by - * enabling bits individually and simply ignoring any errors. - */ - pci_io.pci_io->Attributes ( pci_io.pci_io, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_IO, NULL ); - pci_io.pci_io->Attributes ( pci_io.pci_io, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL ); - pci_io.pci_io->Attributes ( pci_io.pci_io, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL ); - - /* Populate PCI device */ - pci_init ( pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) ); - if ( ( rc = pci_read_config ( pci ) ) != 0 ) { - DBGC ( device, "EFIPCI %p %s cannot read PCI configuration: " - "%s\n", device, efi_handle_name ( device ), - strerror ( rc ) ); - goto err_pci_read_config; - } - - return 0; - - err_pci_read_config: - err_get_location: - bs->CloseProtocol ( device, &efi_pci_io_protocol_guid, - efi_image_handle, device ); - err_open_protocol: - return rc; -} - -/** - * Close EFI PCI device - * - * @v device EFI device handle - */ -void efipci_close ( EFI_HANDLE device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - bs->CloseProtocol ( device, &efi_pci_io_protocol_guid, - efi_image_handle, device ); -} - -/** - * Get EFI PCI device information - * - * @v device EFI device handle - * @v pci PCI device to fill in - * @ret rc Return status code - */ -int efipci_info ( EFI_HANDLE device, struct pci_device *pci ) { - int rc; - - /* Open PCI device, if possible */ - if ( ( rc = efipci_open ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL, - pci ) ) != 0 ) - return rc; - - /* Close PCI device */ - efipci_close ( device ); - - return 0; -} - -/****************************************************************************** - * - * EFI PCI driver - * - ****************************************************************************** - */ - -/** - * Check to see if driver supports a device - * - * @v device EFI device handle - * @ret rc Return status code - */ -static int efipci_supported ( EFI_HANDLE device ) { - struct pci_device pci; - int rc; - - /* Get PCI device information */ - if ( ( rc = efipci_info ( device, &pci ) ) != 0 ) - return rc; - - /* Look for a driver */ - if ( ( rc = pci_find_driver ( &pci ) ) != 0 ) { - DBGCP ( device, "EFIPCI %p %s has no driver\n", - device, efi_handle_name ( device ) ); - return rc; - } - DBGC ( device, "EFIPCI %p %s has driver \"%s\"\n", - device, efi_handle_name ( device ), pci.id->name ); - - return 0; -} - -/** - * Attach driver to device - * - * @v efidev EFI device - * @ret rc Return status code - */ -static int efipci_start ( struct efi_device *efidev ) { - EFI_HANDLE device = efidev->device; - struct pci_device *pci; - int rc; - - /* Allocate PCI device */ - pci = zalloc ( sizeof ( *pci ) ); - if ( ! pci ) { - rc = -ENOMEM; - goto err_alloc; - } - - /* Open PCI device */ - if ( ( rc = efipci_open ( device, ( EFI_OPEN_PROTOCOL_BY_DRIVER | - EFI_OPEN_PROTOCOL_EXCLUSIVE ), - pci ) ) != 0 ) { - DBGC ( device, "EFIPCI %p %s could not open PCI device: %s\n", - device, efi_handle_name ( device ), strerror ( rc ) ); - DBGC_EFI_OPENERS ( device, device, &efi_pci_io_protocol_guid ); - goto err_open; - } - - /* Find driver */ - if ( ( rc = pci_find_driver ( pci ) ) != 0 ) { - DBGC ( device, "EFIPCI %p %s has no driver\n", - device, efi_handle_name ( device ) ); - goto err_find_driver; - } - - /* Mark PCI device as a child of the EFI device */ - pci->dev.parent = &efidev->dev; - list_add ( &pci->dev.siblings, &efidev->dev.children ); - - /* Probe driver */ - if ( ( rc = pci_probe ( pci ) ) != 0 ) { - DBGC ( device, "EFIPCI %p %s could not probe driver \"%s\": " - "%s\n", device, efi_handle_name ( device ), - pci->id->name, strerror ( rc ) ); - goto err_probe; - } - DBGC ( device, "EFIPCI %p %s using driver \"%s\"\n", - device, efi_handle_name ( device ), pci->id->name ); - - efidev_set_drvdata ( efidev, pci ); - return 0; - - pci_remove ( pci ); - err_probe: - list_del ( &pci->dev.siblings ); - err_find_driver: - efipci_close ( device ); - err_open: - free ( pci ); - err_alloc: - return rc; -} - -/** - * Detach driver from device - * - * @v efidev EFI device - */ -static void efipci_stop ( struct efi_device *efidev ) { - struct pci_device *pci = efidev_get_drvdata ( efidev ); - EFI_HANDLE device = efidev->device; - - pci_remove ( pci ); - list_del ( &pci->dev.siblings ); - efipci_close ( device ); - free ( pci ); -} - -/** EFI PCI driver */ -struct efi_driver efipci_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { - .name = "PCI", - .supported = efipci_supported, - .start = efipci_start, - .stop = efipci_stop, -}; diff --git a/qemu/roms/ipxe/src/interface/efi/efi_reboot.c b/qemu/roms/ipxe/src/interface/efi/efi_reboot.c deleted file mode 100644 index 35919221e..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_reboot.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - * - * 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 - * - * EFI reboot mechanism - * - */ - -#include <errno.h> -#include <ipxe/efi/efi.h> -#include <ipxe/reboot.h> - -/** - * Reboot system - * - * @v warm Perform a warm reboot - */ -static void efi_reboot ( int warm ) { - EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices; - - /* Use runtime services to reset system */ - rs->ResetSystem ( ( warm ? EfiResetWarm : EfiResetCold ), 0, 0, NULL ); -} - -/** - * Power off system - * - * @ret rc Return status code - */ -static int efi_poweroff ( void ) { - EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices; - - /* Use runtime services to power off system */ - rs->ResetSystem ( EfiResetShutdown, 0, 0, NULL ); - - /* Should never happen */ - return -ECANCELED; -} - -PROVIDE_REBOOT ( efi, reboot, efi_reboot ); -PROVIDE_REBOOT ( efi, poweroff, efi_poweroff ); diff --git a/qemu/roms/ipxe/src/interface/efi/efi_smbios.c b/qemu/roms/ipxe/src/interface/efi/efi_smbios.c deleted file mode 100644 index 304f95a56..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_smbios.c +++ /dev/null @@ -1,67 +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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <errno.h> -#include <ipxe/smbios.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/Guid/SmBios.h> - -/** @file - * - * iPXE SMBIOS API for EFI - * - */ - -/** SMBIOS configuration table */ -static struct smbios_entry *smbios_entry; -EFI_USE_TABLE ( SMBIOS_TABLE, &smbios_entry, 0 ); - -/** - * Find SMBIOS - * - * @v smbios SMBIOS entry point descriptor structure to fill in - * @ret rc Return status code - */ -static int efi_find_smbios ( struct smbios *smbios ) { - - if ( ! smbios_entry ) { - DBG ( "No SMBIOS table provided\n" ); - return -ENODEV; - } - - if ( smbios_entry->signature != SMBIOS_SIGNATURE ) { - DBG ( "Invalid SMBIOS signature\n" ); - return -ENODEV; - } - - smbios->address = phys_to_user ( smbios_entry->smbios_address ); - smbios->len = smbios_entry->smbios_len; - smbios->count = smbios_entry->smbios_count; - smbios->version = - SMBIOS_VERSION ( smbios_entry->major, smbios_entry->minor ); - DBG ( "Found SMBIOS v%d.%d entry point at %p (%x+%zx)\n", - smbios_entry->major, smbios_entry->minor, smbios_entry, - smbios_entry->smbios_address, smbios->len ); - - return 0; -} - -PROVIDE_SMBIOS ( efi, find_smbios, efi_find_smbios ); diff --git a/qemu/roms/ipxe/src/interface/efi/efi_snp.c b/qemu/roms/ipxe/src/interface/efi/efi_snp.c deleted file mode 100644 index 3dfcc5e16..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_snp.c +++ /dev/null @@ -1,1248 +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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <byteswap.h> -#include <ipxe/netdevice.h> -#include <ipxe/iobuf.h> -#include <ipxe/in.h> -#include <ipxe/version.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_driver.h> -#include <ipxe/efi/efi_strings.h> -#include <ipxe/efi/efi_utils.h> -#include <ipxe/efi/efi_watchdog.h> -#include <ipxe/efi/efi_snp.h> -#include <usr/autoboot.h> -#include <config/general.h> - -/** List of SNP devices */ -static LIST_HEAD ( efi_snp_devices ); - -/** Network devices are currently claimed for use by iPXE */ -static int efi_snp_claimed; - -/* Downgrade user experience if configured to do so - * - * The default UEFI user experience for network boot is somewhat - * excremental: only TFTP is available as a download protocol, and if - * anything goes wrong the user will be shown just a dot on an - * otherwise blank screen. (Some programmer was clearly determined to - * win a bet that they could outshine Apple at producing uninformative - * error messages.) - * - * For comparison, the default iPXE user experience provides the - * option to use protocols designed more recently than 1980 (such as - * HTTP and iSCSI), and if anything goes wrong the the user will be - * shown one of over 1200 different error messages, complete with a - * link to a wiki page describing that specific error. - * - * We default to upgrading the user experience to match that available - * in a "legacy" BIOS environment, by installing our own instance of - * EFI_LOAD_FILE_PROTOCOL. - * - * Note that unfortunately we can't sensibly provide the choice of - * both options to the user in the same build, because the UEFI boot - * menu ignores the multitude of ways in which a network device handle - * can be described and opaquely labels both menu entries as just "EFI - * Network". - */ -#ifdef EFI_DOWNGRADE_UX -static EFI_GUID dummy_load_file_protocol_guid = { - 0x6f6c7323, 0x2077, 0x7523, - { 0x6e, 0x68, 0x65, 0x6c, 0x70, 0x66, 0x75, 0x6c } -}; -#define efi_load_file_protocol_guid dummy_load_file_protocol_guid -#endif - -/** - * Set EFI SNP mode state - * - * @v snp SNP interface - */ -static void efi_snp_set_state ( struct efi_snp_device *snpdev ) { - struct net_device *netdev = snpdev->netdev; - EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode; - - /* Calculate state */ - if ( ! snpdev->started ) { - /* Start() method not called; report as Stopped */ - mode->State = EfiSimpleNetworkStopped; - } else if ( ! netdev_is_open ( netdev ) ) { - /* Network device not opened; report as Started */ - mode->State = EfiSimpleNetworkStarted; - } else if ( efi_snp_claimed ) { - /* Network device opened but claimed for use by iPXE; report - * as Started to inhibit receive polling. - */ - mode->State = EfiSimpleNetworkStarted; - } else { - /* Network device opened and available for use via SNP; report - * as Initialized. - */ - mode->State = EfiSimpleNetworkInitialized; - } -} - -/** - * Set EFI SNP mode based on iPXE net device parameters - * - * @v snp SNP interface - */ -static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) { - struct net_device *netdev = snpdev->netdev; - EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode; - struct ll_protocol *ll_protocol = netdev->ll_protocol; - unsigned int ll_addr_len = ll_protocol->ll_addr_len; - - mode->HwAddressSize = ll_addr_len; - mode->MediaHeaderSize = ll_protocol->ll_header_len; - mode->MaxPacketSize = netdev->max_pkt_len; - mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | - EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | - EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ); - assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) ); - memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len ); - memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len ); - ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress ); - mode->IfType = ntohs ( ll_protocol->ll_proto ); - mode->MacAddressChangeable = TRUE; - mode->MediaPresentSupported = TRUE; - mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE ); -} - -/** - * Flush transmit ring and receive queue - * - * @v snpdev SNP device - */ -static void efi_snp_flush ( struct efi_snp_device *snpdev ) { - struct io_buffer *iobuf; - struct io_buffer *tmp; - - /* Reset transmit completion ring */ - snpdev->tx_prod = 0; - snpdev->tx_cons = 0; - - /* Discard any queued receive buffers */ - list_for_each_entry_safe ( iobuf, tmp, &snpdev->rx, list ) { - list_del ( &iobuf->list ); - free_iob ( iobuf ); - } -} - -/** - * Poll net device and count received packets - * - * @v snpdev SNP device - */ -static void efi_snp_poll ( struct efi_snp_device *snpdev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct io_buffer *iobuf; - - /* Poll network device */ - netdev_poll ( snpdev->netdev ); - - /* Retrieve any received packets */ - while ( ( iobuf = netdev_rx_dequeue ( snpdev->netdev ) ) ) { - list_add_tail ( &iobuf->list, &snpdev->rx ); - snpdev->interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; - bs->SignalEvent ( &snpdev->snp.WaitForPacket ); - } -} - -/** - * Change SNP state from "stopped" to "started" - * - * @v snp SNP interface - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - - DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - snpdev->started = 1; - efi_snp_set_state ( snpdev ); - return 0; -} - -/** - * Change SNP state from "started" to "stopped" - * - * @v snp SNP interface - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - - DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - snpdev->started = 0; - efi_snp_set_state ( snpdev ); - return 0; -} - -/** - * Open the network device - * - * @v snp SNP interface - * @v extra_rx_bufsize Extra RX buffer size, in bytes - * @v extra_tx_bufsize Extra TX buffer size, in bytes - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, - UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - int rc; - - DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n", - snpdev, ( ( unsigned long ) extra_rx_bufsize ), - ( ( unsigned long ) extra_tx_bufsize ) ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { - DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n", - snpdev, snpdev->netdev->name, strerror ( rc ) ); - return EFIRC ( rc ); - } - efi_snp_set_state ( snpdev ); - - return 0; -} - -/** - * Reset the network device - * - * @v snp SNP interface - * @v ext_verify Extended verification required - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - int rc; - - DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n", - snpdev, ( ext_verify ? "with" : "without" ) ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - netdev_close ( snpdev->netdev ); - efi_snp_set_state ( snpdev ); - efi_snp_flush ( snpdev ); - - if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { - DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n", - snpdev, snpdev->netdev->name, strerror ( rc ) ); - return EFIRC ( rc ); - } - efi_snp_set_state ( snpdev ); - - return 0; -} - -/** - * Shut down the network device - * - * @v snp SNP interface - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - - DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - netdev_close ( snpdev->netdev ); - efi_snp_set_state ( snpdev ); - efi_snp_flush ( snpdev ); - - return 0; -} - -/** - * Manage receive filters - * - * @v snp SNP interface - * @v enable Receive filters to enable - * @v disable Receive filters to disable - * @v mcast_reset Reset multicast filters - * @v mcast_count Number of multicast filters - * @v mcast Multicast filters - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable, - UINT32 disable, BOOLEAN mcast_reset, - UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - unsigned int i; - - DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n", - snpdev, enable, disable, ( mcast_reset ? " reset" : "" ), - ( ( unsigned long ) mcast_count ) ); - for ( i = 0 ; i < mcast_count ; i++ ) { - DBGC2_HDA ( snpdev, i, &mcast[i], - snpdev->netdev->ll_protocol->ll_addr_len ); - } - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - /* Lie through our teeth, otherwise MNP refuses to accept us */ - return 0; -} - -/** - * Set station address - * - * @v snp SNP interface - * @v reset Reset to permanent address - * @v new New station address - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, - EFI_MAC_ADDRESS *new ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; - - DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev, - ( reset ? "reset" : ll_protocol->ntoa ( new ) ) ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - /* Set the MAC address */ - if ( reset ) - new = &snpdev->mode.PermanentAddress; - memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len ); - - /* MAC address changes take effect only on netdev_open() */ - if ( netdev_is_open ( snpdev->netdev ) ) { - DBGC ( snpdev, "SNPDEV %p MAC address changed while net " - "device open\n", snpdev ); - } - - return 0; -} - -/** - * Get (or reset) statistics - * - * @v snp SNP interface - * @v reset Reset statistics - * @v stats_len Size of statistics table - * @v stats Statistics table - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, - UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - EFI_NETWORK_STATISTICS stats_buf; - - DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev, - ( reset ? " reset" : "" ) ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - /* Gather statistics */ - memset ( &stats_buf, 0, sizeof ( stats_buf ) ); - stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good; - stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad; - stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good + - snpdev->netdev->tx_stats.bad ); - stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good; - stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad; - stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good + - snpdev->netdev->rx_stats.bad ); - if ( *stats_len > sizeof ( stats_buf ) ) - *stats_len = sizeof ( stats_buf ); - if ( stats ) - memcpy ( stats, &stats_buf, *stats_len ); - - /* Reset statistics if requested to do so */ - if ( reset ) { - memset ( &snpdev->netdev->tx_stats, 0, - sizeof ( snpdev->netdev->tx_stats ) ); - memset ( &snpdev->netdev->rx_stats, 0, - sizeof ( snpdev->netdev->rx_stats ) ); - } - - return 0; -} - -/** - * Convert multicast IP address to MAC address - * - * @v snp SNP interface - * @v ipv6 Address is IPv6 - * @v ip IP address - * @v mac MAC address - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6, - EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; - const char *ip_str; - int rc; - - ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ : - inet_ntoa ( *( ( struct in_addr * ) ip ) ) ); - DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - /* Try to hash the address */ - if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ), - ip, mac ) ) != 0 ) { - DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n", - snpdev, ip_str, strerror ( rc ) ); - return EFIRC ( rc ); - } - - return 0; -} - -/** - * Read or write non-volatile storage - * - * @v snp SNP interface - * @v read Operation is a read - * @v offset Starting offset within NVRAM - * @v len Length of data buffer - * @v data Data buffer - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read, - UINTN offset, UINTN len, VOID *data ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - - DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev, - ( read ? "read" : "write" ), ( ( unsigned long ) offset ), - ( ( unsigned long ) len ) ); - if ( ! read ) - DBGC2_HDA ( snpdev, offset, data, len ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - return EFI_UNSUPPORTED; -} - -/** - * Read interrupt status and TX recycled buffer status - * - * @v snp SNP interface - * @v interrupts Interrupt status, or NULL - * @v txbuf Recycled transmit buffer address, or NULL - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, - UINT32 *interrupts, VOID **txbuf ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - - DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) { - DBGC2 ( snpdev, "\n" ); - return EFI_NOT_READY; - } - - /* Poll the network device */ - efi_snp_poll ( snpdev ); - - /* Interrupt status. In practice, this seems to be used only - * to detect TX completions. - */ - if ( interrupts ) { - *interrupts = snpdev->interrupts; - DBGC2 ( snpdev, " INTS:%02x", *interrupts ); - snpdev->interrupts = 0; - } - - /* TX completions */ - if ( txbuf ) { - if ( snpdev->tx_prod != snpdev->tx_cons ) { - *txbuf = snpdev->tx[snpdev->tx_cons++ % EFI_SNP_NUM_TX]; - } else { - *txbuf = NULL; - } - DBGC2 ( snpdev, " TX:%p", *txbuf ); - } - - DBGC2 ( snpdev, "\n" ); - return 0; -} - -/** - * Start packet transmission - * - * @v snp SNP interface - * @v ll_header_len Link-layer header length, if to be filled in - * @v len Length of data buffer - * @v data Data buffer - * @v ll_src Link-layer source address, if specified - * @v ll_dest Link-layer destination address, if specified - * @v net_proto Network-layer protocol (in host order) - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, - UINTN ll_header_len, UINTN len, VOID *data, - EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest, - UINT16 *net_proto ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; - struct io_buffer *iobuf; - size_t payload_len; - unsigned int tx_fill; - int rc; - - DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data, - ( ( unsigned long ) len ) ); - if ( ll_header_len ) { - if ( ll_src ) { - DBGC2 ( snpdev, " src %s", - ll_protocol->ntoa ( ll_src ) ); - } - if ( ll_dest ) { - DBGC2 ( snpdev, " dest %s", - ll_protocol->ntoa ( ll_dest ) ); - } - if ( net_proto ) { - DBGC2 ( snpdev, " proto %04x", *net_proto ); - } - } - DBGC2 ( snpdev, "\n" ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - /* Sanity checks */ - if ( ll_header_len ) { - if ( ll_header_len != ll_protocol->ll_header_len ) { - DBGC ( snpdev, "SNPDEV %p TX invalid header length " - "%ld\n", snpdev, - ( ( unsigned long ) ll_header_len ) ); - rc = -EINVAL; - goto err_sanity; - } - if ( len < ll_header_len ) { - DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n", - snpdev, ( ( unsigned long ) len ) ); - rc = -EINVAL; - goto err_sanity; - } - if ( ! ll_dest ) { - DBGC ( snpdev, "SNPDEV %p TX missing destination " - "address\n", snpdev ); - rc = -EINVAL; - goto err_sanity; - } - if ( ! net_proto ) { - DBGC ( snpdev, "SNPDEV %p TX missing network " - "protocol\n", snpdev ); - rc = -EINVAL; - goto err_sanity; - } - if ( ! ll_src ) - ll_src = &snpdev->mode.CurrentAddress; - } - - /* Allocate buffer */ - payload_len = ( len - ll_protocol->ll_header_len ); - iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ? - payload_len : IOB_ZLEN ) ); - if ( ! iobuf ) { - DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte " - "buffer\n", snpdev, ( ( unsigned long ) len ) ); - rc = -ENOMEM; - goto err_alloc_iob; - } - iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN - - ll_protocol->ll_header_len ) ); - memcpy ( iob_put ( iobuf, len ), data, len ); - - /* Create link-layer header, if specified */ - if ( ll_header_len ) { - iob_pull ( iobuf, ll_protocol->ll_header_len ); - if ( ( rc = ll_protocol->push ( snpdev->netdev, - iobuf, ll_dest, ll_src, - htons ( *net_proto ) )) != 0 ){ - DBGC ( snpdev, "SNPDEV %p TX could not construct " - "header: %s\n", snpdev, strerror ( rc ) ); - goto err_ll_push; - } - } - - /* Transmit packet */ - if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){ - DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n", - snpdev, strerror ( rc ) ); - goto err_tx; - } - - /* Record in transmit completion ring. If we run out of - * space, report the failure even though we have already - * transmitted the packet. - * - * This allows us to report completions only for packets for - * which we had reported successfully initiating transmission, - * while continuing to support clients that never poll for - * transmit completions. - */ - tx_fill = ( snpdev->tx_prod - snpdev->tx_cons ); - if ( tx_fill >= EFI_SNP_NUM_TX ) { - DBGC ( snpdev, "SNPDEV %p TX completion ring full\n", snpdev ); - rc = -ENOBUFS; - goto err_ring_full; - } - snpdev->tx[ snpdev->tx_prod++ % EFI_SNP_NUM_TX ] = data; - snpdev->interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; - - return 0; - - err_ring_full: - err_tx: - err_ll_push: - free_iob ( iobuf ); - err_alloc_iob: - err_sanity: - return EFIRC ( rc ); -} - -/** - * Receive packet - * - * @v snp SNP interface - * @v ll_header_len Link-layer header length, if to be filled in - * @v len Length of data buffer - * @v data Data buffer - * @v ll_src Link-layer source address, if specified - * @v ll_dest Link-layer destination address, if specified - * @v net_proto Network-layer protocol (in host order) - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, - UINTN *ll_header_len, UINTN *len, VOID *data, - EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest, - UINT16 *net_proto ) { - struct efi_snp_device *snpdev = - container_of ( snp, struct efi_snp_device, snp ); - struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; - struct io_buffer *iobuf; - const void *iob_ll_dest; - const void *iob_ll_src; - uint16_t iob_net_proto; - unsigned int iob_flags; - int rc; - - DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data, - ( ( unsigned long ) *len ) ); - - /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; - - /* Poll the network device */ - efi_snp_poll ( snpdev ); - - /* Dequeue a packet, if one is available */ - iobuf = list_first_entry ( &snpdev->rx, struct io_buffer, list ); - if ( ! iobuf ) { - DBGC2 ( snpdev, "\n" ); - rc = -EAGAIN; - goto out_no_packet; - } - list_del ( &iobuf->list ); - DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) ); - - /* Return packet to caller */ - memcpy ( data, iobuf->data, iob_len ( iobuf ) ); - *len = iob_len ( iobuf ); - - /* Attempt to decode link-layer header */ - if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest, - &iob_ll_src, &iob_net_proto, - &iob_flags ) ) != 0 ) { - DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n", - snpdev, strerror ( rc ) ); - goto out_bad_ll_header; - } - - /* Return link-layer header parameters to caller, if required */ - if ( ll_header_len ) - *ll_header_len = ll_protocol->ll_header_len; - if ( ll_src ) - memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len ); - if ( ll_dest ) - memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len ); - if ( net_proto ) - *net_proto = ntohs ( iob_net_proto ); - - rc = 0; - - out_bad_ll_header: - free_iob ( iobuf ); - out_no_packet: - return EFIRC ( rc ); -} - -/** - * Poll event - * - * @v event Event - * @v context Event context - */ -static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event __unused, - VOID *context ) { - struct efi_snp_device *snpdev = context; - - DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev ); - - /* Do nothing unless the net device is open */ - if ( ! netdev_is_open ( snpdev->netdev ) ) - return; - - /* Do nothing if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return; - - /* Poll the network device */ - efi_snp_poll ( snpdev ); -} - -/** SNP interface */ -static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = { - .Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION, - .Start = efi_snp_start, - .Stop = efi_snp_stop, - .Initialize = efi_snp_initialize, - .Reset = efi_snp_reset, - .Shutdown = efi_snp_shutdown, - .ReceiveFilters = efi_snp_receive_filters, - .StationAddress = efi_snp_station_address, - .Statistics = efi_snp_statistics, - .MCastIpToMac = efi_snp_mcast_ip_to_mac, - .NvData = efi_snp_nvdata, - .GetStatus = efi_snp_get_status, - .Transmit = efi_snp_transmit, - .Receive = efi_snp_receive, -}; - -/****************************************************************************** - * - * Component name protocol - * - ****************************************************************************** - */ - -/** - * Look up driver name - * - * @v name2 Component name protocol - * @v language Language to use - * @v driver_name Driver name to fill in - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2, - CHAR8 *language __unused, CHAR16 **driver_name ) { - struct efi_snp_device *snpdev = - container_of ( name2, struct efi_snp_device, name2 ); - - *driver_name = snpdev->driver_name; - return 0; -} - -/** - * Look up controller name - * - * @v name2 Component name protocol - * @v device Device - * @v child Child device, or NULL - * @v language Language to use - * @v driver_name Device name to fill in - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2, - EFI_HANDLE device __unused, - EFI_HANDLE child __unused, - CHAR8 *language __unused, - CHAR16 **controller_name ) { - struct efi_snp_device *snpdev = - container_of ( name2, struct efi_snp_device, name2 ); - - *controller_name = snpdev->controller_name; - return 0; -} - -/****************************************************************************** - * - * Load file protocol - * - ****************************************************************************** - */ - -/** - * Load file - * - * @v loadfile Load file protocol - * @v path File path - * @v booting Loading as part of a boot attempt - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file, - EFI_DEVICE_PATH_PROTOCOL *path __unused, - BOOLEAN booting, UINTN *len __unused, - VOID *data __unused ) { - struct efi_snp_device *snpdev = - container_of ( load_file, struct efi_snp_device, load_file ); - struct net_device *netdev = snpdev->netdev; - int rc; - - /* Fail unless this is a boot attempt */ - if ( ! booting ) { - DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n", - snpdev ); - return EFI_UNSUPPORTED; - } - - /* Claim network devices for use by iPXE */ - efi_snp_claim(); - - /* Start watchdog holdoff timer */ - efi_watchdog_start(); - - /* Boot from network device */ - if ( ( rc = ipxe ( netdev ) ) != 0 ) - goto err_ipxe; - - err_ipxe: - efi_watchdog_stop(); - efi_snp_release(); - return EFIRC ( rc ); -} - -/** Load file protocol */ -static EFI_LOAD_FILE_PROTOCOL efi_snp_load_file_protocol = { - .LoadFile = efi_snp_load_file, -}; - -/****************************************************************************** - * - * iPXE network driver - * - ****************************************************************************** - */ - -/** - * Locate SNP device corresponding to network device - * - * @v netdev Network device - * @ret snp SNP device, or NULL if not found - */ -static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) { - struct efi_snp_device *snpdev; - - list_for_each_entry ( snpdev, &efi_snp_devices, list ) { - if ( snpdev->netdev == netdev ) - return snpdev; - } - return NULL; -} - -/** - * Create SNP device - * - * @v netdev Network device - * @ret rc Return status code - */ -static int efi_snp_probe ( struct net_device *netdev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct efi_device *efidev; - struct efi_snp_device *snpdev; - union { - EFI_DEVICE_PATH_PROTOCOL *path; - void *interface; - } path; - EFI_DEVICE_PATH_PROTOCOL *path_end; - MAC_ADDR_DEVICE_PATH *macpath; - size_t path_prefix_len = 0; - EFI_STATUS efirc; - int rc; - - /* Find parent EFI device */ - efidev = efidev_parent ( netdev->dev ); - if ( ! efidev ) { - DBG ( "SNP skipping non-EFI device %s\n", netdev->name ); - rc = 0; - goto err_no_efidev; - } - - /* Allocate the SNP device */ - snpdev = zalloc ( sizeof ( *snpdev ) ); - if ( ! snpdev ) { - rc = -ENOMEM; - goto err_alloc_snp; - } - snpdev->netdev = netdev_get ( netdev ); - snpdev->efidev = efidev; - INIT_LIST_HEAD ( &snpdev->rx ); - - /* Sanity check */ - if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) { - DBGC ( snpdev, "SNPDEV %p cannot support link-layer address " - "length %d for %s\n", snpdev, - netdev->ll_protocol->ll_addr_len, netdev->name ); - rc = -ENOTSUP; - goto err_ll_addr_len; - } - - /* Populate the SNP structure */ - memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) ); - snpdev->snp.Mode = &snpdev->mode; - if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, - efi_snp_wait_for_packet, snpdev, - &snpdev->snp.WaitForPacket ) ) != 0 ){ - rc = -EEFI ( efirc ); - DBGC ( snpdev, "SNPDEV %p could not create event: %s\n", - snpdev, strerror ( rc ) ); - goto err_create_event; - } - - /* Populate the SNP mode structure */ - snpdev->mode.State = EfiSimpleNetworkStopped; - efi_snp_set_mode ( snpdev ); - - /* Populate the NII structure */ - snpdev->nii.Revision = - EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; - strncpy ( snpdev->nii.StringId, "iPXE", - sizeof ( snpdev->nii.StringId ) ); - - /* Populate the component name structure */ - efi_snprintf ( snpdev->driver_name, - ( sizeof ( snpdev->driver_name ) / - sizeof ( snpdev->driver_name[0] ) ), - "%s %s", product_short_name, netdev->dev->driver_name ); - efi_snprintf ( snpdev->controller_name, - ( sizeof ( snpdev->controller_name ) / - sizeof ( snpdev->controller_name[0] ) ), - "%s %s (%s, %s)", product_short_name, - netdev->dev->driver_name, netdev->dev->name, - netdev_addr ( netdev ) ); - snpdev->name2.GetDriverName = efi_snp_get_driver_name; - snpdev->name2.GetControllerName = efi_snp_get_controller_name; - snpdev->name2.SupportedLanguages = "en"; - - /* Populate the load file protocol structure */ - memcpy ( &snpdev->load_file, &efi_snp_load_file_protocol, - sizeof ( snpdev->load_file ) ); - - /* Populate the device name */ - efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) / - sizeof ( snpdev->name[0] ) ), - "%s", netdev->name ); - - /* Get the parent device path */ - if ( ( efirc = bs->OpenProtocol ( efidev->device, - &efi_device_path_protocol_guid, - &path.interface, efi_image_handle, - efidev->device, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - rc = -EEFI ( efirc ); - DBGC ( snpdev, "SNPDEV %p cannot get %p %s device path: %s\n", - snpdev, efidev->device, - efi_handle_name ( efidev->device ), strerror ( rc ) ); - goto err_open_device_path; - } - - /* Allocate the new device path */ - path_end = efi_devpath_end ( path.path ); - path_prefix_len = ( ( ( void * ) path_end ) - ( ( void * ) path.path )); - snpdev->path = zalloc ( path_prefix_len + sizeof ( *macpath ) + - sizeof ( *path_end ) ); - if ( ! snpdev->path ) { - rc = -ENOMEM; - goto err_alloc_device_path; - } - - /* Populate the device path */ - memcpy ( snpdev->path, path.path, path_prefix_len ); - macpath = ( ( ( void * ) snpdev->path ) + path_prefix_len ); - path_end = ( ( void * ) ( macpath + 1 ) ); - memset ( macpath, 0, sizeof ( *macpath ) ); - macpath->Header.Type = MESSAGING_DEVICE_PATH; - macpath->Header.SubType = MSG_MAC_ADDR_DP; - macpath->Header.Length[0] = sizeof ( *macpath ); - memcpy ( &macpath->MacAddress, netdev->ll_addr, - sizeof ( macpath->MacAddress ) ); - macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto ); - memset ( path_end, 0, sizeof ( *path_end ) ); - path_end->Type = END_DEVICE_PATH_TYPE; - path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; - path_end->Length[0] = sizeof ( *path_end ); - - /* Install the SNP */ - if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( - &snpdev->handle, - &efi_simple_network_protocol_guid, &snpdev->snp, - &efi_device_path_protocol_guid, snpdev->path, - &efi_nii_protocol_guid, &snpdev->nii, - &efi_nii31_protocol_guid, &snpdev->nii, - &efi_component_name2_protocol_guid, &snpdev->name2, - &efi_load_file_protocol_guid, &snpdev->load_file, - NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( snpdev, "SNPDEV %p could not install protocols: " - "%s\n", snpdev, strerror ( rc ) ); - goto err_install_protocol_interface; - } - - /* Add as child of EFI parent device */ - if ( ( rc = efi_child_add ( efidev->device, snpdev->handle ) ) != 0 ) { - DBGC ( snpdev, "SNPDEV %p could not become child of %p %s: " - "%s\n", snpdev, efidev->device, - efi_handle_name ( efidev->device ), strerror ( rc ) ); - goto err_efi_child_add; - } - - /* Install HII */ - if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) { - DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n", - snpdev, strerror ( rc ) ); - /* HII fails on several platforms. It's - * non-essential, so treat this as a non-fatal - * error. - */ - } - - /* Add to list of SNP devices */ - list_add ( &snpdev->list, &efi_snp_devices ); - - /* Close device path */ - bs->CloseProtocol ( efidev->device, &efi_device_path_protocol_guid, - efi_image_handle, efidev->device ); - - DBGC ( snpdev, "SNPDEV %p installed for %s as device %p %s\n", - snpdev, netdev->name, snpdev->handle, - efi_handle_name ( snpdev->handle ) ); - return 0; - - if ( snpdev->package_list ) - efi_snp_hii_uninstall ( snpdev ); - efi_child_del ( efidev->device, snpdev->handle ); - err_efi_child_add: - bs->UninstallMultipleProtocolInterfaces ( - snpdev->handle, - &efi_simple_network_protocol_guid, &snpdev->snp, - &efi_device_path_protocol_guid, snpdev->path, - &efi_nii_protocol_guid, &snpdev->nii, - &efi_nii31_protocol_guid, &snpdev->nii, - &efi_component_name2_protocol_guid, &snpdev->name2, - &efi_load_file_protocol_guid, &snpdev->load_file, - NULL ); - err_install_protocol_interface: - free ( snpdev->path ); - err_alloc_device_path: - bs->CloseProtocol ( efidev->device, &efi_device_path_protocol_guid, - efi_image_handle, efidev->device ); - err_open_device_path: - bs->CloseEvent ( snpdev->snp.WaitForPacket ); - err_create_event: - err_ll_addr_len: - netdev_put ( netdev ); - free ( snpdev ); - err_alloc_snp: - err_no_efidev: - return rc; -} - -/** - * Handle SNP device or link state change - * - * @v netdev Network device - */ -static void efi_snp_notify ( struct net_device *netdev ) { - struct efi_snp_device *snpdev; - - /* Locate SNP device */ - snpdev = efi_snp_demux ( netdev ); - if ( ! snpdev ) { - DBG ( "SNP skipping non-SNP device %s\n", netdev->name ); - return; - } - - /* Update link state */ - snpdev->mode.MediaPresent = - ( netdev_link_ok ( netdev ) ? TRUE : FALSE ); - DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev, - ( snpdev->mode.MediaPresent ? "up" : "down" ) ); - - /* Update mode state */ - efi_snp_set_state ( snpdev ); -} - -/** - * Destroy SNP device - * - * @v netdev Network device - */ -static void efi_snp_remove ( struct net_device *netdev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct efi_snp_device *snpdev; - - /* Locate SNP device */ - snpdev = efi_snp_demux ( netdev ); - if ( ! snpdev ) { - DBG ( "SNP skipping non-SNP device %s\n", netdev->name ); - return; - } - - /* Uninstall the SNP */ - if ( snpdev->package_list ) - efi_snp_hii_uninstall ( snpdev ); - efi_child_del ( snpdev->efidev->device, snpdev->handle ); - list_del ( &snpdev->list ); - bs->UninstallMultipleProtocolInterfaces ( - snpdev->handle, - &efi_simple_network_protocol_guid, &snpdev->snp, - &efi_device_path_protocol_guid, snpdev->path, - &efi_nii_protocol_guid, &snpdev->nii, - &efi_nii31_protocol_guid, &snpdev->nii, - &efi_component_name2_protocol_guid, &snpdev->name2, - &efi_load_file_protocol_guid, &snpdev->load_file, - NULL ); - free ( snpdev->path ); - bs->CloseEvent ( snpdev->snp.WaitForPacket ); - netdev_put ( snpdev->netdev ); - free ( snpdev ); -} - -/** SNP driver */ -struct net_driver efi_snp_driver __net_driver = { - .name = "SNP", - .probe = efi_snp_probe, - .notify = efi_snp_notify, - .remove = efi_snp_remove, -}; - -/** - * Find SNP device by EFI device handle - * - * @v handle EFI device handle - * @ret snpdev SNP device, or NULL - */ -struct efi_snp_device * find_snpdev ( EFI_HANDLE handle ) { - struct efi_snp_device *snpdev; - - list_for_each_entry ( snpdev, &efi_snp_devices, list ) { - if ( snpdev->handle == handle ) - return snpdev; - } - return NULL; -} - -/** - * Get most recently opened SNP device - * - * @ret snpdev Most recently opened SNP device, or NULL - */ -struct efi_snp_device * last_opened_snpdev ( void ) { - struct net_device *netdev; - - netdev = last_opened_netdev(); - if ( ! netdev ) - return NULL; - - return efi_snp_demux ( netdev ); -} - -/** - * Set SNP claimed/released state - * - * @v claimed Network devices are claimed for use by iPXE - */ -void efi_snp_set_claimed ( int claimed ) { - struct efi_snp_device *snpdev; - - /* Claim SNP devices */ - efi_snp_claimed = claimed; - - /* Update SNP mode state for each interface */ - list_for_each_entry ( snpdev, &efi_snp_devices, list ) - efi_snp_set_state ( snpdev ); -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_snp_hii.c b/qemu/roms/ipxe/src/interface/efi/efi_snp_hii.c deleted file mode 100644 index 720402bdb..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_snp_hii.c +++ /dev/null @@ -1,727 +0,0 @@ -/* - * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** - * @file - * - * EFI SNP HII protocol - * - * The HII protocols are some of the less-well designed parts of the - * entire EFI specification. This is a significant accomplishment. - * - * The face-slappingly ludicrous query string syntax seems to be - * motivated by the desire to allow a caller to query multiple drivers - * simultaneously via the single-instance HII_CONFIG_ROUTING_PROTOCOL, - * which is supposed to pass relevant subsets of the query string to - * the relevant drivers. - * - * Nobody uses the HII_CONFIG_ROUTING_PROTOCOL. Not even the EFI - * setup browser uses the HII_CONFIG_ROUTING_PROTOCOL. To the best of - * my knowledge, there has only ever been one implementation of the - * HII_CONFIG_ROUTING_PROTOCOL (as part of EDK2), and it just doesn't - * work. It's so badly broken that I can't even figure out what the - * code is _trying_ to do. - * - * Fundamentally, the problem seems to be that Javascript programmers - * should not be allowed to design APIs for C code. - */ - -#include <string.h> -#include <strings.h> -#include <stdlib.h> -#include <stdio.h> -#include <wchar.h> -#include <errno.h> -#include <ipxe/settings.h> -#include <ipxe/nvo.h> -#include <ipxe/device.h> -#include <ipxe/netdevice.h> -#include <ipxe/version.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_hii.h> -#include <ipxe/efi/efi_snp.h> -#include <ipxe/efi/efi_strings.h> -#include <config/branding.h> - -/** EFI platform setup formset GUID */ -static EFI_GUID efi_hii_platform_setup_formset_guid - = EFI_HII_PLATFORM_SETUP_FORMSET_GUID; - -/** EFI IBM UCM compliant formset GUID */ -static EFI_GUID efi_hii_ibm_ucm_compliant_formset_guid - = EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID; - -/** EFI HII database protocol */ -static EFI_HII_DATABASE_PROTOCOL *efihii; -EFI_REQUEST_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii ); - -/** - * Identify settings to be exposed via HII - * - * @v snpdev SNP device - * @ret settings Settings, or NULL - */ -static struct settings * efi_snp_hii_settings ( struct efi_snp_device *snpdev ){ - - return find_child_settings ( netdev_settings ( snpdev->netdev ), - NVO_SETTINGS_NAME ); -} - -/** - * Check whether or not setting is applicable - * - * @v snpdev SNP device - * @v setting Setting - * @ret applies Setting applies - */ -static int efi_snp_hii_setting_applies ( struct efi_snp_device *snpdev, - struct setting *setting ) { - - return nvo_applies ( efi_snp_hii_settings ( snpdev ), setting ); -} - -/** - * Generate a random GUID - * - * @v guid GUID to fill in - */ -static void efi_snp_hii_random_guid ( EFI_GUID *guid ) { - uint8_t *byte = ( ( uint8_t * ) guid ); - unsigned int i; - - for ( i = 0 ; i < sizeof ( *guid ) ; i++ ) - *(byte++) = random(); -} - -/** - * Generate EFI SNP questions - * - * @v snpdev SNP device - * @v ifr IFR builder - * @v varstore_id Variable store identifier - */ -static void efi_snp_hii_questions ( struct efi_snp_device *snpdev, - struct efi_ifr_builder *ifr, - unsigned int varstore_id ) { - struct setting *setting; - struct setting *previous = NULL; - unsigned int name_id; - unsigned int prompt_id; - unsigned int help_id; - unsigned int question_id; - - /* Add all applicable settings */ - for_each_table_entry ( setting, SETTINGS ) { - if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) ) - continue; - if ( previous && ( setting_cmp ( setting, previous ) == 0 ) ) - continue; - previous = setting; - name_id = efi_ifr_string ( ifr, "%s", setting->name ); - prompt_id = efi_ifr_string ( ifr, "%s", setting->description ); - help_id = efi_ifr_string ( ifr, PRODUCT_SETTING_URI, - setting->name ); - question_id = setting->tag; - efi_ifr_string_op ( ifr, prompt_id, help_id, - question_id, varstore_id, name_id, - 0, 0x00, 0xff, 0 ); - } -} - -/** - * Build HII package list for SNP device - * - * @v snpdev SNP device - * @ret package Package list, or NULL on error - */ -static EFI_HII_PACKAGE_LIST_HEADER * -efi_snp_hii_package_list ( struct efi_snp_device *snpdev ) { - struct net_device *netdev = snpdev->netdev; - struct device *dev = netdev->dev; - struct efi_ifr_builder ifr; - EFI_HII_PACKAGE_LIST_HEADER *package; - const char *name; - EFI_GUID package_guid; - EFI_GUID formset_guid; - EFI_GUID varstore_guid; - unsigned int title_id; - unsigned int varstore_id; - - /* Initialise IFR builder */ - efi_ifr_init ( &ifr ); - - /* Determine product name */ - name = ( product_name[0] ? product_name : product_short_name ); - - /* Generate GUIDs */ - efi_snp_hii_random_guid ( &package_guid ); - efi_snp_hii_random_guid ( &formset_guid ); - efi_snp_hii_random_guid ( &varstore_guid ); - - /* Generate title string (used more than once) */ - title_id = efi_ifr_string ( &ifr, "%s (%s)", name, - netdev_addr ( netdev ) ); - - /* Generate opcodes */ - efi_ifr_form_set_op ( &ifr, &formset_guid, title_id, - efi_ifr_string ( &ifr, "Configure %s", - product_short_name ), - &efi_hii_platform_setup_formset_guid, - &efi_hii_ibm_ucm_compliant_formset_guid, NULL ); - efi_ifr_guid_class_op ( &ifr, EFI_NETWORK_DEVICE_CLASS ); - efi_ifr_guid_subclass_op ( &ifr, 0x03 ); - varstore_id = efi_ifr_varstore_name_value_op ( &ifr, &varstore_guid ); - efi_ifr_form_op ( &ifr, title_id ); - efi_ifr_text_op ( &ifr, - efi_ifr_string ( &ifr, "Name" ), - efi_ifr_string ( &ifr, "Firmware product name" ), - efi_ifr_string ( &ifr, "%s", name ) ); - efi_ifr_text_op ( &ifr, - efi_ifr_string ( &ifr, "Version" ), - efi_ifr_string ( &ifr, "Firmware version" ), - efi_ifr_string ( &ifr, "%s", product_version ) ); - efi_ifr_text_op ( &ifr, - efi_ifr_string ( &ifr, "Driver" ), - efi_ifr_string ( &ifr, "Firmware driver" ), - efi_ifr_string ( &ifr, "%s", dev->driver_name ) ); - efi_ifr_text_op ( &ifr, - efi_ifr_string ( &ifr, "Device" ), - efi_ifr_string ( &ifr, "Hardware device" ), - efi_ifr_string ( &ifr, "%s", dev->name ) ); - efi_snp_hii_questions ( snpdev, &ifr, varstore_id ); - efi_ifr_end_op ( &ifr ); - efi_ifr_end_op ( &ifr ); - - /* Build package */ - package = efi_ifr_package ( &ifr, &package_guid, "en-us", - efi_ifr_string ( &ifr, "English" ) ); - if ( ! package ) { - DBGC ( snpdev, "SNPDEV %p could not build IFR package\n", - snpdev ); - efi_ifr_free ( &ifr ); - return NULL; - } - - /* Free temporary storage */ - efi_ifr_free ( &ifr ); - return package; -} - -/** - * Append response to result string - * - * @v snpdev SNP device - * @v key Key - * @v value Value - * @v results Result string - * @ret rc Return status code - * - * The result string is allocated dynamically using - * BootServices::AllocatePool(), and the caller is responsible for - * eventually calling BootServices::FreePool(). - */ -static int efi_snp_hii_append ( struct efi_snp_device *snpdev __unused, - const char *key, const char *value, - wchar_t **results ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - size_t len; - void *new; - - /* Allocate new string */ - len = ( ( *results ? ( wcslen ( *results ) + 1 /* "&" */ ) : 0 ) + - strlen ( key ) + 1 /* "=" */ + strlen ( value ) + 1 /* NUL */ ); - bs->AllocatePool ( EfiBootServicesData, ( len * sizeof ( wchar_t ) ), - &new ); - if ( ! new ) - return -ENOMEM; - - /* Populate string */ - efi_snprintf ( new, len, "%ls%s%s=%s", ( *results ? *results : L"" ), - ( *results ? L"&" : L"" ), key, value ); - bs->FreePool ( *results ); - *results = new; - - return 0; -} - -/** - * Fetch HII setting - * - * @v snpdev SNP device - * @v key Key - * @v value Value - * @v results Result string - * @v have_setting Flag indicating detection of a setting - * @ret rc Return status code - */ -static int efi_snp_hii_fetch ( struct efi_snp_device *snpdev, - const char *key, const char *value, - wchar_t **results, int *have_setting ) { - struct settings *settings = efi_snp_hii_settings ( snpdev ); - struct settings *origin; - struct setting *setting; - struct setting fetched; - int len; - char *buf; - char *encoded; - int i; - int rc; - - /* Handle ConfigHdr components */ - if ( ( strcasecmp ( key, "GUID" ) == 0 ) || - ( strcasecmp ( key, "NAME" ) == 0 ) || - ( strcasecmp ( key, "PATH" ) == 0 ) ) { - return efi_snp_hii_append ( snpdev, key, value, results ); - } - if ( have_setting ) - *have_setting = 1; - - /* Do nothing more unless we have a settings block */ - if ( ! settings ) { - rc = -ENOTSUP; - goto err_no_settings; - } - - /* Identify setting */ - setting = find_setting ( key ); - if ( ! setting ) { - DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n", - snpdev, key ); - rc = -ENODEV; - goto err_find_setting; - } - - /* Encode value */ - if ( setting_exists ( settings, setting ) ) { - - /* Calculate formatted length */ - len = fetchf_setting ( settings, setting, &origin, &fetched, - NULL, 0 ); - if ( len < 0 ) { - rc = len; - DBGC ( snpdev, "SNPDEV %p could not fetch %s: %s\n", - snpdev, setting->name, strerror ( rc ) ); - goto err_fetchf_len; - } - - /* Allocate buffer for formatted value and HII-encoded value */ - buf = zalloc ( len + 1 /* NUL */ + ( len * 4 ) + 1 /* NUL */ ); - if ( ! buf ) { - rc = -ENOMEM; - goto err_alloc; - } - encoded = ( buf + len + 1 /* NUL */ ); - - /* Format value */ - fetchf_setting ( origin, &fetched, NULL, NULL, buf, - ( len + 1 /* NUL */ ) ); - for ( i = 0 ; i < len ; i++ ) { - sprintf ( ( encoded + ( 4 * i ) ), "%04x", - *( ( uint8_t * ) buf + i ) ); - } - - } else { - - /* Non-existent or inapplicable setting */ - buf = NULL; - encoded = ""; - } - - /* Append results */ - if ( ( rc = efi_snp_hii_append ( snpdev, key, encoded, - results ) ) != 0 ) { - goto err_append; - } - - /* Success */ - rc = 0; - - err_append: - free ( buf ); - err_alloc: - err_fetchf_len: - err_find_setting: - err_no_settings: - return rc; -} - -/** - * Fetch HII setting - * - * @v snpdev SNP device - * @v key Key - * @v value Value - * @v results Result string (unused) - * @v have_setting Flag indicating detection of a setting (unused) - * @ret rc Return status code - */ -static int efi_snp_hii_store ( struct efi_snp_device *snpdev, - const char *key, const char *value, - wchar_t **results __unused, - int *have_setting __unused ) { - struct settings *settings = efi_snp_hii_settings ( snpdev ); - struct setting *setting; - char *buf; - char tmp[5]; - char *endp; - int len; - int i; - int rc; - - /* Handle ConfigHdr components */ - if ( ( strcasecmp ( key, "GUID" ) == 0 ) || - ( strcasecmp ( key, "NAME" ) == 0 ) || - ( strcasecmp ( key, "PATH" ) == 0 ) ) { - /* Nothing to do */ - return 0; - } - - /* Do nothing more unless we have a settings block */ - if ( ! settings ) { - rc = -ENOTSUP; - goto err_no_settings; - } - - /* Identify setting */ - setting = find_setting ( key ); - if ( ! setting ) { - DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n", - snpdev, key ); - rc = -ENODEV; - goto err_find_setting; - } - - /* Allocate buffer */ - len = ( strlen ( value ) / 4 ); - buf = zalloc ( len + 1 /* NUL */ ); - if ( ! buf ) { - rc = -ENOMEM; - goto err_alloc; - } - - /* Decode value */ - tmp[4] = '\0'; - for ( i = 0 ; i < len ; i++ ) { - memcpy ( tmp, ( value + ( i * 4 ) ), 4 ); - buf[i] = strtoul ( tmp, &endp, 16 ); - if ( endp != &tmp[4] ) { - DBGC ( snpdev, "SNPDEV %p invalid character %s\n", - snpdev, tmp ); - rc = -EINVAL; - goto err_inval; - } - } - - /* Store value */ - if ( ( rc = storef_setting ( settings, setting, buf ) ) != 0 ) { - DBGC ( snpdev, "SNPDEV %p could not store \"%s\" into %s: %s\n", - snpdev, buf, setting->name, strerror ( rc ) ); - goto err_storef; - } - - /* Success */ - rc = 0; - - err_storef: - err_inval: - free ( buf ); - err_alloc: - err_find_setting: - err_no_settings: - return rc; -} - -/** - * Process portion of HII configuration string - * - * @v snpdev SNP device - * @v string HII configuration string - * @v progress Progress through HII configuration string - * @v results Results string - * @v have_setting Flag indicating detection of a setting (unused) - * @v process Function used to process key=value pairs - * @ret rc Return status code - */ -static int efi_snp_hii_process ( struct efi_snp_device *snpdev, - wchar_t *string, wchar_t **progress, - wchar_t **results, int *have_setting, - int ( * process ) ( struct efi_snp_device *, - const char *key, - const char *value, - wchar_t **results, - int *have_setting ) ) { - wchar_t *wkey = string; - wchar_t *wend = string; - wchar_t *wvalue = NULL; - size_t key_len; - size_t value_len; - void *temp; - char *key; - char *value; - int rc; - - /* Locate key, value (if any), and end */ - while ( *wend ) { - if ( *wend == L'&' ) - break; - if ( *(wend++) == L'=' ) - wvalue = wend; - } - - /* Allocate memory for key and value */ - key_len = ( ( wvalue ? ( wvalue - 1 ) : wend ) - wkey ); - value_len = ( wvalue ? ( wend - wvalue ) : 0 ); - temp = zalloc ( key_len + 1 /* NUL */ + value_len + 1 /* NUL */ ); - if ( ! temp ) - return -ENOMEM; - key = temp; - value = ( temp + key_len + 1 /* NUL */ ); - - /* Copy key and value */ - while ( key_len-- ) - key[key_len] = wkey[key_len]; - while ( value_len-- ) - value[value_len] = wvalue[value_len]; - - /* Process key and value */ - if ( ( rc = process ( snpdev, key, value, results, - have_setting ) ) != 0 ) { - goto err; - } - - /* Update progress marker */ - *progress = wend; - - err: - /* Free temporary storage */ - free ( temp ); - - return rc; -} - -/** - * Fetch configuration - * - * @v hii HII configuration access protocol - * @v request Configuration to fetch - * @ret progress Progress made through configuration to fetch - * @ret results Query results - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, - EFI_STRING request, EFI_STRING *progress, - EFI_STRING *results ) { - struct efi_snp_device *snpdev = - container_of ( hii, struct efi_snp_device, hii ); - int have_setting = 0; - wchar_t *pos; - int rc; - - DBGC ( snpdev, "SNPDEV %p ExtractConfig request \"%ls\"\n", - snpdev, request ); - - /* Initialise results */ - *results = NULL; - - /* Process all request fragments */ - for ( pos = *progress = request ; *progress && **progress ; - pos = *progress + 1 ) { - if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, - results, &have_setting, - efi_snp_hii_fetch ) ) != 0 ) { - return EFIRC ( rc ); - } - } - - /* If we have no explicit request, return all settings */ - if ( ! have_setting ) { - struct setting *setting; - - for_each_table_entry ( setting, SETTINGS ) { - if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) ) - continue; - if ( ( rc = efi_snp_hii_fetch ( snpdev, setting->name, - NULL, results, - NULL ) ) != 0 ) { - return EFIRC ( rc ); - } - } - } - - DBGC ( snpdev, "SNPDEV %p ExtractConfig results \"%ls\"\n", - snpdev, *results ); - return 0; -} - -/** - * Store configuration - * - * @v hii HII configuration access protocol - * @v config Configuration to store - * @ret progress Progress made through configuration to store - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, - EFI_STRING config, EFI_STRING *progress ) { - struct efi_snp_device *snpdev = - container_of ( hii, struct efi_snp_device, hii ); - wchar_t *pos; - int rc; - - DBGC ( snpdev, "SNPDEV %p RouteConfig \"%ls\"\n", snpdev, config ); - - /* Process all request fragments */ - for ( pos = *progress = config ; *progress && **progress ; - pos = *progress + 1 ) { - if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, - NULL, NULL, - efi_snp_hii_store ) ) != 0 ) { - return EFIRC ( rc ); - } - } - - return 0; -} - -/** - * Handle form actions - * - * @v hii HII configuration access protocol - * @v action Form browser action - * @v question_id Question ID - * @v type Type of value - * @v value Value - * @ret action_request Action requested by driver - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, - EFI_BROWSER_ACTION action __unused, - EFI_QUESTION_ID question_id __unused, - UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused, - EFI_BROWSER_ACTION_REQUEST *action_request __unused ) { - struct efi_snp_device *snpdev = - container_of ( hii, struct efi_snp_device, hii ); - - DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev ); - return EFI_UNSUPPORTED; -} - -/** HII configuration access protocol */ -static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = { - .ExtractConfig = efi_snp_hii_extract_config, - .RouteConfig = efi_snp_hii_route_config, - .Callback = efi_snp_hii_callback, -}; - -/** - * Install HII protocol and packages for SNP device - * - * @v snpdev SNP device - * @ret rc Return status code - */ -int efi_snp_hii_install ( struct efi_snp_device *snpdev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - int efirc; - int rc; - - /* Do nothing if HII database protocol is not supported */ - if ( ! efihii ) { - rc = -ENOTSUP; - goto err_no_hii; - } - - /* Initialise HII protocol */ - memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) ); - - /* Create HII package list */ - snpdev->package_list = efi_snp_hii_package_list ( snpdev ); - if ( ! snpdev->package_list ) { - DBGC ( snpdev, "SNPDEV %p could not create HII package list\n", - snpdev ); - rc = -ENOMEM; - goto err_build_package_list; - } - - /* Add HII packages */ - if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list, - snpdev->handle, - &snpdev->hii_handle ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n", - snpdev, strerror ( rc ) ); - goto err_new_package_list; - } - - /* Install HII protocol */ - if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( - &snpdev->handle, - &efi_hii_config_access_protocol_guid, &snpdev->hii, - NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( snpdev, "SNPDEV %p could not install HII protocol: %s\n", - snpdev, strerror ( rc ) ); - goto err_install_protocol; - } - - return 0; - - bs->UninstallMultipleProtocolInterfaces ( - snpdev->handle, - &efi_hii_config_access_protocol_guid, &snpdev->hii, - NULL ); - err_install_protocol: - efihii->RemovePackageList ( efihii, snpdev->hii_handle ); - err_new_package_list: - free ( snpdev->package_list ); - snpdev->package_list = NULL; - err_build_package_list: - err_no_hii: - return rc; -} - -/** - * Uninstall HII protocol and package for SNP device - * - * @v snpdev SNP device - */ -void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - /* Do nothing if HII database protocol is not supported */ - if ( ! efihii ) - return; - - /* Uninstall protocols and remove package list */ - bs->UninstallMultipleProtocolInterfaces ( - snpdev->handle, - &efi_hii_config_access_protocol_guid, &snpdev->hii, - NULL ); - efihii->RemovePackageList ( efihii, snpdev->hii_handle ); - free ( snpdev->package_list ); - snpdev->package_list = NULL; -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_strings.c b/qemu/roms/ipxe/src/interface/efi/efi_strings.c deleted file mode 100644 index aa3afc64f..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_strings.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2011 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 <stddef.h> -#include <stdarg.h> -#include <ipxe/vsprintf.h> -#include <ipxe/efi/efi_strings.h> - -/** Context used by efi_vsnprintf() and friends */ -struct efi_sputc_context { - /** printf context */ - struct printf_context ctx; - /** Buffer for formatted string (used by efi_printf_sputc()) */ - wchar_t *buf; - /** Buffer length (used by efi_printf_sputc()) - * - * Note that this is a number of wide characters, not a number - * of bytes. - */ - size_t max_wlen; -}; - -/** - * Write wide character to buffer - * - * @v ctx Context - * @v c Character - */ -static void efi_printf_sputc ( struct printf_context *ctx, unsigned int c ) { - struct efi_sputc_context * sctx = - container_of ( ctx, struct efi_sputc_context, ctx ); - - if ( ctx->len < sctx->max_wlen ) - sctx->buf[ctx->len] = c; -} - -/** - * Write a formatted string to a wide-character buffer - * - * @v wbuf Buffer into which to write the string - * @v wsize Size of buffer (in wide characters) - * @v fmt Format string - * @v args Arguments corresponding to the format string - * @ret wlen Length of formatted string (in wide characters) - * - * If the buffer is too small to contain the string, the returned - * length is the length that would have been written had enough space - * been available. - */ -int efi_vsnprintf ( wchar_t *wbuf, size_t wsize, const char *fmt, - va_list args ) { - struct efi_sputc_context sctx; - size_t wlen; - size_t wend; - - /* Hand off to vcprintf */ - sctx.ctx.handler = efi_printf_sputc; - sctx.buf = wbuf; - sctx.max_wlen = wsize; - wlen = vcprintf ( &sctx.ctx, fmt, args ); - - /* Add trailing NUL */ - if ( wsize ) { - wend = wsize - 1; - if ( wlen < wend ) - wend = wlen; - wbuf[wend] = '\0'; - } - - return wlen; -} - -/** - * Write a formatted string to a buffer - * - * @v wbuf Buffer into which to write the string - * @v wsize Size of buffer (in wide characters) - * @v fmt Format string - * @v ... Arguments corresponding to the format string - * @ret wlen Length of formatted string (in wide characters) - */ -int efi_snprintf ( wchar_t *wbuf, size_t wsize, const char *fmt, ... ) { - va_list args; - int i; - - va_start ( args, fmt ); - i = efi_vsnprintf ( wbuf, wsize, fmt, args ); - va_end ( args ); - return i; -} - -/** - * Version of efi_vsnprintf() that accepts a signed buffer size - * - * @v wbuf Buffer into which to write the string - * @v swsize Size of buffer (in wide characters) - * @v fmt Format string - * @v args Arguments corresponding to the format string - * @ret wlen Length of formatted string (in wide characters) - */ -int efi_vssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt, - va_list args ) { - - /* Treat negative buffer size as zero buffer size */ - if ( swsize < 0 ) - swsize = 0; - - /* Hand off to vsnprintf */ - return efi_vsnprintf ( wbuf, swsize, fmt, args ); -} - -/** - * Version of efi_vsnprintf() that accepts a signed buffer size - * - * @v wbuf Buffer into which to write the string - * @v swsize Size of buffer (in wide characters) - * @v fmt Format string - * @v ... Arguments corresponding to the format string - * @ret wlen Length of formatted string (in wide characters) - */ -int efi_ssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt, ... ) { - va_list args; - int len; - - /* Hand off to vssnprintf */ - va_start ( args, fmt ); - len = efi_vssnprintf ( wbuf, swsize, fmt, args ); - va_end ( args ); - return len; -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_time.c b/qemu/roms/ipxe/src/interface/efi/efi_time.c deleted file mode 100644 index 983a0ef5c..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_time.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2015 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 <string.h> -#include <errno.h> -#include <time.h> -#include <ipxe/time.h> -#include <ipxe/efi/efi.h> - -/** @file - * - * EFI time source - * - */ - -/** - * Get current time in seconds - * - * @ret time Time, in seconds - */ -static time_t efi_get_time ( void ) { - EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices; - EFI_TIME time; - struct tm tm; - EFI_STATUS efirc; - int rc; - - /* Get current time and date */ - if ( ( efirc = rs->GetTime ( &time, NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( rs, "EFITIME could not get system time: %s\n", - strerror ( rc ) ); - /* Nothing meaningful we can return */ - return 0; - } - - /* Construct broken-down time */ - memset ( &tm, 0, sizeof ( tm ) ); - tm.tm_sec = time.Second; - tm.tm_min = time.Minute; - tm.tm_hour = time.Hour; - tm.tm_mday = time.Day; - tm.tm_mon = ( time.Month - 1 ); - tm.tm_year = ( time.Year - 1900 ); - DBGC ( rs, "EFITIME is %04d-%02d-%02d %02d:%02d:%02d\n", - ( tm.tm_year + 1900 ), ( tm.tm_mon + 1 ), - tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); - - /* Convert to seconds since the Epoch */ - return mktime ( &tm ); -} - -PROVIDE_TIME ( efi, time_now, efi_get_time ); diff --git a/qemu/roms/ipxe/src/interface/efi/efi_timer.c b/qemu/roms/ipxe/src/interface/efi/efi_timer.c deleted file mode 100644 index 81620c92c..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_timer.c +++ /dev/null @@ -1,128 +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 <string.h> -#include <errno.h> -#include <limits.h> -#include <assert.h> -#include <unistd.h> -#include <ipxe/timer.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/Protocol/Cpu.h> - -/** @file - * - * iPXE timer API for EFI - * - */ - -/** Scale factor to apply to CPU timer 0 - * - * The timer is scaled down in order to ensure that reasonable values - * for "number of ticks" don't exceed the size of an unsigned long. - */ -#define EFI_TIMER0_SHIFT 12 - -/** Calibration time */ -#define EFI_CALIBRATE_DELAY_MS 1 - -/** CPU protocol */ -static EFI_CPU_ARCH_PROTOCOL *cpu_arch; -EFI_REQUIRE_PROTOCOL ( EFI_CPU_ARCH_PROTOCOL, &cpu_arch ); - -/** - * Delay for a fixed number of microseconds - * - * @v usecs Number of microseconds for which to delay - */ -static void efi_udelay ( unsigned long usecs ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_STATUS efirc; - int rc; - - if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBG ( "EFI could not delay for %ldus: %s\n", - usecs, strerror ( rc ) ); - /* Probably screwed */ - } -} - -/** - * Get current system time in ticks - * - * @ret ticks Current time, in ticks - */ -static unsigned long efi_currticks ( void ) { - UINT64 time; - EFI_STATUS efirc; - int rc; - - /* Read CPU timer 0 (TSC) */ - if ( ( efirc = cpu_arch->GetTimerValue ( cpu_arch, 0, &time, - NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBG ( "EFI could not read CPU timer: %s\n", strerror ( rc ) ); - /* Probably screwed */ - return -1UL; - } - - return ( time >> EFI_TIMER0_SHIFT ); -} - -/** - * Get number of ticks per second - * - * @ret ticks_per_sec Number of ticks per second - */ -static unsigned long efi_ticks_per_sec ( void ) { - static unsigned long ticks_per_sec = 0; - - /* Calibrate timer, if necessary. EFI does nominally provide - * the timer speed via the (optional) TimerPeriod parameter to - * the GetTimerValue() call, but it gets the speed slightly - * wrong. By up to three orders of magnitude. Not helpful. - */ - if ( ! ticks_per_sec ) { - unsigned long start; - unsigned long elapsed; - - DBG ( "Calibrating EFI timer with a %d ms delay\n", - EFI_CALIBRATE_DELAY_MS ); - start = currticks(); - mdelay ( EFI_CALIBRATE_DELAY_MS ); - elapsed = ( currticks() - start ); - ticks_per_sec = ( elapsed * ( 1000 / EFI_CALIBRATE_DELAY_MS )); - DBG ( "EFI CPU timer calibrated at %ld ticks in %d ms (%ld " - "ticks/sec)\n", elapsed, EFI_CALIBRATE_DELAY_MS, - ticks_per_sec ); - } - - return ticks_per_sec; -} - -PROVIDE_TIMER ( efi, udelay, efi_udelay ); -PROVIDE_TIMER ( efi, currticks, efi_currticks ); -PROVIDE_TIMER ( efi, ticks_per_sec, efi_ticks_per_sec ); diff --git a/qemu/roms/ipxe/src/interface/efi/efi_uaccess.c b/qemu/roms/ipxe/src/interface/efi/efi_uaccess.c deleted file mode 100644 index e058be66b..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_uaccess.c +++ /dev/null @@ -1,44 +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/uaccess.h> -#include <ipxe/efi/efi.h> - -/** @file - * - * iPXE user access API for EFI - * - */ - -PROVIDE_UACCESS_INLINE ( efi, phys_to_user ); -PROVIDE_UACCESS_INLINE ( efi, user_to_phys ); -PROVIDE_UACCESS_INLINE ( efi, virt_to_user ); -PROVIDE_UACCESS_INLINE ( efi, user_to_virt ); -PROVIDE_UACCESS_INLINE ( efi, userptr_add ); -PROVIDE_UACCESS_INLINE ( efi, memcpy_user ); -PROVIDE_UACCESS_INLINE ( efi, memmove_user ); -PROVIDE_UACCESS_INLINE ( efi, memset_user ); -PROVIDE_UACCESS_INLINE ( efi, strlen_user ); -PROVIDE_UACCESS_INLINE ( efi, memchr_user ); diff --git a/qemu/roms/ipxe/src/interface/efi/efi_umalloc.c b/qemu/roms/ipxe/src/interface/efi/efi_umalloc.c deleted file mode 100644 index e3f1dacc2..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_umalloc.c +++ /dev/null @@ -1,108 +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 <string.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/umalloc.h> -#include <ipxe/efi/efi.h> - -/** @file - * - * iPXE user memory allocation API for EFI - * - */ - -/** Equivalent of NOWHERE for user pointers */ -#define UNOWHERE ( ~UNULL ) - -/** - * 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 efi_urealloc ( userptr_t old_ptr, size_t new_size ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_PHYSICAL_ADDRESS phys_addr; - unsigned int new_pages, old_pages; - userptr_t new_ptr = UNOWHERE; - size_t old_size; - EFI_STATUS efirc; - int rc; - - /* Allocate new memory if necessary. If allocation fails, - * return without touching the old block. - */ - if ( new_size ) { - new_pages = ( EFI_SIZE_TO_PAGES ( new_size ) + 1 ); - if ( ( efirc = bs->AllocatePages ( AllocateAnyPages, - EfiBootServicesData, - new_pages, - &phys_addr ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBG ( "EFI could not allocate %d pages: %s\n", - new_pages, strerror ( rc ) ); - return UNULL; - } - assert ( phys_addr != 0 ); - new_ptr = phys_to_user ( phys_addr + EFI_PAGE_SIZE ); - copy_to_user ( new_ptr, -EFI_PAGE_SIZE, - &new_size, sizeof ( new_size ) ); - DBG ( "EFI allocated %d pages at %llx\n", - new_pages, phys_addr ); - } - - /* Copy across relevant part of the old data region (if any), - * then free it. Note that at this point either (a) new_ptr - * is valid, or (b) new_size is 0; either way, the memcpy() is - * valid. - */ - if ( old_ptr && ( old_ptr != UNOWHERE ) ) { - copy_from_user ( &old_size, old_ptr, -EFI_PAGE_SIZE, - sizeof ( old_size ) ); - memcpy_user ( new_ptr, 0, old_ptr, 0, - ( (old_size < new_size) ? old_size : new_size )); - old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 ); - phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE ); - if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){ - rc = -EEFI ( efirc ); - DBG ( "EFI could not free %d pages at %llx: %s\n", - old_pages, phys_addr, strerror ( rc ) ); - /* Not fatal; we have leaked memory but successfully - * allocated (if asked to do so). - */ - } - DBG ( "EFI freed %d pages at %llx\n", old_pages, phys_addr ); - } - - return new_ptr; -} - -PROVIDE_UMALLOC ( efi, urealloc, efi_urealloc ); diff --git a/qemu/roms/ipxe/src/interface/efi/efi_utils.c b/qemu/roms/ipxe/src/interface/efi/efi_utils.c deleted file mode 100644 index 936ad48ec..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_utils.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2011 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 <stdio.h> -#include <string.h> -#include <errno.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_pci.h> -#include <ipxe/efi/efi_utils.h> - -/** @file - * - * EFI utilities - * - */ - -/** - * Find end of device path - * - * @v path Path to device - * @ret path_end End of device path - */ -EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) { - - while ( path->Type != END_DEVICE_PATH_TYPE ) { - path = ( ( ( void * ) path ) + - /* There's this amazing new-fangled thing known as - * a UINT16, but who wants to use one of those? */ - ( ( path->Length[1] << 8 ) | path->Length[0] ) ); - } - - return path; -} - -/** - * Locate parent device supporting a given protocol - * - * @v device EFI device handle - * @v protocol Protocol GUID - * @v parent Parent EFI device handle to fill in - * @ret rc Return status code - */ -int efi_locate_device ( EFI_HANDLE device, EFI_GUID *protocol, - EFI_HANDLE *parent ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - union { - EFI_DEVICE_PATH_PROTOCOL *path; - void *interface; - } path; - EFI_DEVICE_PATH_PROTOCOL *devpath; - EFI_STATUS efirc; - int rc; - - /* Get device path */ - if ( ( efirc = bs->OpenProtocol ( device, - &efi_device_path_protocol_guid, - &path.interface, - efi_image_handle, device, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - rc = -EEFI ( efirc ); - DBGC ( device, "EFIDEV %p %s cannot open device path: %s\n", - device, efi_handle_name ( device ), strerror ( rc ) ); - goto err_open_device_path; - } - devpath = path.path; - - /* Check for presence of specified protocol */ - if ( ( efirc = bs->LocateDevicePath ( protocol, &devpath, - parent ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( device, "EFIDEV %p %s has no parent supporting %s: %s\n", - device, efi_handle_name ( device ), - efi_guid_ntoa ( protocol ), strerror ( rc ) ); - goto err_locate_protocol; - } - - /* Success */ - rc = 0; - - err_locate_protocol: - bs->CloseProtocol ( device, &efi_device_path_protocol_guid, - efi_image_handle, device ); - err_open_device_path: - return rc; -} - -/** - * Add EFI device as child of another EFI device - * - * @v parent EFI parent device handle - * @v child EFI child device handle - * @ret rc Return status code - */ -int efi_child_add ( EFI_HANDLE parent, EFI_HANDLE child ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - void *devpath; - EFI_STATUS efirc; - int rc; - - /* Re-open the device path protocol */ - if ( ( efirc = bs->OpenProtocol ( parent, - &efi_device_path_protocol_guid, - &devpath, - efi_image_handle, child, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( parent, "EFIDEV %p %s could not add child", - parent, efi_handle_name ( parent ) ); - DBGC ( parent, " %p %s: %s\n", child, - efi_handle_name ( child ), strerror ( rc ) ); - DBGC_EFI_OPENERS ( parent, parent, - &efi_device_path_protocol_guid ); - return rc; - } - - DBGC2 ( parent, "EFIDEV %p %s added child", - parent, efi_handle_name ( parent ) ); - DBGC2 ( parent, " %p %s\n", child, efi_handle_name ( child ) ); - return 0; -} - -/** - * Remove EFI device as child of another EFI device - * - * @v parent EFI parent device handle - * @v child EFI child device handle - */ -void efi_child_del ( EFI_HANDLE parent, EFI_HANDLE child ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - bs->CloseProtocol ( parent, &efi_device_path_protocol_guid, - efi_image_handle, child ); - DBGC2 ( parent, "EFIDEV %p %s removed child", - parent, efi_handle_name ( parent ) ); - DBGC2 ( parent, " %p %s\n", - child, efi_handle_name ( child ) ); -} - -/** - * Get underlying PCI device information - * - * @v device EFI device handle - * @v prefix Device name prefix - * @v dev Generic device to fill in - * @ret rc Return status code - */ -static int efi_pci_info ( EFI_HANDLE device, const char *prefix, - struct device *dev ) { - EFI_HANDLE pci_device; - struct pci_device pci; - int rc; - - /* Find parent PCI device */ - if ( ( rc = efi_locate_device ( device, &efi_pci_io_protocol_guid, - &pci_device ) ) != 0 ) { - DBGC ( device, "EFIDEV %p %s is not a PCI device: %s\n", - device, efi_handle_name ( device ), strerror ( rc ) ); - return rc; - } - - /* Get PCI device information */ - if ( ( rc = efipci_info ( pci_device, &pci ) ) != 0 ) { - DBGC ( device, "EFIDEV %p %s could not get PCI information: " - "%s\n", device, efi_handle_name ( device ), - strerror ( rc ) ); - return rc; - } - - /* Populate device information */ - memcpy ( &dev->desc, &pci.dev.desc, sizeof ( dev->desc ) ); - snprintf ( dev->name, sizeof ( dev->name ), "%s-%s", - prefix, pci.dev.name ); - - return 0; -} - -/** - * Get underlying device information - * - * @v device EFI device handle - * @v prefix Device name prefix - * @v dev Generic device to fill in - */ -void efi_device_info ( EFI_HANDLE device, const char *prefix, - struct device *dev ) { - int rc; - - /* Try getting underlying PCI device information */ - if ( ( rc = efi_pci_info ( device, prefix, dev ) ) == 0 ) - return; - - /* If we cannot get any underlying device information, fall - * back to providing information about the EFI handle. - */ - DBGC ( device, "EFIDEV %p %s could not get underlying device " - "information\n", device, efi_handle_name ( device ) ); - dev->desc.bus_type = BUS_TYPE_EFI; - snprintf ( dev->name, sizeof ( dev->name ), "%s-%p", prefix, device ); -} diff --git a/qemu/roms/ipxe/src/interface/efi/efi_watchdog.c b/qemu/roms/ipxe/src/interface/efi/efi_watchdog.c deleted file mode 100644 index 7061f81d8..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_watchdog.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2015 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 - * - * EFI watchdog holdoff timer - * - */ - -#include <errno.h> -#include <string.h> -#include <ipxe/retry.h> -#include <ipxe/timer.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_watchdog.h> - -/** Watchdog holdoff interval (in seconds) */ -#define WATCHDOG_HOLDOFF_SECS 10 - -/** Watchdog timeout (in seconds) */ -#define WATCHDOG_TIMEOUT_SECS ( 5 * 60 ) - -/** Watchdog code (to be logged on watchdog timeout) */ -#define WATCHDOG_CODE 0x6950584544454144ULL - -/** Watchdog data (to be logged on watchdog timeout) */ -#define WATCHDOG_DATA L"iPXE"; - -/** - * Hold off watchdog timer - * - * @v retry Retry timer - * @v over Failure indicator - */ -static void efi_watchdog_expired ( struct retry_timer *timer, - int over __unused ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - static CHAR16 data[] = WATCHDOG_DATA; - EFI_STATUS efirc; - int rc; - - DBGC2 ( timer, "EFI holding off watchdog timer\n" ); - - /* Restart this holdoff timer */ - start_timer_fixed ( timer, ( WATCHDOG_HOLDOFF_SECS * TICKS_PER_SEC ) ); - - /* Reset watchdog timer */ - if ( ( efirc = bs->SetWatchdogTimer ( WATCHDOG_TIMEOUT_SECS, - WATCHDOG_CODE, sizeof ( data ), - data ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( timer, "EFI could not set watchdog timer: %s\n", - strerror ( rc ) ); - return; - } -} - -/** Watchdog holdoff timer */ -struct retry_timer efi_watchdog = TIMER_INIT ( efi_watchdog_expired ); diff --git a/qemu/roms/ipxe/src/interface/efi/efi_wrap.c b/qemu/roms/ipxe/src/interface/efi/efi_wrap.c deleted file mode 100644 index 2ea184e97..000000000 --- a/qemu/roms/ipxe/src/interface/efi/efi_wrap.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2014 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 - * - * EFI image wrapping - * - */ - -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/Protocol/LoadedImage.h> -#include <ipxe/efi/efi_wrap.h> - -/** EFI system table wrapper */ -static EFI_SYSTEM_TABLE efi_systab_wrapper; - -/** EFI boot services table wrapper */ -static EFI_BOOT_SERVICES efi_bs_wrapper; - -/** Colour for debug messages */ -#define colour &efi_systab_wrapper - -/** - * Convert EFI status code to text - * - * @v efirc EFI status code - * @ret text EFI status code text - */ -static const char * efi_status ( EFI_STATUS efirc ) { - static char buf[ 19 /* "0xXXXXXXXXXXXXXXXX" + NUL */ ]; - - switch ( efirc ) { - case EFI_SUCCESS : return "0"; - case EFI_LOAD_ERROR : return "LOAD_ERROR"; - case EFI_INVALID_PARAMETER : return "INVALID_PARAMETER"; - case EFI_UNSUPPORTED : return "UNSUPPORTED"; - case EFI_BAD_BUFFER_SIZE : return "BAD_BUFFER_SIZE"; - case EFI_BUFFER_TOO_SMALL : return "BUFFER_TOO_SMALL"; - case EFI_NOT_READY : return "NOT_READY"; - case EFI_DEVICE_ERROR : return "DEVICE_ERROR"; - case EFI_WRITE_PROTECTED : return "WRITE_PROTECTED"; - case EFI_OUT_OF_RESOURCES : return "OUT_OF_RESOURCES"; - case EFI_VOLUME_CORRUPTED : return "VOLUME_CORRUPTED"; - case EFI_VOLUME_FULL : return "VOLUME_FULL"; - case EFI_NO_MEDIA : return "NO_MEDIA"; - case EFI_MEDIA_CHANGED : return "MEDIA_CHANGED"; - case EFI_NOT_FOUND : return "NOT_FOUND"; - case EFI_ACCESS_DENIED : return "ACCESS_DENIED"; - case EFI_NO_RESPONSE : return "NO_RESPONSE"; - case EFI_NO_MAPPING : return "NO_MAPPING"; - case EFI_TIMEOUT : return "TIMEOUT"; - case EFI_NOT_STARTED : return "NOT_STARTED"; - case EFI_ALREADY_STARTED : return "ALREADY_STARTED"; - case EFI_ABORTED : return "ABORTED"; - case EFI_ICMP_ERROR : return "ICMP_ERROR"; - case EFI_TFTP_ERROR : return "TFTP_ERROR"; - case EFI_PROTOCOL_ERROR : return "PROTOCOL_ERROR"; - case EFI_INCOMPATIBLE_VERSION : return "INCOMPATIBLE_VERSION"; - case EFI_SECURITY_VIOLATION : return "SECURITY_VIOLATION"; - case EFI_CRC_ERROR : return "CRC_ERROR"; - case EFI_END_OF_MEDIA : return "END_OF_MEDIA"; - case EFI_END_OF_FILE : return "END_OF_FILE"; - case EFI_INVALID_LANGUAGE : return "INVALID_LANGUAGE"; - case EFI_COMPROMISED_DATA : return "COMPROMISED_DATA"; - case EFI_WARN_UNKNOWN_GLYPH : return "WARN_UNKNOWN_GLYPH"; - case EFI_WARN_DELETE_FAILURE : return "WARN_DELETE_FAILURE"; - case EFI_WARN_WRITE_FAILURE : return "WARN_WRITE_FAILURE"; - case EFI_WARN_BUFFER_TOO_SMALL : return "WARN_BUFFER_TOO_SMALL"; - case EFI_WARN_STALE_DATA : return "WARN_STALE_DATA"; - default: - snprintf ( buf, sizeof ( buf ), "%#lx", - ( unsigned long ) efirc ); - return buf; - } -} - -/** - * Wrap HandleProtocol() - * - */ -static EFI_STATUS EFIAPI -efi_handle_protocol_wrapper ( EFI_HANDLE handle, EFI_GUID *protocol, - VOID **interface ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - void *retaddr = __builtin_return_address ( 0 ); - EFI_STATUS efirc; - - DBGC ( colour, "HandleProtocol ( %p %s, %s, ... ) ", handle, - efi_handle_name ( handle ), efi_guid_ntoa ( protocol ) ); - efirc = bs->HandleProtocol ( handle, protocol, interface ); - DBGC ( colour, "= %s ( %p ) -> %p\n", - efi_status ( efirc ), *interface, retaddr ); - return efirc; -} - -/** - * Wrap LocateHandle() - * - */ -static EFI_STATUS EFIAPI -efi_locate_handle_wrapper ( EFI_LOCATE_SEARCH_TYPE search_type, - EFI_GUID *protocol, VOID *search_key, - UINTN *buffer_size, EFI_HANDLE *buffer ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - void *retaddr = __builtin_return_address ( 0 ); - EFI_STATUS efirc; - - DBGC ( colour, "LocateHandle ( %d, %s, ..., %zd, ... ) ", search_type, - efi_guid_ntoa ( protocol ), ( ( size_t ) *buffer_size ) ); - efirc = bs->LocateHandle ( search_type, protocol, search_key, - buffer_size, buffer ); - DBGC ( colour, "= %s ( %zd ) -> %p\n", - efi_status ( efirc ), ( ( size_t ) *buffer_size ), retaddr ); - return efirc; -} - -/** - * Wrap LocateDevicePath() - * - */ -static EFI_STATUS EFIAPI -efi_locate_device_path_wrapper ( EFI_GUID *protocol, - EFI_DEVICE_PATH_PROTOCOL **device_path, - EFI_HANDLE *device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - void *retaddr = __builtin_return_address ( 0 ); - EFI_STATUS efirc; - - DBGC ( colour, "LocateDevicePath ( %s, %s, ... ) ", - efi_guid_ntoa ( protocol ), efi_devpath_text ( *device_path ) ); - efirc = bs->LocateDevicePath ( protocol, device_path, device ); - DBGC ( colour, "= %s ( %p, ", - efi_status ( efirc ), efi_devpath_text ( *device_path ) ); - DBGC ( colour, "%p %s ) -> %p\n", - *device, efi_handle_name ( *device ), retaddr ); - return efirc; -} - -/** - * Wrap LoadImage() - * - */ -static EFI_STATUS EFIAPI -efi_load_image_wrapper ( BOOLEAN boot_policy, EFI_HANDLE parent_image_handle, - EFI_DEVICE_PATH_PROTOCOL *device_path, - VOID *source_buffer, UINTN source_size, - EFI_HANDLE *image_handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - void *retaddr = __builtin_return_address ( 0 ); - EFI_STATUS efirc; - - DBGC ( colour, "LoadImage ( %d, %p %s, ", boot_policy, - parent_image_handle, efi_handle_name ( parent_image_handle ) ); - DBGC ( colour, "%s, %p, %#llx, ... ) ", - efi_devpath_text ( device_path ), source_buffer, - ( ( unsigned long long ) source_size ) ); - efirc = bs->LoadImage ( boot_policy, parent_image_handle, device_path, - source_buffer, source_size, image_handle ); - DBGC ( colour, "= %s ( ", efi_status ( efirc ) ); - if ( efirc == 0 ) { - DBGC ( colour, "%p %s ", *image_handle, - efi_handle_name ( *image_handle ) ); - } - DBGC ( colour, ") -> %p\n", retaddr ); - - /* Wrap the new image */ - if ( efirc == 0 ) - efi_wrap ( *image_handle ); - - return efirc; -} - -/** - * Wrap ExitBootServices() - * - */ -static EFI_STATUS EFIAPI -efi_exit_boot_services_wrapper ( EFI_HANDLE image_handle, UINTN map_key ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - void *retaddr = __builtin_return_address ( 0 ); - EFI_STATUS efirc; - - DBGC ( colour, "ExitBootServices ( %p %s, %#llx ) ", - image_handle, efi_handle_name ( image_handle ), - ( ( unsigned long long ) map_key ) ); - efirc = bs->ExitBootServices ( image_handle, map_key ); - DBGC ( colour, "= %s -> %p\n", efi_status ( efirc ), retaddr ); - return efirc; -} - -/** - * Wrap OpenProtocol() - * - */ -static EFI_STATUS EFIAPI -efi_open_protocol_wrapper ( EFI_HANDLE handle, EFI_GUID *protocol, - VOID **interface, EFI_HANDLE agent_handle, - EFI_HANDLE controller_handle, UINT32 attributes ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - void *retaddr = __builtin_return_address ( 0 ); - EFI_STATUS efirc; - - DBGC ( colour, "OpenProtocol ( %p %s, %s, ..., ", handle, - efi_handle_name ( handle ), efi_guid_ntoa ( protocol ) ); - DBGC ( colour, "%p %s, ", agent_handle, - efi_handle_name ( agent_handle ) ); - DBGC ( colour, "%p %s, %#x ) ", controller_handle, - efi_handle_name ( controller_handle ), attributes ); - efirc = bs->OpenProtocol ( handle, protocol, interface, agent_handle, - controller_handle, attributes ); - DBGC ( colour, "= %s ( %p ) -> %p\n", - efi_status ( efirc ), *interface, retaddr ); - return efirc; -} - -/** - * Wrap LocateProtocol() - * - */ -static EFI_STATUS EFIAPI -efi_locate_protocol_wrapper ( EFI_GUID *protocol, VOID *registration, - VOID **interface ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - void *retaddr = __builtin_return_address ( 0 ); - EFI_STATUS efirc; - - DBGC ( colour, "LocateProtocol ( %s, %p, ... ) ", - efi_guid_ntoa ( protocol ), registration ); - efirc = bs->LocateProtocol ( protocol, registration, interface ); - DBGC ( colour, "= %s ( %p ) -> %p\n", - efi_status ( efirc ), *interface, retaddr ); - return efirc; -} - -/** - * Wrap the calls made by a loaded image - * - * @v handle Image handle - */ - void efi_wrap ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - union { - EFI_LOADED_IMAGE_PROTOCOL *image; - void *intf; - } loaded; - EFI_STATUS efirc; - int rc; - - /* Do nothing unless debugging is enabled */ - if ( ! DBG_LOG ) - return; - - /* Populate table wrappers */ - memcpy ( &efi_systab_wrapper, efi_systab, - sizeof ( efi_systab_wrapper ) ); - memcpy ( &efi_bs_wrapper, bs, sizeof ( efi_bs_wrapper ) ); - efi_systab_wrapper.BootServices = &efi_bs_wrapper; - efi_bs_wrapper.HandleProtocol = efi_handle_protocol_wrapper; - efi_bs_wrapper.LocateHandle = efi_locate_handle_wrapper; - efi_bs_wrapper.LocateDevicePath = efi_locate_device_path_wrapper; - efi_bs_wrapper.LoadImage = efi_load_image_wrapper; - efi_bs_wrapper.ExitBootServices = efi_exit_boot_services_wrapper; - efi_bs_wrapper.OpenProtocol = efi_open_protocol_wrapper; - efi_bs_wrapper.LocateProtocol = efi_locate_protocol_wrapper; - - /* Open loaded image protocol */ - if ( ( efirc = bs->OpenProtocol ( handle, - &efi_loaded_image_protocol_guid, - &loaded.intf, efi_image_handle, NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - rc = -EEFI ( efirc ); - DBGC ( colour, "Could not get loaded image protocol for %p %s: " - "%s\n", handle, efi_handle_name ( handle ), - strerror ( rc ) ); - return; - } - - /* Provide system table wrapper to image */ - loaded.image->SystemTable = &efi_systab_wrapper; - DBGC ( colour, "Wrapped image %p %s at base %p has protocols:\n", - handle, efi_handle_name ( handle ), loaded.image->ImageBase ); - DBGC_EFI_PROTOCOLS ( colour, handle ); - DBGC ( colour, "Parent image %p %s\n", loaded.image->ParentHandle, - efi_handle_name ( loaded.image->ParentHandle ) ); - DBGC ( colour, "Device %p %s ", loaded.image->DeviceHandle, - efi_handle_name ( loaded.image->DeviceHandle ) ); - DBGC ( colour, "file %p %s\n", loaded.image->FilePath, - efi_devpath_text ( loaded.image->FilePath ) ); - - /* Close loaded image protocol */ - bs->CloseProtocol ( handle, &efi_loaded_image_protocol_guid, - efi_image_handle, NULL ); -} |