diff options
Diffstat (limited to 'qemu/roms/ipxe/src/interface')
39 files changed, 0 insertions, 11822 deletions
diff --git a/qemu/roms/ipxe/src/interface/bofm/bofm.c b/qemu/roms/ipxe/src/interface/bofm/bofm.c deleted file mode 100644 index 545088dc6..000000000 --- a/qemu/roms/ipxe/src/interface/bofm/bofm.c +++ /dev/null @@ -1,345 +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 <stdint.h> -#include <string.h> -#include <errno.h> -#include <ipxe/uaccess.h> -#include <ipxe/list.h> -#include <ipxe/ethernet.h> -#include <ipxe/bofm.h> - -/** @file - * - * IBM BladeCenter Open Fabric Manager (BOFM) - * - */ - -/** List of BOFM devices */ -static LIST_HEAD ( bofmdevs ); - -/** - * Register BOFM device - * - * @v bofm BOFM device - * @ret rc Return status code - */ -int bofm_register ( struct bofm_device *bofm ) { - - list_add ( &bofm->list, &bofmdevs ); - DBG ( "BOFM: " PCI_FMT " registered using driver \"%s\"\n", - PCI_ARGS ( bofm->pci ), bofm->pci->id->name ); - return 0; -} - -/** - * Unregister BOFM device - * - * @v bofm BOFM device - */ -void bofm_unregister ( struct bofm_device *bofm ) { - - list_del ( &bofm->list ); - DBG ( "BOFM: " PCI_FMT " unregistered\n", PCI_ARGS ( bofm->pci ) ); -} - -/** - * Find BOFM device matching PCI bus:dev.fn address - * - * @v busdevfn PCI bus:dev.fn address - * @ret bofm BOFM device, or NULL - */ -static struct bofm_device * bofm_find_busdevfn ( unsigned int busdevfn ) { - struct bofm_device *bofm; - - list_for_each_entry ( bofm, &bofmdevs, list ) { - if ( bofm->pci->busdevfn == busdevfn ) - return bofm; - } - return NULL; -} - -/** - * Find BOFM driver for PCI device - * - * @v pci PCI device - * @ret rc Return status code - */ -int bofm_find_driver ( struct pci_device *pci ) { - struct pci_driver *driver; - struct pci_device_id *id; - unsigned int i; - - for_each_table_entry ( driver, BOFM_DRIVERS ) { - for ( i = 0 ; i < driver->id_count ; i++ ) { - id = &driver->ids[i]; - if ( ( id->vendor == pci->vendor ) && - ( id->device == pci->device ) ) { - pci_set_driver ( pci, driver, id ); - return 0; - } - } - } - return -ENOENT; -} - -/** - * Probe PCI device for BOFM driver - * - * @v pci PCI device - * @ret rc Return status code - */ -static int bofm_probe ( struct pci_device *pci ) { - int rc; - - /* Probe device */ - if ( ( rc = pci_probe ( pci ) ) != 0 ) { - DBG ( "BOFM: " PCI_FMT " could not load driver: %s\n", - PCI_ARGS ( pci ), strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Remove PCI device - * - * @v pci PCI device - */ -static void bofm_remove ( struct pci_device *pci ) { - - /* Note that the IBM BIOS may re-read the expansion ROM after - * the BOFM initialisation call. The BOFM driver must ensure - * that the card is left in a state in which expansion ROM - * reads will succeed. (For example, if a card contains an - * embedded CPU that may issue reads to the same underlying - * flash device, and these reads are not locked against reads - * via the expansion ROM BAR, then the CPU must be stopped.) - * - * If this is not done, then occasional corrupted reads from - * the expansion ROM will be seen, and the BIOS may complain - * about a ROM checksum error. - */ - pci_remove ( pci ); - DBG ( "BOFM: " PCI_FMT " removed\n", PCI_ARGS ( pci ) ); -} - -/** - * Locate BOFM table section - * - * @v bofmtab BOFM table - * @v len Length of BOFM table - * @v magic Section magic - * @v bofmsec BOFM section header to fill in - * @ret offset Offset to section, or 0 if not found - */ -static size_t bofm_locate_section ( userptr_t bofmtab, size_t len, - uint32_t magic, - struct bofm_section_header *bofmsec ) { - size_t offset = sizeof ( struct bofm_global_header ); - - while ( offset < len ) { - copy_from_user ( bofmsec, bofmtab, offset, - sizeof ( *bofmsec ) ); - if ( bofmsec->magic == magic ) - return offset; - if ( bofmsec->magic == BOFM_DONE_MAGIC ) - break; - offset += ( sizeof ( *bofmsec ) + bofmsec->length ); - } - return 0; -} - -/** - * Process BOFM Ethernet parameter entry - * - * @v bofm BOFM device - * @v en EN parameter entry - * @ret rc Return status code - */ -static int bofm_en ( struct bofm_device *bofm, struct bofm_en *en ) { - uint8_t mac[6]; - int rc; - - /* Retrieve current MAC address */ - if ( ( rc = bofm->op->harvest ( bofm, en->mport, mac ) ) != 0 ) { - DBG ( "BOFM: " PCI_FMT " mport %d could not harvest: %s\n", - PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) ); - return rc; - } - - /* Harvest MAC address if necessary */ - if ( en->options & BOFM_EN_RQ_HVST_MASK ) { - DBG ( "BOFM: " PCI_FMT " mport %d harvested MAC %s\n", - PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( mac ) ); - memcpy ( en->mac_a, mac, sizeof ( en->mac_a ) ); - en->options |= ( BOFM_EN_EN_A | BOFM_EN_HVST ); - } - - /* Mark as changed if necessary */ - if ( ( en->options & BOFM_EN_EN_A ) && - ( memcmp ( en->mac_a, mac, sizeof ( en->mac_a ) ) != 0 ) ) { - DBG ( "BOFM: " PCI_FMT " mport %d MAC %s", - PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( mac ) ); - DBG ( " changed to %s\n", eth_ntoa ( en->mac_a ) ); - en->options |= BOFM_EN_CHG_CHANGED; - } - - /* Apply MAC address if necessary */ - if ( ( en->options & BOFM_EN_EN_A ) && - ( en->options & BOFM_EN_USAGE_ENTRY ) && - ( ! ( en->options & BOFM_EN_USAGE_HARVEST ) ) ) { - DBG ( "BOFM: " PCI_FMT " mport %d applied MAC %s\n", - PCI_ARGS ( bofm->pci ), en->mport, - eth_ntoa ( en->mac_a ) ); - memcpy ( mac, en->mac_a, sizeof ( mac ) ); - } - - /* Store MAC address */ - if ( ( rc = bofm->op->update ( bofm, en->mport, mac ) ) != 0 ) { - DBG ( "BOFM: " PCI_FMT " mport %d could not update: %s\n", - PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Process BOFM table - * - * @v bofmtab BOFM table - * @v pci PCI device - * @ret bofmrc BOFM return status - */ -int bofm ( userptr_t bofmtab, struct pci_device *pci ) { - struct bofm_global_header bofmhdr; - struct bofm_section_header bofmsec; - struct bofm_en en; - struct bofm_device *bofm; - size_t en_region_offset; - size_t en_offset; - int skip; - int rc; - int bofmrc; - - /* Read BOFM structure */ - copy_from_user ( &bofmhdr, bofmtab, 0, sizeof ( bofmhdr ) ); - if ( bofmhdr.magic != BOFM_IOAA_MAGIC ) { - DBG ( "BOFM: invalid table signature " BOFM_MAGIC_FMT "\n", - BOFM_MAGIC_ARGS ( bofmhdr.magic ) ); - bofmrc = BOFM_ERR_INVALID_ACTION; - goto err_bad_signature; - } - DBG ( "BOFM: " BOFM_MAGIC_FMT " (profile \"%s\")\n", - BOFM_MAGIC_ARGS ( bofmhdr.action ), bofmhdr.profile ); - - /* Determine whether or not we should skip normal POST - * initialisation. - */ - switch ( bofmhdr.action ) { - case BOFM_ACTION_UPDT: - case BOFM_ACTION_DFLT: - case BOFM_ACTION_HVST: - skip = BOFM_SKIP_INIT; - break; - case BOFM_ACTION_PARM: - case BOFM_ACTION_NONE: - skip = 0; - break; - default: - DBG ( "BOFM: invalid action " BOFM_MAGIC_FMT "\n", - BOFM_MAGIC_ARGS ( bofmhdr.action ) ); - bofmrc = BOFM_ERR_INVALID_ACTION; - goto err_bad_action; - } - - /* Find BOFM driver */ - if ( ( rc = bofm_find_driver ( pci ) ) != 0 ) { - DBG ( "BOFM: " PCI_FMT " has no driver\n", PCI_ARGS ( pci ) ); - bofmrc = BOFM_ERR_DEVICE_ERROR; - goto err_find_driver; - } - - /* Probe driver for PCI device */ - if ( ( rc = bofm_probe ( pci ) ) != 0 ) { - bofmrc = BOFM_ERR_DEVICE_ERROR; - goto err_probe; - } - - /* Locate EN section, if present */ - en_region_offset = bofm_locate_section ( bofmtab, bofmhdr.length, - BOFM_EN_MAGIC, &bofmsec ); - if ( ! en_region_offset ) { - DBG ( "BOFM: No EN section found\n" ); - bofmrc = ( BOFM_SUCCESS | skip ); - goto err_no_en_section; - } - - /* Iterate through EN entries */ - for ( en_offset = ( en_region_offset + sizeof ( bofmsec ) ) ; - en_offset < ( en_region_offset + sizeof ( bofmsec ) + - bofmsec.length ) ; en_offset += sizeof ( en ) ) { - copy_from_user ( &en, bofmtab, en_offset, sizeof ( en ) ); - DBG2 ( "BOFM: EN entry found:\n" ); - DBG2_HDA ( en_offset, &en, sizeof ( en ) ); - if ( ( en.options & BOFM_EN_MAP_MASK ) != BOFM_EN_MAP_PFA ) { - DBG ( "BOFM: slot %d port %d has no PCI mapping\n", - en.slot, ( en.port + 1 ) ); - continue; - } - DBG ( "BOFM: slot %d port %d%s is " PCI_FMT " mport %d\n", - en.slot, ( en.port + 1 ), - ( ( en.slot || en.port ) ? "" : "(?)" ), - PCI_BUS ( en.busdevfn ), PCI_SLOT ( en.busdevfn ), - PCI_FUNC ( en.busdevfn ), en.mport ); - bofm = bofm_find_busdevfn ( en.busdevfn ); - if ( ! bofm ) { - DBG ( "BOFM: " PCI_FMT " mport %d ignored\n", - PCI_BUS ( en.busdevfn ), PCI_SLOT ( en.busdevfn ), - PCI_FUNC ( en.busdevfn ), en.mport ); - continue; - } - if ( ( rc = bofm_en ( bofm, &en ) ) == 0 ) { - en.options |= BOFM_EN_CSM_SUCCESS; - } else { - en.options |= BOFM_EN_CSM_FAILED; - } - DBG2 ( "BOFM: EN entry after processing:\n" ); - DBG2_HDA ( en_offset, &en, sizeof ( en ) ); - copy_to_user ( bofmtab, en_offset, &en, sizeof ( en ) ); - } - - bofmrc = ( BOFM_SUCCESS | skip ); - - err_no_en_section: - bofm_remove ( pci ); - err_probe: - err_find_driver: - err_bad_action: - err_bad_signature: - return bofmrc; -} 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 ); -} diff --git a/qemu/roms/ipxe/src/interface/hyperv/vmbus.c b/qemu/roms/ipxe/src/interface/hyperv/vmbus.c deleted file mode 100644 index 795929eae..000000000 --- a/qemu/roms/ipxe/src/interface/hyperv/vmbus.c +++ /dev/null @@ -1,1333 +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 (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 ); - -/** @file - * - * Hyper-V virtual machine bus - * - */ - -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <byteswap.h> -#include <ipxe/nap.h> -#include <ipxe/malloc.h> -#include <ipxe/iobuf.h> -#include <ipxe/hyperv.h> -#include <ipxe/vmbus.h> - -/** VMBus initial GPADL ID - * - * This is an opaque value with no meaning. The Linux kernel uses - * 0xe1e10. - */ -#define VMBUS_GPADL_MAGIC 0x18ae0000 - -/** - * Post message - * - * @v hv Hyper-V hypervisor - * @v header Message header - * @v len Length of message (including header) - * @ret rc Return status code - */ -static int vmbus_post_message ( struct hv_hypervisor *hv, - const struct vmbus_message_header *header, - size_t len ) { - struct vmbus *vmbus = hv->vmbus; - int rc; - - /* Post message */ - if ( ( rc = hv_post_message ( hv, VMBUS_MESSAGE_ID, VMBUS_MESSAGE_TYPE, - header, len ) ) != 0 ) { - DBGC ( vmbus, "VMBUS %p could not post message: %s\n", - vmbus, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Post empty message - * - * @v hv Hyper-V hypervisor - * @v type Message type - * @ret rc Return status code - */ -static int vmbus_post_empty_message ( struct hv_hypervisor *hv, - unsigned int type ) { - struct vmbus_message_header header = { .type = cpu_to_le32 ( type ) }; - - return vmbus_post_message ( hv, &header, sizeof ( header ) ); -} - -/** - * Wait for received message - * - * @v hv Hyper-V hypervisor - * @ret rc Return status code - */ -static int vmbus_wait_for_message ( struct hv_hypervisor *hv ) { - struct vmbus *vmbus = hv->vmbus; - int rc; - - /* Wait for message */ - if ( ( rc = hv_wait_for_message ( hv, VMBUS_MESSAGE_SINT ) ) != 0 ) { - DBGC ( vmbus, "VMBUS %p failed waiting for message: %s\n", - vmbus, strerror ( rc ) ); - return rc; - } - - /* Sanity check */ - if ( hv->message->received.type != cpu_to_le32 ( VMBUS_MESSAGE_TYPE ) ){ - DBGC ( vmbus, "VMBUS %p invalid message type %d\n", - vmbus, le32_to_cpu ( hv->message->received.type ) ); - return -EINVAL; - } - - return 0; -} - -/** - * Initiate contact - * - * @v hv Hyper-V hypervisor - * @v raw VMBus protocol (raw) version - * @ret rc Return status code - */ -static int vmbus_initiate_contact ( struct hv_hypervisor *hv, - unsigned int raw ) { - struct vmbus *vmbus = hv->vmbus; - const struct vmbus_version_response *version = &vmbus->message->version; - struct vmbus_initiate_contact initiate; - int rc; - - /* Construct message */ - memset ( &initiate, 0, sizeof ( initiate ) ); - initiate.header.type = cpu_to_le32 ( VMBUS_INITIATE_CONTACT ); - initiate.version.raw = cpu_to_le32 ( raw ); - initiate.intr = virt_to_phys ( vmbus->intr ); - initiate.monitor_in = virt_to_phys ( vmbus->monitor_in ); - initiate.monitor_out = virt_to_phys ( vmbus->monitor_out ); - - /* Post message */ - if ( ( rc = vmbus_post_message ( hv, &initiate.header, - sizeof ( initiate ) ) ) != 0 ) - return rc; - - /* Wait for response */ - if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 ) - return rc; - - /* Check response */ - if ( version->header.type != cpu_to_le32 ( VMBUS_VERSION_RESPONSE ) ) { - DBGC ( vmbus, "VMBUS %p unexpected version response type %d\n", - vmbus, le32_to_cpu ( version->header.type ) ); - return -EPROTO; - } - if ( ! version->supported ) { - DBGC ( vmbus, "VMBUS %p requested version not supported\n", - vmbus ); - return -ENOTSUP; - } - if ( version->version.raw != cpu_to_le32 ( raw ) ) { - DBGC ( vmbus, "VMBUS %p unexpected version %d.%d\n", - vmbus, le16_to_cpu ( version->version.major ), - le16_to_cpu ( version->version.minor ) ); - return -EPROTO; - } - - DBGC ( vmbus, "VMBUS %p initiated contact using version %d.%d\n", - vmbus, le16_to_cpu ( version->version.major ), - le16_to_cpu ( version->version.minor ) ); - return 0; -} - -/** - * Terminate contact - * - * @v hv Hyper-V hypervisor - * @ret rc Return status code - */ -static int vmbus_unload ( struct hv_hypervisor *hv ) { - struct vmbus *vmbus = hv->vmbus; - const struct vmbus_message_header *header = &vmbus->message->header; - int rc; - - /* Post message */ - if ( ( rc = vmbus_post_empty_message ( hv, VMBUS_UNLOAD ) ) != 0 ) - return rc; - - /* Wait for response */ - if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 ) - return rc; - - /* Check response */ - if ( header->type != cpu_to_le32 ( VMBUS_UNLOAD_RESPONSE ) ) { - DBGC ( vmbus, "VMBUS %p unexpected unload response type %d\n", - vmbus, le32_to_cpu ( header->type ) ); - return -EPROTO; - } - - return 0; -} - -/** - * Negotiate protocol version - * - * @v hv Hyper-V hypervisor - * @ret rc Return status code - */ -static int vmbus_negotiate_version ( struct hv_hypervisor *hv ) { - int rc; - - /* We require the ability to disconnect from and reconnect to - * VMBus; if we don't have this then there is no (viable) way - * for a loaded operating system to continue to use any VMBus - * devices. (There is also a small but non-zero risk that the - * host will continue to write to our interrupt and monitor - * pages, since the VMBUS_UNLOAD message in earlier versions - * is essentially a no-op.) - * - * This requires us to ensure that the host supports protocol - * version 3.0 (VMBUS_VERSION_WIN8_1). However, we can't - * actually _use_ protocol version 3.0, since doing so causes - * an iSCSI-booted Windows Server 2012 R2 VM to crash due to a - * NULL pointer dereference in vmbus.sys. - * - * To work around this problem, we first ensure that we can - * connect using protocol v3.0, then disconnect and reconnect - * using the oldest known protocol. - */ - - /* Initiate contact to check for required protocol support */ - if ( ( rc = vmbus_initiate_contact ( hv, VMBUS_VERSION_WIN8_1 ) ) != 0 ) - return rc; - - /* Terminate contact */ - if ( ( rc = vmbus_unload ( hv ) ) != 0 ) - return rc; - - /* Reinitiate contact using the oldest known protocol version */ - if ( ( rc = vmbus_initiate_contact ( hv, VMBUS_VERSION_WS2008 ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Establish GPA descriptor list - * - * @v vmdev VMBus device - * @v data Data buffer - * @v len Length of data buffer - * @ret gpadl GPADL ID, or negative error - */ -int vmbus_establish_gpadl ( struct vmbus_device *vmdev, userptr_t data, - size_t len ) { - struct hv_hypervisor *hv = vmdev->hv; - struct vmbus *vmbus = hv->vmbus; - physaddr_t addr = user_to_phys ( data, 0 ); - unsigned int pfn_count = hv_pfn_count ( addr, len ); - struct { - struct vmbus_gpadl_header gpadlhdr; - struct vmbus_gpa_range range; - uint64_t pfn[pfn_count]; - } __attribute__ (( packed )) gpadlhdr; - const struct vmbus_gpadl_created *created = &vmbus->message->created; - static unsigned int gpadl = VMBUS_GPADL_MAGIC; - unsigned int i; - int rc; - - /* Allocate GPADL ID */ - gpadl++; - - /* Construct message */ - memset ( &gpadlhdr, 0, sizeof ( gpadlhdr ) ); - gpadlhdr.gpadlhdr.header.type = cpu_to_le32 ( VMBUS_GPADL_HEADER ); - gpadlhdr.gpadlhdr.channel = cpu_to_le32 ( vmdev->channel ); - gpadlhdr.gpadlhdr.gpadl = cpu_to_le32 ( gpadl ); - gpadlhdr.gpadlhdr.range_len = - cpu_to_le16 ( ( sizeof ( gpadlhdr.range ) + - sizeof ( gpadlhdr.pfn ) ) ); - gpadlhdr.gpadlhdr.range_count = cpu_to_le16 ( 1 ); - gpadlhdr.range.len = cpu_to_le32 ( len ); - gpadlhdr.range.offset = cpu_to_le32 ( addr & ( PAGE_SIZE - 1 ) ); - for ( i = 0 ; i < pfn_count ; i++ ) - gpadlhdr.pfn[i] = ( ( addr / PAGE_SIZE ) + i ); - - /* Post message */ - if ( ( rc = vmbus_post_message ( hv, &gpadlhdr.gpadlhdr.header, - sizeof ( gpadlhdr ) ) ) != 0 ) - return rc; - - /* Wait for response */ - if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 ) - return rc; - - /* Check response */ - if ( created->header.type != cpu_to_le32 ( VMBUS_GPADL_CREATED ) ) { - DBGC ( vmdev, "VMBUS %s unexpected GPADL response type %d\n", - vmdev->dev.name, le32_to_cpu ( created->header.type ) ); - return -EPROTO; - } - if ( created->channel != cpu_to_le32 ( vmdev->channel ) ) { - DBGC ( vmdev, "VMBUS %s unexpected GPADL channel %d\n", - vmdev->dev.name, le32_to_cpu ( created->channel ) ); - return -EPROTO; - } - if ( created->gpadl != cpu_to_le32 ( gpadl ) ) { - DBGC ( vmdev, "VMBUS %s unexpected GPADL ID %#08x\n", - vmdev->dev.name, le32_to_cpu ( created->gpadl ) ); - return -EPROTO; - } - if ( created->status != 0 ) { - DBGC ( vmdev, "VMBUS %s GPADL creation failed: %#08x\n", - vmdev->dev.name, le32_to_cpu ( created->status ) ); - return -EPROTO; - } - - DBGC ( vmdev, "VMBUS %s GPADL %#08x is [%08lx,%08lx)\n", - vmdev->dev.name, gpadl, addr, ( addr + len ) ); - return gpadl; -} - -/** - * Tear down GPA descriptor list - * - * @v vmdev VMBus device - * @v gpadl GPADL ID - * @ret rc Return status code - */ -int vmbus_gpadl_teardown ( struct vmbus_device *vmdev, unsigned int gpadl ) { - struct hv_hypervisor *hv = vmdev->hv; - struct vmbus *vmbus = hv->vmbus; - struct vmbus_gpadl_teardown teardown; - const struct vmbus_gpadl_torndown *torndown = &vmbus->message->torndown; - int rc; - - /* Construct message */ - memset ( &teardown, 0, sizeof ( teardown ) ); - teardown.header.type = cpu_to_le32 ( VMBUS_GPADL_TEARDOWN ); - teardown.channel = cpu_to_le32 ( vmdev->channel ); - teardown.gpadl = cpu_to_le32 ( gpadl ); - - /* Post message */ - if ( ( rc = vmbus_post_message ( hv, &teardown.header, - sizeof ( teardown ) ) ) != 0 ) - return rc; - - /* Wait for response */ - if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 ) - return rc; - - /* Check response */ - if ( torndown->header.type != cpu_to_le32 ( VMBUS_GPADL_TORNDOWN ) ) { - DBGC ( vmdev, "VMBUS %s unexpected GPADL response type %d\n", - vmdev->dev.name, le32_to_cpu ( torndown->header.type ) ); - return -EPROTO; - } - if ( torndown->gpadl != cpu_to_le32 ( gpadl ) ) { - DBGC ( vmdev, "VMBUS %s unexpected GPADL ID %#08x\n", - vmdev->dev.name, le32_to_cpu ( torndown->gpadl ) ); - return -EPROTO; - } - - return 0; -} - -/** - * Open VMBus channel - * - * @v vmdev VMBus device - * @v op Channel operations - * @v out_len Outbound ring buffer length - * @v in_len Inbound ring buffer length - * @v mtu Maximum expected data packet length (including headers) - * @ret rc Return status code - * - * Both outbound and inbound ring buffer lengths must be a power of - * two and a multiple of PAGE_SIZE. The requirement to be a power of - * two is a policy decision taken to simplify the ring buffer indexing - * logic. - */ -int vmbus_open ( struct vmbus_device *vmdev, - struct vmbus_channel_operations *op, - size_t out_len, size_t in_len, size_t mtu ) { - struct hv_hypervisor *hv = vmdev->hv; - struct vmbus *vmbus = hv->vmbus; - struct vmbus_open_channel open; - const struct vmbus_open_channel_result *opened = - &vmbus->message->opened; - size_t len; - void *ring; - void *packet; - int gpadl; - uint32_t open_id; - int rc; - - /* Sanity checks */ - assert ( ( out_len % PAGE_SIZE ) == 0 ); - assert ( ( out_len & ( out_len - 1 ) ) == 0 ); - assert ( ( in_len % PAGE_SIZE ) == 0 ); - assert ( ( in_len & ( in_len - 1 ) ) == 0 ); - assert ( mtu >= ( sizeof ( struct vmbus_packet_header ) + - sizeof ( struct vmbus_packet_footer ) ) ); - - /* Allocate packet buffer */ - packet = malloc ( mtu ); - if ( ! packet ) { - rc = -ENOMEM; - goto err_alloc_packet; - } - - /* Allocate ring buffer */ - len = ( sizeof ( *vmdev->out ) + out_len + - sizeof ( *vmdev->in ) + in_len ); - assert ( ( len % PAGE_SIZE ) == 0 ); - ring = malloc_dma ( len, PAGE_SIZE ); - if ( ! ring ) { - rc = -ENOMEM; - goto err_alloc_ring; - } - memset ( ring, 0, len ); - - /* Establish GPADL for ring buffer */ - gpadl = vmbus_establish_gpadl ( vmdev, virt_to_user ( ring ), len ); - if ( gpadl < 0 ) { - rc = gpadl; - goto err_establish; - } - - /* Construct message */ - memset ( &open, 0, sizeof ( open ) ); - open.header.type = cpu_to_le32 ( VMBUS_OPEN_CHANNEL ); - open.channel = cpu_to_le32 ( vmdev->channel ); - open_id = random(); - open.id = open_id; /* Opaque random value: endianness irrelevant */ - open.gpadl = cpu_to_le32 ( gpadl ); - open.out_pages = ( ( sizeof ( *vmdev->out ) / PAGE_SIZE ) + - ( out_len / PAGE_SIZE ) ); - - /* Post message */ - if ( ( rc = vmbus_post_message ( hv, &open.header, - sizeof ( open ) ) ) != 0 ) - return rc; - - /* Wait for response */ - if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 ) - return rc; - - /* Check response */ - if ( opened->header.type != cpu_to_le32 ( VMBUS_OPEN_CHANNEL_RESULT ) ){ - DBGC ( vmdev, "VMBUS %s unexpected open response type %d\n", - vmdev->dev.name, le32_to_cpu ( opened->header.type ) ); - return -EPROTO; - } - if ( opened->channel != cpu_to_le32 ( vmdev->channel ) ) { - DBGC ( vmdev, "VMBUS %s unexpected opened channel %#08x\n", - vmdev->dev.name, le32_to_cpu ( opened->channel ) ); - return -EPROTO; - } - if ( opened->id != open_id /* Non-endian */ ) { - DBGC ( vmdev, "VMBUS %s unexpected open ID %#08x\n", - vmdev->dev.name, le32_to_cpu ( opened->id ) ); - return -EPROTO; - } - if ( opened->status != 0 ) { - DBGC ( vmdev, "VMBUS %s open failed: %#08x\n", - vmdev->dev.name, le32_to_cpu ( opened->status ) ); - return -EPROTO; - } - - /* Store channel parameters */ - vmdev->out_len = out_len; - vmdev->in_len = in_len; - vmdev->out = ring; - vmdev->in = ( ring + sizeof ( *vmdev->out ) + out_len ); - vmdev->gpadl = gpadl; - vmdev->op = op; - vmdev->mtu = mtu; - vmdev->packet = packet; - - DBGC ( vmdev, "VMBUS %s channel GPADL %#08x ring " - "[%#08lx,%#08lx,%#08lx)\n", vmdev->dev.name, vmdev->gpadl, - virt_to_phys ( vmdev->out ), virt_to_phys ( vmdev->in ), - ( virt_to_phys ( vmdev->out ) + len ) ); - return 0; - - vmbus_gpadl_teardown ( vmdev, vmdev->gpadl ); - err_establish: - free_dma ( ring, len ); - err_alloc_ring: - free ( packet ); - err_alloc_packet: - return rc; -} - -/** - * Close VMBus channel - * - * @v vmdev VMBus device - */ -void vmbus_close ( struct vmbus_device *vmdev ) { - struct hv_hypervisor *hv = vmdev->hv; - struct vmbus_close_channel close; - size_t len; - int rc; - - /* Construct message */ - memset ( &close, 0, sizeof ( close ) ); - close.header.type = cpu_to_le32 ( VMBUS_CLOSE_CHANNEL ); - close.channel = cpu_to_le32 ( vmdev->channel ); - - /* Post message */ - if ( ( rc = vmbus_post_message ( hv, &close.header, - sizeof ( close ) ) ) != 0 ) { - DBGC ( vmdev, "VMBUS %s failed to close: %s\n", - vmdev->dev.name, strerror ( rc ) ); - /* Continue to attempt to tear down GPADL, so that our - * memory is no longer accessible by the remote VM. - */ - } - - /* Tear down GPADL */ - if ( ( rc = vmbus_gpadl_teardown ( vmdev, - vmdev->gpadl ) ) != 0 ) { - DBGC ( vmdev, "VMBUS %s failed to tear down channel GPADL: " - "%s\n", vmdev->dev.name, strerror ( rc ) ); - /* We can't prevent the remote VM from continuing to - * access this memory, so leak it. - */ - return; - } - - /* Free ring buffer */ - len = ( sizeof ( *vmdev->out ) + vmdev->out_len + - sizeof ( *vmdev->in ) + vmdev->in_len ); - free_dma ( vmdev->out, len ); - vmdev->out = NULL; - vmdev->in = NULL; - - /* Free packet buffer */ - free ( vmdev->packet ); - vmdev->packet = NULL; - - DBGC ( vmdev, "VMBUS %s closed\n", vmdev->dev.name ); -} - -/** - * Signal channel via monitor page - * - * @v vmdev VMBus device - */ -static void vmbus_signal_monitor ( struct vmbus_device *vmdev ) { - struct hv_hypervisor *hv = vmdev->hv; - struct vmbus *vmbus = hv->vmbus; - struct hv_monitor_trigger *trigger; - unsigned int group; - unsigned int bit; - - /* Set bit in monitor trigger group */ - group = ( vmdev->monitor / ( 8 * sizeof ( trigger->pending ) )); - bit = ( vmdev->monitor % ( 8 * sizeof ( trigger->pending ) ) ); - trigger = &vmbus->monitor_out->trigger[group]; - hv_set_bit ( trigger, bit ); -} - -/** - * Signal channel via hypervisor event - * - * @v vmdev VMBus device - */ -static void vmbus_signal_event ( struct vmbus_device *vmdev ) { - struct hv_hypervisor *hv = vmdev->hv; - int rc; - - /* Signal hypervisor event */ - if ( ( rc = hv_signal_event ( hv, VMBUS_EVENT_ID, 0 ) ) != 0 ) { - DBGC ( vmdev, "VMBUS %s could not signal event: %s\n", - vmdev->dev.name, strerror ( rc ) ); - return; - } -} - -/** - * Fill outbound ring buffer - * - * @v vmdev VMBus device - * @v prod Producer index - * @v data Data - * @v len Length - * @ret prod New producer index - * - * The caller must ensure that there is sufficient space in the ring - * buffer. - */ -static size_t vmbus_produce ( struct vmbus_device *vmdev, size_t prod, - const void *data, size_t len ) { - size_t first; - size_t second; - - /* Determine fragment lengths */ - first = ( vmdev->out_len - prod ); - if ( first > len ) - first = len; - second = ( len - first ); - - /* Copy fragment(s) */ - memcpy ( &vmdev->out->data[prod], data, first ); - if ( second ) - memcpy ( &vmdev->out->data[0], ( data + first ), second ); - - return ( ( prod + len ) & ( vmdev->out_len - 1 ) ); -} - -/** - * Consume inbound ring buffer - * - * @v vmdev VMBus device - * @v cons Consumer index - * @v data Data buffer, or NULL - * @v len Length to consume - * @ret cons New consumer index - */ -static size_t vmbus_consume ( struct vmbus_device *vmdev, size_t cons, - void *data, size_t len ) { - size_t first; - size_t second; - - /* Determine fragment lengths */ - first = ( vmdev->in_len - cons ); - if ( first > len ) - first = len; - second = ( len - first ); - - /* Copy fragment(s) */ - memcpy ( data, &vmdev->in->data[cons], first ); - if ( second ) - memcpy ( ( data + first ), &vmdev->in->data[0], second ); - - return ( ( cons + len ) & ( vmdev->in_len - 1 ) ); -} - -/** - * Send packet via ring buffer - * - * @v vmdev VMBus device - * @v header Packet header - * @v data Data - * @v len Length of data - * @ret rc Return status code - * - * Send a packet via the outbound ring buffer. All fields in the - * packet header must be filled in, with the exception of the total - * packet length. - */ -static int vmbus_send ( struct vmbus_device *vmdev, - struct vmbus_packet_header *header, - const void *data, size_t len ) { - struct hv_hypervisor *hv = vmdev->hv; - struct vmbus *vmbus = hv->vmbus; - static uint8_t padding[ 8 - 1 ]; - struct vmbus_packet_footer footer; - size_t header_len; - size_t pad_len; - size_t footer_len; - size_t ring_len; - size_t cons; - size_t prod; - size_t old_prod; - size_t fill; - - /* Sanity check */ - assert ( vmdev->out != NULL ); - - /* Calculate lengths */ - header_len = ( le16_to_cpu ( header->hdr_qlen ) * 8 ); - pad_len = ( ( -len ) & ( 8 - 1 ) ); - footer_len = sizeof ( footer ); - ring_len = ( header_len + len + pad_len + footer_len ); - - /* Check that we have enough room in the outbound ring buffer */ - cons = le32_to_cpu ( vmdev->out->cons ); - prod = le32_to_cpu ( vmdev->out->prod ); - old_prod = prod; - fill = ( ( prod - cons ) & ( vmdev->out_len - 1 ) ); - if ( ( fill + ring_len ) >= vmdev->out_len ) { - DBGC ( vmdev, "VMBUS %s ring buffer full\n", vmdev->dev.name ); - return -ENOBUFS; - } - - /* Complete header */ - header->qlen = cpu_to_le16 ( ( ring_len - footer_len ) / 8 ); - - /* Construct footer */ - footer.reserved = 0; - footer.prod = vmdev->out->prod; - - /* Copy packet to buffer */ - DBGC2 ( vmdev, "VMBUS %s sending:\n", vmdev->dev.name ); - DBGC2_HDA ( vmdev, prod, header, header_len ); - prod = vmbus_produce ( vmdev, prod, header, header_len ); - DBGC2_HDA ( vmdev, prod, data, len ); - prod = vmbus_produce ( vmdev, prod, data, len ); - prod = vmbus_produce ( vmdev, prod, padding, pad_len ); - DBGC2_HDA ( vmdev, prod, &footer, sizeof ( footer ) ); - prod = vmbus_produce ( vmdev, prod, &footer, sizeof ( footer ) ); - assert ( ( ( prod - old_prod ) & ( vmdev->out_len - 1 ) ) == ring_len ); - - /* Update producer index */ - wmb(); - vmdev->out->prod = cpu_to_le32 ( prod ); - - /* Return if we do not need to signal the host. This follows - * the logic of hv_need_to_signal() in the Linux driver. - */ - mb(); - if ( vmdev->out->intr_mask ) - return 0; - rmb(); - cons = le32_to_cpu ( vmdev->out->cons ); - if ( cons != old_prod ) - return 0; - - /* Set channel bit in interrupt page */ - hv_set_bit ( vmbus->intr->out, vmdev->channel ); - - /* Signal the host */ - vmdev->signal ( vmdev ); - - return 0; -} - -/** - * Send control packet via ring buffer - * - * @v vmdev VMBus device - * @v xid Transaction ID (or zero to not request completion) - * @v data Data - * @v len Length of data - * @ret rc Return status code - * - * Send data using a VMBUS_DATA_INBAND packet. - */ -int vmbus_send_control ( struct vmbus_device *vmdev, uint64_t xid, - const void *data, size_t len ) { - struct vmbus_packet_header *header = vmdev->packet; - - /* Construct header in packet buffer */ - assert ( header != NULL ); - header->type = cpu_to_le16 ( VMBUS_DATA_INBAND ); - header->hdr_qlen = cpu_to_le16 ( sizeof ( *header ) / 8 ); - header->flags = ( xid ? - cpu_to_le16 ( VMBUS_COMPLETION_REQUESTED ) : 0 ); - header->xid = xid; /* Non-endian */ - - return vmbus_send ( vmdev, header, data, len ); -} - -/** - * Send data packet via ring buffer - * - * @v vmdev VMBus device - * @v xid Transaction ID - * @v data Data - * @v len Length of data - * @v iobuf I/O buffer - * @ret rc Return status code - * - * Send data using a VMBUS_DATA_GPA_DIRECT packet. The caller is - * responsible for ensuring that the I/O buffer remains untouched - * until the corresponding completion has been received. - */ -int vmbus_send_data ( struct vmbus_device *vmdev, uint64_t xid, - const void *data, size_t len, struct io_buffer *iobuf ) { - physaddr_t addr = virt_to_phys ( iobuf->data ); - unsigned int pfn_count = hv_pfn_count ( addr, iob_len ( iobuf ) ); - struct { - struct vmbus_gpa_direct_header gpa; - struct vmbus_gpa_range range; - uint64_t pfn[pfn_count]; - } __attribute__ (( packed )) *header = vmdev->packet; - unsigned int i; - - /* Sanity check */ - assert ( header != NULL ); - assert ( sizeof ( *header ) <= vmdev->mtu ); - - /* Construct header in packet buffer */ - header->gpa.header.type = cpu_to_le16 ( VMBUS_DATA_GPA_DIRECT ); - header->gpa.header.hdr_qlen = cpu_to_le16 ( sizeof ( *header ) / 8 ); - header->gpa.header.flags = cpu_to_le16 ( VMBUS_COMPLETION_REQUESTED ); - header->gpa.header.xid = xid; /* Non-endian */ - header->gpa.range_count = 1; - header->range.len = cpu_to_le32 ( iob_len ( iobuf ) ); - header->range.offset = cpu_to_le32 ( addr & ( PAGE_SIZE - 1 ) ); - for ( i = 0 ; i < pfn_count ; i++ ) - header->pfn[i] = ( ( addr / PAGE_SIZE ) + i ); - - return vmbus_send ( vmdev, &header->gpa.header, data, len ); -} - -/** - * Send completion packet via ring buffer - * - * @v vmdev VMBus device - * @v xid Transaction ID - * @v data Data - * @v len Length of data - * @ret rc Return status code - * - * Send data using a VMBUS_COMPLETION packet. - */ -int vmbus_send_completion ( struct vmbus_device *vmdev, uint64_t xid, - const void *data, size_t len ) { - struct vmbus_packet_header *header = vmdev->packet; - - /* Construct header in packet buffer */ - assert ( header != NULL ); - header->type = cpu_to_le16 ( VMBUS_COMPLETION ); - header->hdr_qlen = cpu_to_le16 ( sizeof ( *header ) / 8 ); - header->flags = 0; - header->xid = xid; /* Non-endian */ - - return vmbus_send ( vmdev, header, data, len ); -} - -/** - * Send cancellation packet via ring buffer - * - * @v vmdev VMBus device - * @v xid Transaction ID - * @ret rc Return status code - * - * Send data using a VMBUS_CANCELLATION packet. - */ -int vmbus_send_cancellation ( struct vmbus_device *vmdev, uint64_t xid ) { - struct vmbus_packet_header *header = vmdev->packet; - - /* Construct header in packet buffer */ - assert ( header != NULL ); - header->type = cpu_to_le16 ( VMBUS_CANCELLATION ); - header->hdr_qlen = cpu_to_le16 ( sizeof ( *header ) / 8 ); - header->flags = 0; - header->xid = xid; /* Non-endian */ - - return vmbus_send ( vmdev, header, NULL, 0 ); -} - -/** - * Get transfer page set from pageset ID - * - * @v vmdev VMBus device - * @v pageset Page set ID (in protocol byte order) - * @ret pages Page set, or NULL if not found - */ -static struct vmbus_xfer_pages * vmbus_xfer_pages ( struct vmbus_device *vmdev, - uint16_t pageset ) { - struct vmbus_xfer_pages *pages; - - /* Locate page set */ - list_for_each_entry ( pages, &vmdev->pages, list ) { - if ( pages->pageset == pageset ) - return pages; - } - - DBGC ( vmdev, "VMBUS %s unrecognised page set ID %#04x\n", - vmdev->dev.name, le16_to_cpu ( pageset ) ); - return NULL; -} - -/** - * Construct I/O buffer list from transfer pages - * - * @v vmdev VMBus device - * @v header Transfer page header - * @v list I/O buffer list to populate - * @ret rc Return status code - */ -static int vmbus_xfer_page_iobufs ( struct vmbus_device *vmdev, - struct vmbus_packet_header *header, - struct list_head *list ) { - struct vmbus_xfer_page_header *page_header = - container_of ( header, struct vmbus_xfer_page_header, header ); - struct vmbus_xfer_pages *pages; - struct io_buffer *iobuf; - struct io_buffer *tmp; - size_t len; - size_t offset; - unsigned int range_count; - unsigned int i; - int rc; - - /* Sanity check */ - assert ( header->type == cpu_to_le16 ( VMBUS_DATA_XFER_PAGES ) ); - - /* Locate page set */ - pages = vmbus_xfer_pages ( vmdev, page_header->pageset ); - if ( ! pages ) { - rc = -ENOENT; - goto err_pages; - } - - /* Allocate and populate I/O buffers */ - range_count = le32_to_cpu ( page_header->range_count ); - for ( i = 0 ; i < range_count ; i++ ) { - - /* Parse header */ - len = le32_to_cpu ( page_header->range[i].len ); - offset = le32_to_cpu ( page_header->range[i].offset ); - - /* Allocate I/O buffer */ - iobuf = alloc_iob ( len ); - if ( ! iobuf ) { - DBGC ( vmdev, "VMBUS %s could not allocate %zd-byte " - "I/O buffer\n", vmdev->dev.name, len ); - rc = -ENOMEM; - goto err_alloc; - } - - /* Add I/O buffer to list */ - list_add ( &iobuf->list, list ); - - /* Populate I/O buffer */ - if ( ( rc = pages->op->copy ( pages, iob_put ( iobuf, len ), - offset, len ) ) != 0 ) { - DBGC ( vmdev, "VMBUS %s could not populate I/O buffer " - "range [%zd,%zd): %s\n", - vmdev->dev.name, offset, len, strerror ( rc ) ); - goto err_copy; - } - } - - return 0; - - err_copy: - err_alloc: - list_for_each_entry_safe ( iobuf, tmp, list, list ) { - list_del ( &iobuf->list ); - free_iob ( iobuf ); - } - err_pages: - return rc; -} - -/** - * Poll ring buffer - * - * @v vmdev VMBus device - * @ret rc Return status code - */ -int vmbus_poll ( struct vmbus_device *vmdev ) { - struct vmbus_packet_header *header = vmdev->packet; - struct list_head list; - void *data; - size_t header_len; - size_t len; - size_t footer_len; - size_t ring_len; - size_t cons; - size_t old_cons; - uint64_t xid; - int rc; - - /* Sanity checks */ - assert ( vmdev->packet != NULL ); - assert ( vmdev->in != NULL ); - - /* Return immediately if buffer is empty */ - if ( ! vmbus_has_data ( vmdev ) ) - return 0; - cons = le32_to_cpu ( vmdev->in->cons ); - old_cons = cons; - - /* Consume (start of) header */ - cons = vmbus_consume ( vmdev, cons, header, sizeof ( *header ) ); - - /* Parse and sanity check header */ - header_len = ( le16_to_cpu ( header->hdr_qlen ) * 8 ); - if ( header_len < sizeof ( *header ) ) { - DBGC ( vmdev, "VMBUS %s received underlength header (%zd " - "bytes)\n", vmdev->dev.name, header_len ); - return -EINVAL; - } - len = ( ( le16_to_cpu ( header->qlen ) * 8 ) - header_len ); - footer_len = sizeof ( struct vmbus_packet_footer ); - ring_len = ( header_len + len + footer_len ); - if ( ring_len > vmdev->mtu ) { - DBGC ( vmdev, "VMBUS %s received overlength packet (%zd " - "bytes)\n", vmdev->dev.name, ring_len ); - return -ERANGE; - } - xid = le64_to_cpu ( header->xid ); - - /* Consume remainder of packet */ - cons = vmbus_consume ( vmdev, cons, - ( ( ( void * ) header ) + sizeof ( *header ) ), - ( ring_len - sizeof ( *header ) ) ); - DBGC2 ( vmdev, "VMBUS %s received:\n", vmdev->dev.name ); - DBGC2_HDA ( vmdev, old_cons, header, ring_len ); - assert ( ( ( cons - old_cons ) & ( vmdev->in_len - 1 ) ) == ring_len ); - - /* Allocate I/O buffers, if applicable */ - INIT_LIST_HEAD ( &list ); - if ( header->type == cpu_to_le16 ( VMBUS_DATA_XFER_PAGES ) ) { - if ( ( rc = vmbus_xfer_page_iobufs ( vmdev, header, - &list ) ) != 0 ) - return rc; - } - - /* Update producer index */ - rmb(); - vmdev->in->cons = cpu_to_le32 ( cons ); - - /* Handle packet */ - data = ( ( ( void * ) header ) + header_len ); - switch ( header->type ) { - - case cpu_to_le16 ( VMBUS_DATA_INBAND ) : - if ( ( rc = vmdev->op->recv_control ( vmdev, xid, data, - len ) ) != 0 ) { - DBGC ( vmdev, "VMBUS %s could not handle control " - "packet: %s\n", - vmdev->dev.name, strerror ( rc ) ); - return rc; - } - break; - - case cpu_to_le16 ( VMBUS_DATA_XFER_PAGES ) : - if ( ( rc = vmdev->op->recv_data ( vmdev, xid, data, len, - &list ) ) != 0 ) { - DBGC ( vmdev, "VMBUS %s could not handle data packet: " - "%s\n", vmdev->dev.name, strerror ( rc ) ); - return rc; - } - break; - - case cpu_to_le16 ( VMBUS_COMPLETION ) : - if ( ( rc = vmdev->op->recv_completion ( vmdev, xid, data, - len ) ) != 0 ) { - DBGC ( vmdev, "VMBUS %s could not handle completion: " - "%s\n", vmdev->dev.name, strerror ( rc ) ); - return rc; - } - break; - - case cpu_to_le16 ( VMBUS_CANCELLATION ) : - if ( ( rc = vmdev->op->recv_cancellation ( vmdev, xid ) ) != 0){ - DBGC ( vmdev, "VMBUS %s could not handle cancellation: " - "%s\n", vmdev->dev.name, strerror ( rc ) ); - return rc; - } - break; - - default: - DBGC ( vmdev, "VMBUS %s unknown packet type %d\n", - vmdev->dev.name, le16_to_cpu ( header->type ) ); - return -ENOTSUP; - } - - return 0; -} - -/** - * Dump channel status (for debugging) - * - * @v vmdev VMBus device - */ -void vmbus_dump_channel ( struct vmbus_device *vmdev ) { - size_t out_prod = le32_to_cpu ( vmdev->out->prod ); - size_t out_cons = le32_to_cpu ( vmdev->out->cons ); - size_t in_prod = le32_to_cpu ( vmdev->in->prod ); - size_t in_cons = le32_to_cpu ( vmdev->in->cons ); - size_t in_len; - size_t first; - size_t second; - - /* Dump ring status */ - DBGC ( vmdev, "VMBUS %s out %03zx:%03zx%s in %03zx:%03zx%s\n", - vmdev->dev.name, out_prod, out_cons, - ( vmdev->out->intr_mask ? "(m)" : "" ), in_prod, in_cons, - ( vmdev->in->intr_mask ? "(m)" : "" ) ); - - /* Dump inbound ring contents, if any */ - if ( in_prod != in_cons ) { - in_len = ( ( in_prod - in_cons ) & - ( vmdev->in_len - 1 ) ); - first = ( vmdev->in_len - in_cons ); - if ( first > in_len ) - first = in_len; - second = ( in_len - first ); - DBGC_HDA ( vmdev, in_cons, &vmdev->in->data[in_cons], first ); - DBGC_HDA ( vmdev, 0, &vmdev->in->data[0], second ); - } -} - -/** - * Find driver for VMBus device - * - * @v vmdev VMBus device - * @ret driver Driver, or NULL - */ -static struct vmbus_driver * vmbus_find_driver ( const union uuid *type ) { - struct vmbus_driver *vmdrv; - - for_each_table_entry ( vmdrv, VMBUS_DRIVERS ) { - if ( memcmp ( &vmdrv->type, type, sizeof ( *type ) ) == 0 ) - return vmdrv; - } - return NULL; -} - -/** - * Probe channels - * - * @v hv Hyper-V hypervisor - * @v parent Parent device - * @ret rc Return status code - */ -static int vmbus_probe_channels ( struct hv_hypervisor *hv, - struct device *parent ) { - struct vmbus *vmbus = hv->vmbus; - const struct vmbus_message_header *header = &vmbus->message->header; - const struct vmbus_offer_channel *offer = &vmbus->message->offer; - const union uuid *type; - struct vmbus_driver *driver; - struct vmbus_device *vmdev; - struct vmbus_device *tmp; - unsigned int channel; - int rc; - - /* Post message */ - if ( ( rc = vmbus_post_empty_message ( hv, VMBUS_REQUEST_OFFERS ) ) !=0) - goto err_post_message; - - /* Collect responses */ - while ( 1 ) { - - /* Wait for response */ - if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 ) - goto err_wait_for_message; - - /* Handle response */ - if ( header->type == cpu_to_le32 ( VMBUS_OFFER_CHANNEL ) ) { - - /* Parse offer */ - type = &offer->type; - channel = le32_to_cpu ( offer->channel ); - DBGC2 ( vmbus, "VMBUS %p offer %d type %s", - vmbus, channel, uuid_ntoa ( type ) ); - if ( offer->monitored ) - DBGC2 ( vmbus, " monitor %d", offer->monitor ); - DBGC2 ( vmbus, "\n" ); - - /* Look for a driver */ - driver = vmbus_find_driver ( type ); - if ( ! driver ) { - DBGC2 ( vmbus, "VMBUS %p has no driver for " - "type %s\n", vmbus, uuid_ntoa ( type )); - /* Not a fatal error */ - continue; - } - - /* Allocate and initialise device */ - vmdev = zalloc ( sizeof ( *vmdev ) ); - if ( ! vmdev ) { - rc = -ENOMEM; - goto err_alloc_vmdev; - } - snprintf ( vmdev->dev.name, sizeof ( vmdev->dev.name ), - "vmbus:%02x", channel ); - vmdev->dev.desc.bus_type = BUS_TYPE_HV; - INIT_LIST_HEAD ( &vmdev->dev.children ); - list_add_tail ( &vmdev->dev.siblings, - &parent->children ); - vmdev->dev.parent = parent; - vmdev->hv = hv; - vmdev->channel = channel; - vmdev->monitor = offer->monitor; - vmdev->signal = ( offer->monitored ? - vmbus_signal_monitor : - vmbus_signal_event ); - INIT_LIST_HEAD ( &vmdev->pages ); - vmdev->driver = driver; - vmdev->dev.driver_name = driver->name; - DBGC ( vmdev, "VMBUS %s has driver \"%s\"\n", - vmdev->dev.name, vmdev->driver->name ); - - } else if ( header->type == - cpu_to_le32 ( VMBUS_ALL_OFFERS_DELIVERED ) ) { - - break; - - } else { - DBGC ( vmbus, "VMBUS %p unexpected offer response type " - "%d\n", vmbus, le32_to_cpu ( header->type ) ); - rc = -EPROTO; - goto err_unexpected_offer; - } - } - - /* Probe all devices. We do this only after completing - * enumeration since devices will need to send and receive - * VMBus messages. - */ - list_for_each_entry ( vmdev, &parent->children, dev.siblings ) { - if ( ( rc = vmdev->driver->probe ( vmdev ) ) != 0 ) { - DBGC ( vmdev, "VMBUS %s could not probe: %s\n", - vmdev->dev.name, strerror ( rc ) ); - goto err_probe; - } - } - - return 0; - - err_probe: - /* Remove driver from each device that was already probed */ - list_for_each_entry_continue_reverse ( vmdev, &parent->children, - dev.siblings ) { - vmdev->driver->remove ( vmdev ); - } - err_unexpected_offer: - err_alloc_vmdev: - err_wait_for_message: - /* Free any devices allocated (but potentially not yet probed) */ - list_for_each_entry_safe ( vmdev, tmp, &parent->children, - dev.siblings ) { - list_del ( &vmdev->dev.siblings ); - free ( vmdev ); - } - err_post_message: - return rc; -} - -/** - * Remove channels - * - * @v hv Hyper-V hypervisor - * @v parent Parent device - */ -static void vmbus_remove_channels ( struct hv_hypervisor *hv __unused, - struct device *parent ) { - struct vmbus_device *vmdev; - struct vmbus_device *tmp; - - /* Remove devices */ - list_for_each_entry_safe ( vmdev, tmp, &parent->children, - dev.siblings ) { - vmdev->driver->remove ( vmdev ); - assert ( list_empty ( &vmdev->dev.children ) ); - assert ( vmdev->out == NULL ); - assert ( vmdev->in == NULL ); - assert ( vmdev->packet == NULL ); - assert ( list_empty ( &vmdev->pages ) ); - list_del ( &vmdev->dev.siblings ); - free ( vmdev ); - } -} - -/** - * Probe Hyper-V virtual machine bus - * - * @v hv Hyper-V hypervisor - * @v parent Parent device - * @ret rc Return status code - */ -int vmbus_probe ( struct hv_hypervisor *hv, struct device *parent ) { - struct vmbus *vmbus; - int rc; - - /* Allocate and initialise structure */ - vmbus = zalloc ( sizeof ( *vmbus ) ); - if ( ! vmbus ) { - rc = -ENOMEM; - goto err_alloc; - } - hv->vmbus = vmbus; - - /* Initialise message buffer pointer - * - * We use a pointer to the fixed-size Hyper-V received message - * buffer. This allows us to access fields within received - * messages without first checking the message size: any - * fields beyond the end of the message will read as zero. - */ - vmbus->message = ( ( void * ) hv->message->received.data ); - assert ( sizeof ( *vmbus->message ) <= - sizeof ( hv->message->received.data ) ); - - /* Allocate interrupt and monitor pages */ - if ( ( rc = hv_alloc_pages ( hv, &vmbus->intr, &vmbus->monitor_in, - &vmbus->monitor_out, NULL ) ) != 0 ) - goto err_alloc_pages; - - /* Enable message interrupt */ - hv_enable_sint ( hv, VMBUS_MESSAGE_SINT ); - - /* Negotiate protocol version */ - if ( ( rc = vmbus_negotiate_version ( hv ) ) != 0 ) - goto err_negotiate_version; - - /* Enumerate channels */ - if ( ( rc = vmbus_probe_channels ( hv, parent ) ) != 0 ) - goto err_probe_channels; - - return 0; - - vmbus_remove_channels ( hv, parent ); - err_probe_channels: - vmbus_unload ( hv ); - err_negotiate_version: - hv_disable_sint ( hv, VMBUS_MESSAGE_SINT ); - hv_free_pages ( hv, vmbus->intr, vmbus->monitor_in, vmbus->monitor_out, - NULL ); - err_alloc_pages: - free ( vmbus ); - err_alloc: - return rc; -} - -/** - * Remove Hyper-V virtual machine bus - * - * @v hv Hyper-V hypervisor - * @v parent Parent device - */ -void vmbus_remove ( struct hv_hypervisor *hv, struct device *parent ) { - struct vmbus *vmbus = hv->vmbus; - - vmbus_remove_channels ( hv, parent ); - vmbus_unload ( hv ); - hv_disable_sint ( hv, VMBUS_MESSAGE_SINT ); - hv_free_pages ( hv, vmbus->intr, vmbus->monitor_in, vmbus->monitor_out, - NULL ); - free ( vmbus ); -} diff --git a/qemu/roms/ipxe/src/interface/linux/linux_console.c b/qemu/roms/ipxe/src/interface/linux/linux_console.c deleted file mode 100644 index 5105eaa94..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_console.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com> - * - * 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); - -/** @file - * - * Linux console implementation. - * - */ - -#include <ipxe/console.h> - -#include <ipxe/init.h> -#include <ipxe/keys.h> -#include <linux_api.h> - -#include <linux/termios.h> -#include <asm/errno.h> - -#include <config/console.h> - -/* Set default console usage if applicable */ -#if ! ( defined ( CONSOLE_LINUX ) && CONSOLE_EXPLICIT ( CONSOLE_LINUX ) ) -#undef CONSOLE_LINUX -#define CONSOLE_LINUX ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG ) -#endif - -static void linux_console_putchar(int c) -{ - /* write to stdout */ - if (linux_write(1, &c, 1) != 1) - DBG("linux_console write failed (%s)\n", linux_strerror(linux_errno)); -} - -static int linux_console_getchar() -{ - char c; - - /* read from stdin */ - if (linux_read(0, &c, 1) < 0) { - DBG("linux_console read failed (%s)\n", linux_strerror(linux_errno)); - return 0; - } - /* backspace seems to be returned as ascii del, map it here */ - if (c == 0x7f) - return KEY_BACKSPACE; - else - return c; -} - -static int linux_console_iskey() -{ - struct pollfd pfd; - pfd.fd = 0; - pfd.events = POLLIN; - - /* poll for data to be read on stdin */ - if (linux_poll(&pfd, 1, 0) == -1) { - DBG("linux_console poll failed (%s)\n", linux_strerror(linux_errno)); - return 0; - } - - if (pfd.revents & POLLIN) - return 1; - else - return 0; -} - -struct console_driver linux_console __console_driver = { - .disabled = 0, - .putchar = linux_console_putchar, - .getchar = linux_console_getchar, - .iskey = linux_console_iskey, - .usage = CONSOLE_LINUX, -}; - -static int linux_tcgetattr(int fd, struct termios *termios_p) -{ - return linux_ioctl(fd, TCGETS, termios_p); -} - -static int linux_tcsetattr(int fd, int optional_actions, const struct termios *termios_p) -{ - unsigned long int cmd; - - switch (optional_actions) - { - case TCSANOW: - cmd = TCSETS; - break; - case TCSADRAIN: - cmd = TCSETSW; - break; - case TCSAFLUSH: - cmd = TCSETSF; - break; - default: - linux_errno = EINVAL; - return -1; - } - - return linux_ioctl(fd, cmd, termios_p); -} - -/** Saved termios attributes */ -static struct termios saved_termios; - -/** Setup the terminal for our use */ -static void linux_console_startup(void) -{ - struct termios t; - - if (linux_tcgetattr(0, &t)) { - DBG("linux_console tcgetattr failed (%s)", linux_strerror(linux_errno)); - return; - } - - saved_termios = t; - - /* Disable canonical mode and echo. Let readline handle that */ - t.c_lflag &= ~(ECHO | ICANON); - /* stop ^C from sending a signal */ - t.c_cc[VINTR] = 0; - - if (linux_tcsetattr(0, TCSAFLUSH, &t)) - DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno)); -} - -/** Restores original terminal attributes on shutdown */ -static void linux_console_shutdown(int flags __unused) -{ - if (linux_tcsetattr(0, TCSAFLUSH, &saved_termios)) - DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno)); -} - -struct startup_fn linux_console_startup_fn __startup_fn(STARTUP_EARLY) = { - .startup = linux_console_startup, - .shutdown = linux_console_shutdown, -}; diff --git a/qemu/roms/ipxe/src/interface/linux/linux_entropy.c b/qemu/roms/ipxe/src/interface/linux/linux_entropy.c deleted file mode 100644 index 0f8e45d36..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_entropy.c +++ /dev/null @@ -1,101 +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 - * - * Linux entropy source - * - */ - -#include <stdint.h> -#include <errno.h> -#include <linux_api.h> -#include <ipxe/entropy.h> - -/** Entropy source filename */ -static const char entropy_filename[] = "/dev/random"; - -/** Entropy source file handle */ -static int entropy_fd; - -/** - * Enable entropy gathering - * - * @ret rc Return status code - */ -static int linux_entropy_enable ( void ) { - - /* Open entropy source */ - entropy_fd = linux_open ( entropy_filename, O_RDONLY ); - if ( entropy_fd < 0 ) { - DBGC ( &entropy_fd, "ENTROPY could not open %s: %s\n", - entropy_filename, linux_strerror ( linux_errno ) ); - return entropy_fd; - } - - return 0; -} - -/** - * Disable entropy gathering - * - */ -static void linux_entropy_disable ( void ) { - - /* Close entropy source */ - linux_close ( entropy_fd ); -} - -/** - * Get noise sample - * - * @ret noise Noise sample - * @ret rc Return status code - */ -static int linux_get_noise ( noise_sample_t *noise ) { - uint8_t byte; - ssize_t len; - - /* Read a single byte from entropy source */ - len = linux_read ( entropy_fd, &byte, sizeof ( byte ) ); - if ( len < 0 ) { - DBGC ( &entropy_fd, "ENTROPY could not read from %s: %s\n", - entropy_filename, linux_strerror ( linux_errno ) ); - return len; - } - if ( len == 0 ) { - DBGC ( &entropy_fd, "ENTROPY EOF on reading from %s: %s\n", - entropy_filename, linux_strerror ( linux_errno ) ); - return -EPIPE; - } - *noise = byte; - - return 0; -} - -PROVIDE_ENTROPY_INLINE ( linux, min_entropy_per_sample ); -PROVIDE_ENTROPY ( linux, entropy_enable, linux_entropy_enable ); -PROVIDE_ENTROPY ( linux, entropy_disable, linux_entropy_disable ); -PROVIDE_ENTROPY ( linux, get_noise, linux_get_noise ); diff --git a/qemu/roms/ipxe/src/interface/linux/linux_nap.c b/qemu/roms/ipxe/src/interface/linux/linux_nap.c deleted file mode 100644 index f1d3cd962..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_nap.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com> - * - * 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 <ipxe/nap.h> - -#include <linux_api.h> - -/** @file - * - * iPXE CPU sleeping API for linux - * - */ - -/** - * Sleep until next CPU interrupt - * - */ -static void linux_cpu_nap(void) -{ - linux_usleep(0); -} - -PROVIDE_NAP(linux, cpu_nap, linux_cpu_nap); diff --git a/qemu/roms/ipxe/src/interface/linux/linux_pci.c b/qemu/roms/ipxe/src/interface/linux/linux_pci.c deleted file mode 100644 index 0c140cb89..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_pci.c +++ /dev/null @@ -1,189 +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 (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 <stdio.h> -#include <errno.h> -#include <byteswap.h> -#include <linux_api.h> -#include <ipxe/linux.h> -#include <ipxe/pci.h> - -/** @file - * - * iPXE PCI API for Linux - * - */ - -/** - * Open PCI configuration space - * - * @v pci PCI device - * @v flags Access mode flags - * @v where Address within configuration space - * @ret fd File handle, or negative error - */ -static int linux_pci_open ( struct pci_device *pci, int flags, - unsigned long where ) { - char filename[ 22 /* "/proc/bus/pci/xx/xx.x" + NUL */ ]; - int fd; - int rc; - - /* Construct filename */ - snprintf ( filename, sizeof ( filename ), "/proc/bus/pci/%02x/%02x.%x", - PCI_BUS ( pci->busdevfn ), PCI_SLOT ( pci->busdevfn ), - PCI_FUNC ( pci->busdevfn ) ); - - /* Open file */ - fd = linux_open ( filename, flags ); - if ( fd < 0 ) { - DBGC ( pci, "PCI could not open %s: %s\n", filename, - linux_strerror ( linux_errno ) ); - rc = -ELINUX ( linux_errno ); - goto err_open; - } - - /* Seek to location */ - if ( linux_lseek ( fd, where, SEEK_SET ) < 0 ) { - DBGC ( pci, "PCI could not seek to %s offset %#02lx: %s\n", - filename, where, linux_strerror ( linux_errno ) ); - rc = -ELINUX ( linux_errno ); - goto err_seek; - } - - return fd; - - err_seek: - linux_close ( fd ); - err_open: - return rc; -} - -/** - * Read from PCI configuration space - * - * @v pci PCI device - * @v where Address within configuration space - * @v value Data buffer - * @v len Length to read - * @ret rc Return status code - */ -int linux_pci_read ( struct pci_device *pci, unsigned long where, - unsigned long *value, size_t len ) { - uint32_t tmp = 0; - int fd; - int check_len; - int rc; - - /* Return "missing device" in case of error */ - *value = -1UL; - - /* Open configuration space */ - fd = linux_pci_open ( pci, O_RDONLY, where ); - if ( fd < 0 ) { - rc = fd; - goto err_open; - } - - /* Read value */ - check_len = linux_read ( fd, &tmp, len ); - if ( check_len < 0 ) { - DBGC ( pci, "PCI could not read from " PCI_FMT " %#02lx+%#zx: " - "%s\n", PCI_ARGS ( pci ), where, len, - linux_strerror ( linux_errno ) ); - rc = -ELINUX ( linux_errno ); - goto err_read; - } - if ( ( size_t ) check_len != len ) { - DBGC ( pci, "PCI read only %#x bytes from " PCI_FMT - " %#02lx+%#zx\n", check_len, PCI_ARGS ( pci ), - where, len ); - rc = -EIO; - goto err_read; - } - - /* Return value */ - *value = le32_to_cpu ( tmp ); - - /* Success */ - rc = 0; - - err_read: - linux_close ( fd ); - err_open: - return rc; -} - -/** - * Write to PCI configuration space - * - * @v pci PCI device - * @v where Address within configuration space - * @v value Value to write - * @v len Length of value - * @ret rc Return status code - */ -int linux_pci_write ( struct pci_device *pci, unsigned long where, - unsigned long value, size_t len ) { - uint32_t tmp; - int fd; - int check_len; - int rc; - - /* Open configuration space */ - fd = linux_pci_open ( pci, O_WRONLY, where ); - if ( fd < 0 ) { - rc = fd; - goto err_open; - } - - /* Prepare value for writing */ - tmp = cpu_to_le32 ( value ); - assert ( len <= sizeof ( tmp ) ); - - /* Write value */ - check_len = linux_write ( fd, &tmp, len ); - if ( check_len < 0 ) { - DBGC ( pci, "PCI could not write to " PCI_FMT " %#02lx+%#zx: " - "%s\n", PCI_ARGS ( pci ), where, len, - linux_strerror ( linux_errno ) ); - rc = -ELINUX ( linux_errno ); - goto err_write; - } - if ( ( size_t ) check_len != len ) { - DBGC ( pci, "PCI wrote only %#x bytes to " PCI_FMT - " %#02lx+%#zx\n", check_len, PCI_ARGS ( pci ), - where, len ); - rc = -EIO; - goto err_write; - } - - /* Success */ - rc = 0; - - err_write: - linux_close ( fd ); - err_open: - return rc; -} diff --git a/qemu/roms/ipxe/src/interface/linux/linux_smbios.c b/qemu/roms/ipxe/src/interface/linux/linux_smbios.c deleted file mode 100644 index 6e5174d23..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_smbios.c +++ /dev/null @@ -1,115 +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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <errno.h> -#include <linux_api.h> -#include <ipxe/linux.h> -#include <ipxe/smbios.h> - -/** SMBIOS filename */ -static const char smbios_filename[] = "/dev/mem"; - -/** SMBIOS entry point scan region start address */ -#define SMBIOS_ENTRY_START 0xf0000 - -/** SMBIOS entry point scan region length */ -#define SMBIOS_ENTRY_LEN 0x10000 - -/** SMBIOS mapping alignment */ -#define SMBIOS_ALIGN 0x1000 - -/** - * Find SMBIOS - * - * @v smbios SMBIOS entry point descriptor structure to fill in - * @ret rc Return status code - */ -static int linux_find_smbios ( struct smbios *smbios ) { - struct smbios_entry entry; - void *entry_mem; - void *smbios_mem; - size_t smbios_offset; - size_t smbios_indent; - size_t smbios_len; - int fd; - int rc; - - /* Open SMBIOS file */ - fd = linux_open ( smbios_filename, O_RDONLY ); - if ( fd < 0 ) { - rc = -ELINUX ( linux_errno ); - DBGC ( smbios, "SMBIOS could not open %s: %s\n", - smbios_filename, linux_strerror ( linux_errno ) ); - goto err_open; - } - - /* Map the region potentially containing the SMBIOS entry point */ - entry_mem = linux_mmap ( NULL, SMBIOS_ENTRY_LEN, PROT_READ, MAP_SHARED, - fd, SMBIOS_ENTRY_START ); - if ( entry_mem == MAP_FAILED ) { - rc = -ELINUX ( linux_errno ); - DBGC ( smbios, "SMBIOS could not mmap %s (%#x+%#x): %s\n", - smbios_filename, SMBIOS_ENTRY_START, SMBIOS_ENTRY_LEN, - linux_strerror ( linux_errno ) ); - goto err_mmap_entry; - } - - /* Scan for the SMBIOS entry point */ - if ( ( rc = find_smbios_entry ( virt_to_user ( entry_mem ), - SMBIOS_ENTRY_LEN, &entry ) ) != 0 ) - goto err_find_entry; - - /* Map the region containing the SMBIOS structures */ - smbios_indent = ( entry.smbios_address & ( SMBIOS_ALIGN - 1 ) ); - smbios_offset = ( entry.smbios_address - smbios_indent ); - smbios_len = ( entry.smbios_len + smbios_indent ); - smbios_mem = linux_mmap ( NULL, smbios_len, PROT_READ, MAP_SHARED, - fd, smbios_offset ); - if ( smbios_mem == MAP_FAILED ) { - rc = -ELINUX ( linux_errno ); - DBGC ( smbios, "SMBIOS could not mmap %s (%#zx+%#zx): %s\n", - smbios_filename, smbios_offset, smbios_len, - linux_strerror ( linux_errno ) ); - goto err_mmap_smbios; - } - - /* Fill in entry point descriptor structure */ - smbios->address = virt_to_user ( smbios_mem + smbios_indent ); - smbios->len = entry.smbios_len; - smbios->count = entry.smbios_count; - smbios->version = SMBIOS_VERSION ( entry.major, entry.minor ); - - /* Unmap the entry point region (no longer required) */ - linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN ); - - return 0; - - linux_munmap ( smbios_mem, smbios_len ); - err_mmap_smbios: - err_find_entry: - linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN ); - err_mmap_entry: - linux_close ( fd ); - err_open: - return rc; -} - -PROVIDE_SMBIOS ( linux, find_smbios, linux_find_smbios ); diff --git a/qemu/roms/ipxe/src/interface/linux/linux_time.c b/qemu/roms/ipxe/src/interface/linux/linux_time.c deleted file mode 100644 index 9e99fe9cd..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_time.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * Linux time source - * - */ - -#include <stdint.h> -#include <stddef.h> -#include <errno.h> -#include <linux_api.h> -#include <ipxe/time.h> - -/** - * Get current time in seconds - * - * @ret time Time, in seconds - */ -static time_t linux_now ( void ) { - struct timeval now; - - linux_gettimeofday ( &now, NULL ); - return now.tv_sec; -} - -PROVIDE_TIME ( linux, time_now, linux_now ); diff --git a/qemu/roms/ipxe/src/interface/linux/linux_timer.c b/qemu/roms/ipxe/src/interface/linux/linux_timer.c deleted file mode 100644 index 7a994517b..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_timer.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com> - * - * 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 <stddef.h> -#include <ipxe/timer.h> - -#include <linux_api.h> - -/** @file - * - * iPXE timer API for linux - * - */ - -/** - * Delay for a fixed number of microseconds - * - * @v usecs Number of microseconds for which to delay - */ -static void linux_udelay(unsigned long usecs) -{ - linux_usleep(usecs); -} - -/** - * Get number of ticks per second - * - * @ret ticks_per_sec Number of ticks per second - */ -static unsigned long linux_ticks_per_sec(void) -{ - return 1000; -} - -/** - * Get current system time in ticks - * - * linux doesn't provide an easy access to jiffies so implement it by measuring - * the time since the first call to this function. - * - * Since this function is used to seed the (non-cryptographic) random - * number generator, we round the start time down to the nearest whole - * second. This minimises the chances of generating identical RNG - * sequences (and hence identical TCP port numbers, etc) on - * consecutive invocations of iPXE. - * - * @ret ticks Current time, in ticks - */ -static unsigned long linux_currticks(void) -{ - static struct timeval start; - static int initialized = 0; - - if (! initialized) { - linux_gettimeofday(&start, NULL); - initialized = 1; - } - - struct timeval now; - linux_gettimeofday(&now, NULL); - - unsigned long ticks = (now.tv_sec - start.tv_sec) * linux_ticks_per_sec(); - ticks += now.tv_usec / (long)(1000000 / linux_ticks_per_sec()); - - return ticks; -} - -PROVIDE_TIMER(linux, udelay, linux_udelay); -PROVIDE_TIMER(linux, currticks, linux_currticks); -PROVIDE_TIMER(linux, ticks_per_sec, linux_ticks_per_sec); diff --git a/qemu/roms/ipxe/src/interface/linux/linux_uaccess.c b/qemu/roms/ipxe/src/interface/linux/linux_uaccess.c deleted file mode 100644 index ea2d8057c..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_uaccess.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com> - * - * 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 <ipxe/uaccess.h> - -/** @file - * - * iPXE user access API for linux - * - */ - -PROVIDE_UACCESS_INLINE(linux, user_to_phys); -PROVIDE_UACCESS_INLINE(linux, virt_to_user); -PROVIDE_UACCESS_INLINE(linux, user_to_virt); -PROVIDE_UACCESS_INLINE(linux, userptr_add); -PROVIDE_UACCESS_INLINE(linux, memcpy_user); -PROVIDE_UACCESS_INLINE(linux, memmove_user); -PROVIDE_UACCESS_INLINE(linux, memset_user); -PROVIDE_UACCESS_INLINE(linux, strlen_user); -PROVIDE_UACCESS_INLINE(linux, memchr_user); diff --git a/qemu/roms/ipxe/src/interface/linux/linux_umalloc.c b/qemu/roms/ipxe/src/interface/linux/linux_umalloc.c deleted file mode 100644 index aa0052c53..000000000 --- a/qemu/roms/ipxe/src/interface/linux/linux_umalloc.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com> - * - * 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 <valgrind/memcheck.h> - -/** @file - * - * iPXE user memory allocation API for linux - * - */ - -#include <assert.h> -#include <ipxe/umalloc.h> - -#include <linux_api.h> - -/** Special address returned for empty allocations */ -#define NOWHERE ((void *)-1) - -/** Poison to make the metadata more unique */ -#define POISON 0xa5a5a5a5 -#define min(a,b) (((a)<(b))?(a):(b)) - -/** Metadata stored at the beginning of all allocations */ -struct metadata -{ - unsigned poison; - size_t size; -}; - -#define SIZE_MD (sizeof(struct metadata)) - -/** Simple realloc which passes most of the work to mmap(), mremap() and munmap() */ -static void * linux_realloc(void *ptr, size_t size) -{ - struct metadata md = {0, 0}; - struct metadata * mdptr = NULL; - - DBG2("linux_realloc(%p, %zd)\n", ptr, size); - - /* Check whether we have a valid pointer */ - if (ptr != NULL && ptr != NOWHERE) { - mdptr = ptr - SIZE_MD; - VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD); - md = *mdptr; - VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD); - - /* Check for poison in the metadata */ - if (md.poison != POISON) { - DBG("linux_realloc bad poison: 0x%x (expected 0x%x)\n", md.poison, POISON); - return NULL; - } - } else { - /* Handle NOWHERE as NULL */ - ptr = NULL; - } - - /* - * At this point, ptr is either NULL or pointing to a region allocated by us. - * In the latter case mdptr is pointing to a valid metadata, otherwise it is NULL. - */ - - /* Handle deallocation or allocation of size 0 */ - if (size == 0) { - if (mdptr) { - if (linux_munmap(mdptr, md.size)) - DBG("linux_realloc munmap failed: %s\n", linux_strerror(linux_errno)); - VALGRIND_FREELIKE_BLOCK(ptr, sizeof(*mdptr)); - } - return NOWHERE; - } - - if (ptr) { - char *vbits = NULL; - - if (RUNNING_ON_VALGRIND > 0) - vbits = linux_realloc(NULL, min(size, md.size)); - -/* prevent an unused variable warning when building w/o valgrind support */ -#ifndef NVALGRIND - VALGRIND_GET_VBITS(ptr, vbits, min(size, md.size)); -#endif - - VALGRIND_FREELIKE_BLOCK(ptr, SIZE_MD); - - mdptr = linux_mremap(mdptr, md.size + SIZE_MD, size + SIZE_MD, MREMAP_MAYMOVE); - if (mdptr == MAP_FAILED) { - DBG("linux_realloc mremap failed: %s\n", linux_strerror(linux_errno)); - return NULL; - } - ptr = ((void *)mdptr) + SIZE_MD; - - VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0); -/* prevent an unused variable warning when building w/o valgrind support */ -#ifndef NVALGRIND - VALGRIND_SET_VBITS(ptr, vbits, min(size, md.size)); -#endif - - if (RUNNING_ON_VALGRIND > 0) - linux_realloc(vbits, 0); - } else { - mdptr = linux_mmap(NULL, size + SIZE_MD, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (mdptr == MAP_FAILED) { - DBG("linux_realloc mmap failed: %s\n", linux_strerror(linux_errno)); - return NULL; - } - ptr = ((void *)mdptr) + SIZE_MD; - VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0); - } - - /* Update the metadata */ - VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD); - mdptr->poison = POISON; - mdptr->size = size; - VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD); - // VALGRIND_MALLOCLIKE_BLOCK ignores redzones currently, make our own - VALGRIND_MAKE_MEM_NOACCESS(ptr + size, SIZE_MD); - - return ptr; -} - -/** - * 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 linux_urealloc(userptr_t old_ptr, size_t new_size) -{ - return (userptr_t)linux_realloc((void *)old_ptr, new_size); -} - -PROVIDE_UMALLOC(linux, urealloc, linux_urealloc); diff --git a/qemu/roms/ipxe/src/interface/smbios/smbios.c b/qemu/roms/ipxe/src/interface/smbios/smbios.c deleted file mode 100644 index 1dcf819c2..000000000 --- a/qemu/roms/ipxe/src/interface/smbios/smbios.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/uaccess.h> -#include <ipxe/smbios.h> - -/** @file - * - * System Management BIOS - * - */ - -/** SMBIOS entry point descriptor */ -static struct smbios smbios = { - .address = UNULL, -}; - -/** - * Scan for SMBIOS entry point structure - * - * @v start Start address of region to scan - * @v len Length of region to scan - * @v entry SMBIOS entry point structure to fill in - * @ret rc Return status code - */ -int find_smbios_entry ( userptr_t start, size_t len, - struct smbios_entry *entry ) { - uint8_t buf[256]; /* 256 is maximum length possible */ - static size_t offset = 0; /* Avoid repeated attempts to locate SMBIOS */ - size_t entry_len; - unsigned int i; - uint8_t sum; - - /* Try to find SMBIOS */ - for ( ; offset < len ; offset += 0x10 ) { - - /* Read start of header and verify signature */ - copy_from_user ( entry, start, offset, sizeof ( *entry ) ); - if ( entry->signature != SMBIOS_SIGNATURE ) - continue; - - /* Read whole header and verify checksum */ - entry_len = entry->len; - assert ( entry_len <= sizeof ( buf ) ); - copy_from_user ( buf, start, offset, entry_len ); - for ( i = 0, sum = 0 ; i < entry_len ; i++ ) { - sum += buf[i]; - } - if ( sum != 0 ) { - DBG ( "SMBIOS at %08lx has bad checksum %02x\n", - user_to_phys ( start, offset ), sum ); - continue; - } - - /* Fill result structure */ - DBG ( "Found SMBIOS v%d.%d entry point at %08lx\n", - entry->major, entry->minor, - user_to_phys ( start, offset ) ); - return 0; - } - - DBG ( "No SMBIOS found\n" ); - return -ENODEV; -} - -/** - * Find SMBIOS strings terminator - * - * @v offset Offset to start of strings - * @ret offset Offset to strings terminator, or 0 if not found - */ -static size_t find_strings_terminator ( size_t offset ) { - size_t max_offset = ( smbios.len - 2 ); - uint16_t nulnul; - - for ( ; offset <= max_offset ; offset++ ) { - copy_from_user ( &nulnul, smbios.address, offset, 2 ); - if ( nulnul == 0 ) - return ( offset + 1 ); - } - return 0; -} - -/** - * Find specific structure type within SMBIOS - * - * @v type Structure type to search for - * @v instance Instance of this type of structure - * @v structure SMBIOS structure descriptor to fill in - * @ret rc Return status code - */ -int find_smbios_structure ( unsigned int type, unsigned int instance, - struct smbios_structure *structure ) { - unsigned int count = 0; - size_t offset = 0; - size_t strings_offset; - size_t terminator_offset; - int rc; - - /* Find SMBIOS */ - if ( ( smbios.address == UNULL ) && - ( ( rc = find_smbios ( &smbios ) ) != 0 ) ) - return rc; - assert ( smbios.address != UNULL ); - - /* Scan through list of structures */ - while ( ( ( offset + sizeof ( structure->header ) ) < smbios.len ) - && ( count < smbios.count ) ) { - - /* Read next SMBIOS structure header */ - copy_from_user ( &structure->header, smbios.address, offset, - sizeof ( structure->header ) ); - - /* Determine start and extent of strings block */ - strings_offset = ( offset + structure->header.len ); - if ( strings_offset > smbios.len ) { - DBG ( "SMBIOS structure at offset %zx with length " - "%x extends beyond SMBIOS\n", offset, - structure->header.len ); - return -ENOENT; - } - terminator_offset = find_strings_terminator ( strings_offset ); - if ( ! terminator_offset ) { - DBG ( "SMBIOS structure at offset %zx has " - "unterminated strings section\n", offset ); - return -ENOENT; - } - structure->strings_len = ( terminator_offset - strings_offset); - - DBG ( "SMBIOS structure at offset %zx has type %d, length %x, " - "strings length %zx\n", offset, structure->header.type, - structure->header.len, structure->strings_len ); - - /* If this is the structure we want, return */ - if ( ( structure->header.type == type ) && - ( instance-- == 0 ) ) { - structure->offset = offset; - return 0; - } - - /* Move to next SMBIOS structure */ - offset = ( terminator_offset + 1 ); - count++; - } - - DBG ( "SMBIOS structure type %d not found\n", type ); - return -ENOENT; -} - -/** - * Copy SMBIOS structure - * - * @v structure SMBIOS structure descriptor - * @v data Buffer to hold SMBIOS structure - * @v len Length of buffer - * @ret rc Return status code - */ -int read_smbios_structure ( struct smbios_structure *structure, - void *data, size_t len ) { - - assert ( smbios.address != UNULL ); - - if ( len > structure->header.len ) - len = structure->header.len; - copy_from_user ( data, smbios.address, structure->offset, len ); - return 0; -} - -/** - * Find indexed string within SMBIOS structure - * - * @v structure SMBIOS structure descriptor - * @v index String index - * @v data Buffer for string - * @v len Length of string buffer - * @ret rc Length of string, or negative error - */ -int read_smbios_string ( struct smbios_structure *structure, - unsigned int index, void *data, size_t len ) { - size_t strings_start = ( structure->offset + structure->header.len ); - size_t strings_end = ( strings_start + structure->strings_len ); - size_t offset; - size_t string_len; - - assert ( smbios.address != UNULL ); - - /* String numbers start at 1 (0 is used to indicate "no string") */ - if ( ! index ) - return -ENOENT; - - for ( offset = strings_start ; offset < strings_end ; - offset += ( string_len + 1 ) ) { - /* Get string length. This is known safe, since the - * smbios_strings struct is constructed so as to - * always end on a string boundary. - */ - string_len = strlen_user ( smbios.address, offset ); - if ( --index == 0 ) { - /* Copy string, truncating as necessary. */ - if ( len > string_len ) - len = string_len; - copy_from_user ( data, smbios.address, offset, len ); - return string_len; - } - } - - DBG ( "SMBIOS string index %d not found\n", index ); - return -ENOENT; -} - -/** - * Get SMBIOS version - * - * @ret version Version, or negative error - */ -int smbios_version ( void ) { - int rc; - - /* Find SMBIOS */ - if ( ( smbios.address == UNULL ) && - ( ( rc = find_smbios ( &smbios ) ) != 0 ) ) - return rc; - assert ( smbios.address != UNULL ); - - return smbios.version; -} diff --git a/qemu/roms/ipxe/src/interface/smbios/smbios_settings.c b/qemu/roms/ipxe/src/interface/smbios/smbios_settings.c deleted file mode 100644 index 5eadfa081..000000000 --- a/qemu/roms/ipxe/src/interface/smbios/smbios_settings.c +++ /dev/null @@ -1,259 +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 <stdint.h> -#include <string.h> -#include <errno.h> -#include <ipxe/settings.h> -#include <ipxe/init.h> -#include <ipxe/uuid.h> -#include <ipxe/smbios.h> - -/** SMBIOS settings scope */ -static const struct settings_scope smbios_settings_scope; - -/** - * Construct SMBIOS raw-data tag - * - * @v _type SMBIOS structure type number - * @v _structure SMBIOS structure data type - * @v _field Field within SMBIOS structure data type - * @ret tag SMBIOS setting tag - */ -#define SMBIOS_RAW_TAG( _type, _structure, _field ) \ - ( ( (_type) << 16 ) | \ - ( offsetof ( _structure, _field ) << 8 ) | \ - ( sizeof ( ( ( _structure * ) 0 )->_field ) ) ) - -/** - * Construct SMBIOS string tag - * - * @v _type SMBIOS structure type number - * @v _structure SMBIOS structure data type - * @v _field Field within SMBIOS structure data type - * @ret tag SMBIOS setting tag - */ -#define SMBIOS_STRING_TAG( _type, _structure, _field ) \ - ( ( (_type) << 16 ) | \ - ( offsetof ( _structure, _field ) << 8 ) ) - -/** - * Check applicability of SMBIOS setting - * - * @v settings Settings block - * @v setting Setting - * @ret applies Setting applies within this settings block - */ -static int smbios_applies ( struct settings *settings __unused, - const struct setting *setting ) { - - return ( setting->scope == &smbios_settings_scope ); -} - -/** - * Fetch value of SMBIOS setting - * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch - * @v data Buffer to fill with setting data - * @v len Length of buffer - * @ret len Length of setting data, or negative error - */ -static int smbios_fetch ( struct settings *settings __unused, - struct setting *setting, - void *data, size_t len ) { - struct smbios_structure structure; - unsigned int tag_instance; - unsigned int tag_type; - unsigned int tag_offset; - unsigned int tag_len; - int rc; - - /* Split tag into instance, type, offset and length */ - tag_instance = ( ( setting->tag >> 24 ) & 0xff ); - tag_type = ( ( setting->tag >> 16 ) & 0xff ); - tag_offset = ( ( setting->tag >> 8 ) & 0xff ); - tag_len = ( setting->tag & 0xff ); - - /* Find SMBIOS structure */ - if ( ( rc = find_smbios_structure ( tag_type, tag_instance, - &structure ) ) != 0 ) - return rc; - - { - uint8_t buf[structure.header.len]; - const void *raw; - union uuid uuid; - unsigned int index; - - /* Read SMBIOS structure */ - if ( ( rc = read_smbios_structure ( &structure, buf, - sizeof ( buf ) ) ) != 0 ) - return rc; - - /* A <length> of zero indicates that the byte at - * <offset> contains a string index. An <offset> of - * zero indicates that the <length> contains a literal - * string index. - */ - if ( ( tag_len == 0 ) || ( tag_offset == 0 ) ) { - index = ( ( tag_offset == 0 ) ? - tag_len : buf[tag_offset] ); - if ( ( rc = read_smbios_string ( &structure, index, - data, len ) ) < 0 ) { - return rc; - } - if ( ! setting->type ) - setting->type = &setting_type_string; - return rc; - } - - /* Mangle UUIDs if necessary. iPXE treats UUIDs as - * being in network byte order (big-endian). SMBIOS - * specification version 2.6 states that UUIDs are - * stored with little-endian values in the first three - * fields; earlier versions did not specify an - * endianness. dmidecode assumes that the byte order - * is little-endian if and only if the SMBIOS version - * is 2.6 or higher; we match this behaviour. - */ - raw = &buf[tag_offset]; - if ( ( setting->type == &setting_type_uuid ) && - ( tag_len == sizeof ( uuid ) ) && - ( smbios_version() >= SMBIOS_VERSION ( 2, 6 ) ) ) { - DBG ( "SMBIOS detected mangled UUID\n" ); - memcpy ( &uuid, &buf[tag_offset], sizeof ( uuid ) ); - uuid_mangle ( &uuid ); - raw = &uuid; - } - - /* Return data */ - if ( len > tag_len ) - len = tag_len; - memcpy ( data, raw, len ); - if ( ! setting->type ) - setting->type = &setting_type_hex; - return tag_len; - } -} - -/** SMBIOS settings operations */ -static struct settings_operations smbios_settings_operations = { - .applies = smbios_applies, - .fetch = smbios_fetch, -}; - -/** SMBIOS settings */ -static struct settings smbios_settings = { - .refcnt = NULL, - .siblings = LIST_HEAD_INIT ( smbios_settings.siblings ), - .children = LIST_HEAD_INIT ( smbios_settings.children ), - .op = &smbios_settings_operations, - .default_scope = &smbios_settings_scope, -}; - -/** Initialise SMBIOS settings */ -static void smbios_init ( void ) { - int rc; - - if ( ( rc = register_settings ( &smbios_settings, NULL, - "smbios" ) ) != 0 ) { - DBG ( "SMBIOS could not register settings: %s\n", - strerror ( rc ) ); - return; - } -} - -/** SMBIOS settings initialiser */ -struct init_fn smbios_init_fn __init_fn ( INIT_NORMAL ) = { - .initialise = smbios_init, -}; - -/** UUID setting obtained via SMBIOS */ -const struct setting uuid_setting __setting ( SETTING_HOST, uuid ) = { - .name = "uuid", - .description = "UUID", - .tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, - struct smbios_system_information, uuid ), - .type = &setting_type_uuid, - .scope = &smbios_settings_scope, -}; - -/** Manufacturer name setting */ -const struct setting manufacturer_setting __setting ( SETTING_HOST_EXTRA, - manufacturer ) = { - .name = "manufacturer", - .description = "Manufacturer", - .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, - struct smbios_system_information, - manufacturer ), - .type = &setting_type_string, - .scope = &smbios_settings_scope, -}; - -/** Product name setting */ -const struct setting product_setting __setting ( SETTING_HOST_EXTRA, product )={ - .name = "product", - .description = "Product name", - .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, - struct smbios_system_information, - product ), - .type = &setting_type_string, - .scope = &smbios_settings_scope, -}; - -/** Serial number setting */ -const struct setting serial_setting __setting ( SETTING_HOST_EXTRA, serial ) = { - .name = "serial", - .description = "Serial number", - .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, - struct smbios_system_information, - serial ), - .type = &setting_type_string, - .scope = &smbios_settings_scope, -}; - -/** Asset tag setting */ -const struct setting asset_setting __setting ( SETTING_HOST_EXTRA, asset ) = { - .name = "asset", - .description = "Asset tag", - .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_ENCLOSURE_INFORMATION, - struct smbios_enclosure_information, - asset_tag ), - .type = &setting_type_string, - .scope = &smbios_settings_scope, -}; - -/** Board serial number setting (may differ from chassis serial number) */ -const struct setting board_serial_setting __setting ( SETTING_HOST_EXTRA, - board_serial ) = { - .name = "board-serial", - .description = "Base board serial", - .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_BASE_BOARD_INFORMATION, - struct smbios_base_board_information, - serial ), - .type = &setting_type_string, - .scope = &smbios_settings_scope, -}; diff --git a/qemu/roms/ipxe/src/interface/xen/xenbus.c b/qemu/roms/ipxe/src/interface/xen/xenbus.c deleted file mode 100644 index c328af443..000000000 --- a/qemu/roms/ipxe/src/interface/xen/xenbus.c +++ /dev/null @@ -1,397 +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 (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 <stdio.h> -#include <errno.h> -#include <ipxe/malloc.h> -#include <ipxe/device.h> -#include <ipxe/timer.h> -#include <ipxe/nap.h> -#include <ipxe/xen.h> -#include <ipxe/xenstore.h> -#include <ipxe/xenbus.h> - -/** @file - * - * Xen device bus - * - */ - -/* Disambiguate the various error causes */ -#define ETIMEDOUT_UNKNOWN \ - __einfo_error ( EINFO_ETIMEDOUT_UNKNOWN ) -#define EINFO_ETIMEDOUT_UNKNOWN \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateUnknown, \ - "Unknown" ) -#define ETIMEDOUT_INITIALISING \ - __einfo_error ( EINFO_ETIMEDOUT_INITIALISING ) -#define EINFO_ETIMEDOUT_INITIALISING \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitialising, \ - "Initialising" ) -#define ETIMEDOUT_INITWAIT \ - __einfo_error ( EINFO_ETIMEDOUT_INITWAIT ) -#define EINFO_ETIMEDOUT_INITWAIT \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitWait, \ - "InitWait" ) -#define ETIMEDOUT_INITIALISED \ - __einfo_error ( EINFO_ETIMEDOUT_INITIALISED ) -#define EINFO_ETIMEDOUT_INITIALISED \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitialised, \ - "Initialised" ) -#define ETIMEDOUT_CONNECTED \ - __einfo_error ( EINFO_ETIMEDOUT_CONNECTED ) -#define EINFO_ETIMEDOUT_CONNECTED \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateConnected, \ - "Connected" ) -#define ETIMEDOUT_CLOSING \ - __einfo_error ( EINFO_ETIMEDOUT_CLOSING ) -#define EINFO_ETIMEDOUT_CLOSING \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateClosing, \ - "Closing" ) -#define ETIMEDOUT_CLOSED \ - __einfo_error ( EINFO_ETIMEDOUT_CLOSED ) -#define EINFO_ETIMEDOUT_CLOSED \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateClosed, \ - "Closed" ) -#define ETIMEDOUT_RECONFIGURING \ - __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURING ) -#define EINFO_ETIMEDOUT_RECONFIGURING \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateReconfiguring, \ - "Reconfiguring" ) -#define ETIMEDOUT_RECONFIGURED \ - __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURED ) -#define EINFO_ETIMEDOUT_RECONFIGURED \ - __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateReconfigured, \ - "Reconfigured" ) -#define ETIMEDOUT_STATE( state ) \ - EUNIQ ( EINFO_ETIMEDOUT, (state), ETIMEDOUT_UNKNOWN, \ - ETIMEDOUT_INITIALISING, ETIMEDOUT_INITWAIT, \ - ETIMEDOUT_INITIALISED, ETIMEDOUT_CONNECTED, \ - ETIMEDOUT_CLOSING, ETIMEDOUT_CLOSED, \ - ETIMEDOUT_RECONFIGURING, ETIMEDOUT_RECONFIGURED ) - -/** Maximum time to wait for backend to reach a given state, in ticks */ -#define XENBUS_BACKEND_TIMEOUT ( 5 * TICKS_PER_SEC ) - -/** - * Set device state - * - * @v xendev Xen device - * @v state New state - * @ret rc Return status code - */ -int xenbus_set_state ( struct xen_device *xendev, int state ) { - int rc; - - /* Attempt to set state */ - if ( ( rc = xenstore_write_num ( xendev->xen, state, xendev->key, - "state", NULL ) ) != 0 ) { - DBGC ( xendev, "XENBUS %s could not set state=\"%d\": %s\n", - xendev->key, state, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Get backend state - * - * @v xendev Xen device - * @ret state Backend state, or negative error - */ -int xenbus_backend_state ( struct xen_device *xendev ) { - unsigned long state; - int rc; - - /* Attempt to get backend state */ - if ( ( rc = xenstore_read_num ( xendev->xen, &state, xendev->backend, - "state", NULL ) ) != 0 ) { - DBGC ( xendev, "XENBUS %s could not read %s/state: %s\n", - xendev->key, xendev->backend, strerror ( rc ) ); - return rc; - } - - return state; -} - -/** - * Wait for backend to reach a given state - * - * @v xendev Xen device - * @v state Desired backend state - * @ret rc Return status code - */ -int xenbus_backend_wait ( struct xen_device *xendev, int state ) { - unsigned long started = currticks(); - unsigned long elapsed; - unsigned int attempts = 0; - int current_state; - int rc; - - /* Wait for backend to reach this state */ - do { - - /* Get current backend state */ - current_state = xenbus_backend_state ( xendev ); - if ( current_state < 0 ) { - rc = current_state; - return rc; - } - if ( current_state == state ) - return 0; - - /* Allow time for backend to react */ - cpu_nap(); - - /* XenStore is a very slow interface; any fixed delay - * time would be dwarfed by the XenStore access time. - * We therefore use wall clock to time out this - * operation. - */ - elapsed = ( currticks() - started ); - attempts++; - - } while ( elapsed < XENBUS_BACKEND_TIMEOUT ); - - /* Construct status code from current backend state */ - rc = -ETIMEDOUT_STATE ( current_state ); - DBGC ( xendev, "XENBUS %s timed out after %d attempts waiting for " - "%s/state=\"%d\": %s\n", xendev->key, attempts, xendev->backend, - state, strerror ( rc ) ); - - return rc; -} - -/** - * Find driver for Xen device - * - * @v type Device type - * @ret driver Driver, or NULL - */ -static struct xen_driver * xenbus_find_driver ( const char *type ) { - struct xen_driver *xendrv; - - for_each_table_entry ( xendrv, XEN_DRIVERS ) { - if ( strcmp ( xendrv->type, type ) == 0 ) - return xendrv; - } - return NULL; -} - -/** - * Probe Xen device - * - * @v xen Xen hypervisor - * @v parent Parent device - * @v type Device type - * @v instance Device instance - * @ret rc Return status code - */ -static int xenbus_probe_device ( struct xen_hypervisor *xen, - struct device *parent, const char *type, - const char *instance ) { - struct xen_device *xendev; - size_t key_len; - int rc; - - /* Allocate and initialise structure */ - key_len = ( 7 /* "device/" */ + strlen ( type ) + 1 /* "/" */ + - strlen ( instance ) + 1 /* NUL */ ); - xendev = zalloc ( sizeof ( *xendev ) + key_len ); - if ( ! xendev ) { - rc = -ENOMEM; - goto err_alloc; - } - snprintf ( xendev->dev.name, sizeof ( xendev->dev.name ), "%s/%s", - type, instance ); - xendev->dev.desc.bus_type = BUS_TYPE_XEN; - INIT_LIST_HEAD ( &xendev->dev.children ); - list_add_tail ( &xendev->dev.siblings, &parent->children ); - xendev->dev.parent = parent; - xendev->xen = xen; - xendev->key = ( ( void * ) ( xendev + 1 ) ); - snprintf ( xendev->key, key_len, "device/%s/%s", type, instance ); - - /* Read backend key */ - if ( ( rc = xenstore_read ( xen, &xendev->backend, xendev->key, - "backend", NULL ) ) != 0 ) { - DBGC ( xendev, "XENBUS %s could not read backend: %s\n", - xendev->key, strerror ( rc ) ); - goto err_read_backend; - } - - /* Read backend domain ID */ - if ( ( rc = xenstore_read_num ( xen, &xendev->backend_id, xendev->key, - "backend-id", NULL ) ) != 0 ) { - DBGC ( xendev, "XENBUS %s could not read backend-id: %s\n", - xendev->key, strerror ( rc ) ); - goto err_read_backend_id; - } - DBGC ( xendev, "XENBUS %s backend=\"%s\" in domain %ld\n", - xendev->key, xendev->backend, xendev->backend_id ); - - /* Look for a driver */ - xendev->driver = xenbus_find_driver ( type ); - if ( ! xendev->driver ) { - DBGC ( xendev, "XENBUS %s has no driver\n", xendev->key ); - /* Not a fatal error */ - rc = 0; - goto err_no_driver; - } - xendev->dev.driver_name = xendev->driver->name; - DBGC ( xendev, "XENBUS %s has driver \"%s\"\n", xendev->key, - xendev->driver->name ); - - /* Probe driver */ - if ( ( rc = xendev->driver->probe ( xendev ) ) != 0 ) { - DBGC ( xendev, "XENBUS could not probe %s: %s\n", - xendev->key, strerror ( rc ) ); - goto err_probe; - } - - return 0; - - xendev->driver->remove ( xendev ); - err_probe: - err_no_driver: - err_read_backend_id: - free ( xendev->backend ); - err_read_backend: - list_del ( &xendev->dev.siblings ); - free ( xendev ); - err_alloc: - return rc; -} - -/** - * Remove Xen device - * - * @v xendev Xen device - */ -static void xenbus_remove_device ( struct xen_device *xendev ) { - - /* Remove device */ - xendev->driver->remove ( xendev ); - free ( xendev->backend ); - list_del ( &xendev->dev.siblings ); - free ( xendev ); -} - -/** - * Probe Xen devices of a given type - * - * @v xen Xen hypervisor - * @v parent Parent device - * @v type Device type - * @ret rc Return status code - */ -static int xenbus_probe_type ( struct xen_hypervisor *xen, - struct device *parent, const char *type ) { - char *children; - char *child; - size_t len; - int rc; - - /* Get children of this key */ - if ( ( rc = xenstore_directory ( xen, &children, &len, "device", - type, NULL ) ) != 0 ) { - DBGC ( xen, "XENBUS could not list \"%s\" devices: %s\n", - type, strerror ( rc ) ); - goto err_directory; - } - - /* Probe each child */ - for ( child = children ; child < ( children + len ) ; - child += ( strlen ( child ) + 1 /* NUL */ ) ) { - if ( ( rc = xenbus_probe_device ( xen, parent, type, - child ) ) != 0 ) - goto err_probe_device; - } - - free ( children ); - return 0; - - err_probe_device: - free ( children ); - err_directory: - return rc; -} - -/** - * Probe Xen bus - * - * @v xen Xen hypervisor - * @v parent Parent device - * @ret rc Return status code - */ -int xenbus_probe ( struct xen_hypervisor *xen, struct device *parent ) { - char *types; - char *type; - size_t len; - int rc; - - /* Get children of "device" key */ - if ( ( rc = xenstore_directory ( xen, &types, &len, "device", - NULL ) ) != 0 ) { - DBGC ( xen, "XENBUS could not list device types: %s\n", - strerror ( rc ) ); - goto err_directory; - } - - /* Probe each child type */ - for ( type = types ; type < ( types + len ) ; - type += ( strlen ( type ) + 1 /* NUL */ ) ) { - if ( ( rc = xenbus_probe_type ( xen, parent, type ) ) != 0 ) - goto err_probe_type; - } - - free ( types ); - return 0; - - xenbus_remove ( xen, parent ); - err_probe_type: - free ( types ); - err_directory: - return rc; -} - -/** - * Remove Xen bus - * - * @v xen Xen hypervisor - * @v parent Parent device - */ -void xenbus_remove ( struct xen_hypervisor *xen __unused, - struct device *parent ) { - struct xen_device *xendev; - struct xen_device *tmp; - - /* Remove devices */ - list_for_each_entry_safe ( xendev, tmp, &parent->children, - dev.siblings ) { - xenbus_remove_device ( xendev ); - } -} diff --git a/qemu/roms/ipxe/src/interface/xen/xengrant.c b/qemu/roms/ipxe/src/interface/xen/xengrant.c deleted file mode 100644 index 269cd5836..000000000 --- a/qemu/roms/ipxe/src/interface/xen/xengrant.c +++ /dev/null @@ -1,232 +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 (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <strings.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/io.h> -#include <ipxe/xen.h> -#include <ipxe/xengrant.h> - -/** @file - * - * Xen grant tables - * - */ - -/** Grant table version to try setting - * - * Using version 1 grant tables limits guests to using 16TB of - * grantable RAM, and prevents the use of subpage grants. Some - * versions of the Xen hypervisor refuse to allow the grant table - * version to be set after the first grant references have been - * created, so the loaded operating system may be stuck with whatever - * choice we make here. We therefore currently use version 2 grant - * tables, since they give the most flexibility to the loaded OS. - * - * Current versions (7.2.0) of the Windows PV drivers have no support - * for version 2 grant tables, and will merrily create version 1 - * entries in what the hypervisor believes to be a version 2 table. - * This causes some confusion. - * - * Avoid this problem by attempting to use version 1 tables, since - * otherwise we may render Windows unable to boot. - * - * Play nicely with other potential bootloaders by accepting either - * version 1 or version 2 grant tables (if we are unable to set our - * requested version). - */ -#define XENGRANT_TRY_VERSION 1 - -/** - * Initialise grant table - * - * @v xen Xen hypervisor - * @ret rc Return status code - */ -int xengrant_init ( struct xen_hypervisor *xen ) { - struct gnttab_query_size size; - struct gnttab_set_version set_version; - struct gnttab_get_version get_version; - struct grant_entry_v1 *v1; - union grant_entry_v2 *v2; - unsigned int version; - int xenrc; - int rc; - - /* Get grant table size */ - size.dom = DOMID_SELF; - if ( ( xenrc = xengrant_query_size ( xen, &size ) ) != 0 ) { - rc = -EXEN ( xenrc ); - DBGC ( xen, "XENGRANT could not get table size: %s\n", - strerror ( rc ) ); - return rc; - } - xen->grant.len = ( size.nr_frames * PAGE_SIZE ); - - /* Set grant table version, if applicable */ - set_version.version = XENGRANT_TRY_VERSION; - if ( ( xenrc = xengrant_set_version ( xen, &set_version ) ) != 0 ) { - rc = -EXEN ( xenrc ); - DBGC ( xen, "XENGRANT could not set version %d: %s\n", - XENGRANT_TRY_VERSION, strerror ( rc ) ); - /* Continue; use whatever version is current */ - } - - /* Get grant table version */ - get_version.dom = DOMID_SELF; - get_version.pad = 0; - if ( ( xenrc = xengrant_get_version ( xen, &get_version ) ) == 0 ) { - version = get_version.version; - switch ( version ) { - - case 0: - /* Version not yet specified: will be version 1 */ - version = 1; - break; - - case 1 : - /* Version 1 table: nothing special to do */ - break; - - case 2: - /* Version 2 table: configure shift appropriately */ - xen->grant.shift = ( fls ( sizeof ( *v2 ) / - sizeof ( *v1 ) ) - 1 ); - break; - - default: - /* Unsupported version */ - DBGC ( xen, "XENGRANT detected unsupported version " - "%d\n", version ); - return -ENOTSUP; - - } - } else { - rc = -EXEN ( xenrc ); - DBGC ( xen, "XENGRANT could not get version (assuming v1): " - "%s\n", strerror ( rc ) ); - version = 1; - } - - DBGC ( xen, "XENGRANT using v%d table with %d entries\n", - version, xengrant_entries ( xen ) ); - return 0; -} - -/** - * Allocate grant references - * - * @v xen Xen hypervisor - * @v refs Grant references to fill in - * @v count Number of references - * @ret rc Return status code - */ -int xengrant_alloc ( struct xen_hypervisor *xen, grant_ref_t *refs, - unsigned int count ) { - struct grant_entry_header *hdr; - unsigned int entries = xengrant_entries ( xen ); - unsigned int mask = ( entries - 1 ); - unsigned int check = 0; - unsigned int avail; - unsigned int ref; - - /* Fail unless we have enough references available */ - avail = ( entries - xen->grant.used - GNTTAB_NR_RESERVED_ENTRIES ); - if ( avail < count ) { - DBGC ( xen, "XENGRANT cannot allocate %d references (only %d " - "of %d available)\n", count, avail, entries ); - return -ENOBUFS; - } - DBGC ( xen, "XENGRANT allocating %d references (from %d of %d " - "available)\n", count, avail, entries ); - - /* Update number of references used */ - xen->grant.used += count; - - /* Find unused references */ - for ( ref = xen->grant.ref ; count ; ref = ( ( ref + 1 ) & mask ) ) { - - /* Sanity check */ - assert ( check++ < entries ); - - /* Skip reserved references */ - if ( ref < GNTTAB_NR_RESERVED_ENTRIES ) - continue; - - /* Skip in-use references */ - hdr = xengrant_header ( xen, ref ); - if ( readw ( &hdr->flags ) & GTF_type_mask ) - continue; - if ( readw ( &hdr->domid ) == DOMID_SELF ) - continue; - - /* Zero reference */ - xengrant_zero ( xen, hdr ); - - /* Mark reference as in-use. We leave the flags as - * empty (to avoid creating a valid grant table entry) - * and set the domid to DOMID_SELF. - */ - writew ( DOMID_SELF, &hdr->domid ); - DBGC2 ( xen, "XENGRANT allocated ref %d\n", ref ); - - /* Record reference */ - refs[--count] = ref; - } - - /* Update cursor */ - xen->grant.ref = ref; - - return 0; -} - -/** - * Free grant references - * - * @v xen Xen hypervisor - * @v refs Grant references - * @v count Number of references - */ -void xengrant_free ( struct xen_hypervisor *xen, grant_ref_t *refs, - unsigned int count ) { - struct grant_entry_header *hdr; - unsigned int ref; - unsigned int i; - - /* Free references */ - for ( i = 0 ; i < count ; i++ ) { - - /* Sanity check */ - ref = refs[i]; - assert ( ref < xengrant_entries ( xen ) ); - - /* Zero reference */ - hdr = xengrant_header ( xen, ref ); - xengrant_zero ( xen, hdr ); - DBGC2 ( xen, "XENGRANT freed ref %d\n", ref ); - } -} diff --git a/qemu/roms/ipxe/src/interface/xen/xenstore.c b/qemu/roms/ipxe/src/interface/xen/xenstore.c deleted file mode 100644 index 23424a926..000000000 --- a/qemu/roms/ipxe/src/interface/xen/xenstore.c +++ /dev/null @@ -1,555 +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 (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ipxe/io.h> -#include <ipxe/nap.h> -#include <ipxe/malloc.h> -#include <ipxe/xen.h> -#include <ipxe/xenevent.h> -#include <ipxe/xenstore.h> - -/* - * xs_wire.h attempts to define a static error table xsd_errors, which - * interacts badly with the dynamically generated error numbers used - * by iPXE. Prevent this table from being constructed by including - * errno.h only after including xs_wire.h. - * - */ -#include <xen/io/xs_wire.h> -#include <errno.h> - -/** @file - * - * XenStore interface - * - */ - -/** Request identifier */ -static uint32_t xenstore_req_id; - -/** - * Send XenStore request raw data - * - * @v xen Xen hypervisor - * @v data Data buffer - * @v len Length of data - */ -static void xenstore_send ( struct xen_hypervisor *xen, const void *data, - size_t len ) { - struct xenstore_domain_interface *intf = xen->store.intf; - XENSTORE_RING_IDX prod = readl ( &intf->req_prod ); - XENSTORE_RING_IDX cons; - XENSTORE_RING_IDX idx; - const char *bytes = data; - size_t offset = 0; - size_t fill; - - DBGCP ( intf, "XENSTORE raw request:\n" ); - DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len ); - - /* Write one byte at a time */ - while ( offset < len ) { - - /* Wait for space to become available */ - while ( 1 ) { - cons = readl ( &intf->req_cons ); - fill = ( prod - cons ); - if ( fill < XENSTORE_RING_SIZE ) - break; - DBGC2 ( xen, "." ); - cpu_nap(); - rmb(); - } - - /* Write byte */ - idx = MASK_XENSTORE_IDX ( prod++ ); - writeb ( bytes[offset++], &intf->req[idx] ); - } - - /* Update producer counter */ - wmb(); - writel ( prod, &intf->req_prod ); - wmb(); -} - -/** - * Send XenStore request string (excluding terminating NUL) - * - * @v xen Xen hypervisor - * @v string String - */ -static void xenstore_send_string ( struct xen_hypervisor *xen, - const char *string ) { - - xenstore_send ( xen, string, strlen ( string ) ); -} - -/** - * Receive XenStore response raw data - * - * @v xen Xen hypervisor - * @v data Data buffer, or NULL to discard data - * @v len Length of data - */ -static void xenstore_recv ( struct xen_hypervisor *xen, void *data, - size_t len ) { - struct xenstore_domain_interface *intf = xen->store.intf; - XENSTORE_RING_IDX cons = readl ( &intf->rsp_cons ); - XENSTORE_RING_IDX prod; - XENSTORE_RING_IDX idx; - char *bytes = data; - size_t offset = 0; - size_t fill; - - DBGCP ( intf, "XENSTORE raw response:\n" ); - - /* Read one byte at a time */ - while ( offset < len ) { - - /* Wait for data to be ready */ - while ( 1 ) { - prod = readl ( &intf->rsp_prod ); - fill = ( prod - cons ); - if ( fill > 0 ) - break; - DBGC2 ( xen, "." ); - cpu_nap(); - rmb(); - } - - /* Read byte */ - idx = MASK_XENSTORE_IDX ( cons++ ); - if ( data ) - bytes[offset++] = readb ( &intf->rsp[idx] ); - } - if ( data ) - DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len ); - - /* Update consumer counter */ - writel ( cons, &intf->rsp_cons ); - wmb(); -} - -/** - * Send XenStore request - * - * @v xen Xen hypervisor - * @v type Message type - * @v req_id Request ID - * @v value Value, or NULL to omit - * @v key Key path components - * @ret rc Return status code - */ -static int xenstore_request ( struct xen_hypervisor *xen, - enum xsd_sockmsg_type type, uint32_t req_id, - const char *value, va_list key ) { - struct xsd_sockmsg msg; - struct evtchn_send event; - const char *string; - va_list tmp; - int xenrc; - int rc; - - /* Construct message header */ - msg.type = type; - msg.req_id = req_id; - msg.tx_id = 0; - msg.len = 0; - DBGC2 ( xen, "XENSTORE request ID %d type %d ", req_id, type ); - - /* Calculate total length */ - va_copy ( tmp, key ); - while ( ( string = va_arg ( tmp, const char * ) ) != NULL ) { - DBGC2 ( xen, "%s%s", ( msg.len ? "/" : "" ), string ); - msg.len += ( strlen ( string ) + 1 /* '/' or NUL */ ); - } - va_end ( tmp ); - if ( value ) { - DBGC2 ( xen, " = \"%s\"", value ); - msg.len += strlen ( value ); - } - DBGC2 ( xen, "\n" ); - - /* Send message */ - xenstore_send ( xen, &msg, sizeof ( msg ) ); - string = va_arg ( key, const char * ); - assert ( string != NULL ); - xenstore_send_string ( xen, string ); - while ( ( string = va_arg ( key, const char * ) ) != NULL ) { - xenstore_send_string ( xen, "/" ); - xenstore_send_string ( xen, string ); - } - xenstore_send ( xen, "", 1 ); /* Separating NUL */ - if ( value ) - xenstore_send_string ( xen, value ); - - /* Notify the back end */ - event.port = xen->store.port; - if ( ( xenrc = xenevent_send ( xen, &event ) ) != 0 ) { - rc = -EXEN ( xenrc ); - DBGC ( xen, "XENSTORE could not notify back end: %s\n", - strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Receive XenStore response - * - * @v xen Xen hypervisor - * @v req_id Request ID - * @v value Value to fill in - * @v len Length to fill in - * @ret rc Return status code - * - * The caller is responsible for eventually calling free() on the - * returned value. Note that the value may comprise multiple - * NUL-terminated strings concatenated together. A terminating NUL - * will always be appended to the returned value. - */ -static int xenstore_response ( struct xen_hypervisor *xen, uint32_t req_id, - char **value, size_t *len ) { - struct xsd_sockmsg msg; - char *string; - int rc; - - /* Wait for response to become available */ - while ( ! xenevent_pending ( xen, xen->store.port ) ) - cpu_nap(); - - /* Receive message header */ - xenstore_recv ( xen, &msg, sizeof ( msg ) ); - *len = msg.len; - - /* Allocate space for response */ - *value = zalloc ( msg.len + 1 /* terminating NUL */ ); - - /* Receive data. Do this even if allocation failed, or if the - * request ID was incorrect, to avoid leaving data in the - * ring. - */ - xenstore_recv ( xen, *value, msg.len ); - - /* Validate request ID */ - if ( msg.req_id != req_id ) { - DBGC ( xen, "XENSTORE response ID mismatch (got %d, expected " - "%d)\n", msg.req_id, req_id ); - rc = -EPROTO; - goto err_req_id; - } - - /* Check for allocation failure */ - if ( ! *value ) { - DBGC ( xen, "XENSTORE could not allocate %d bytes for " - "response\n", msg.len ); - rc = -ENOMEM; - goto err_alloc; - } - - /* Check for explicit errors */ - if ( msg.type == XS_ERROR ) { - DBGC ( xen, "XENSTORE response error \"%s\"\n", *value ); - rc = -EIO; - goto err_explicit; - } - - DBGC2 ( xen, "XENSTORE response ID %d\n", req_id ); - if ( DBG_EXTRA ) { - for ( string = *value ; string < ( *value + msg.len ) ; - string += ( strlen ( string ) + 1 /* NUL */ ) ) { - DBGC2 ( xen, " - \"%s\"\n", string ); - } - } - return 0; - - err_explicit: - err_alloc: - err_req_id: - free ( *value ); - *value = NULL; - return rc; -} - -/** - * Issue a XenStore message - * - * @v xen Xen hypervisor - * @v type Message type - * @v response Response value to fill in, or NULL to discard - * @v len Response length to fill in, or NULL to ignore - * @v request Request value, or NULL to omit - * @v key Key path components - * @ret rc Return status code - */ -static int xenstore_message ( struct xen_hypervisor *xen, - enum xsd_sockmsg_type type, char **response, - size_t *len, const char *request, va_list key ) { - char *response_value; - size_t response_len; - int rc; - - /* Send request */ - if ( ( rc = xenstore_request ( xen, type, ++xenstore_req_id, - request, key ) ) != 0 ) - return rc; - - /* Receive response */ - if ( ( rc = xenstore_response ( xen, xenstore_req_id, &response_value, - &response_len ) ) != 0 ) - return rc; - - /* Return response, if applicable */ - if ( response ) { - *response = response_value; - } else { - free ( response_value ); - } - if ( len ) - *len = response_len; - - return 0; -} - -/** - * Read XenStore value - * - * @v xen Xen hypervisor - * @v value Value to fill in - * @v key Key path components - * @ret rc Return status code - * - * On a successful return, the caller is responsible for calling - * free() on the returned value. - */ -static int xenstore_vread ( struct xen_hypervisor *xen, char **value, - va_list key ) { - - return xenstore_message ( xen, XS_READ, value, NULL, NULL, key ); -} - -/** - * Read XenStore value - * - * @v xen Xen hypervisor - * @v value Value to fill in - * @v ... Key path components - * @ret rc Return status code - * - * On a successful return, the caller is responsible for calling - * free() on the returned value. - */ -__attribute__ (( sentinel )) int -xenstore_read ( struct xen_hypervisor *xen, char **value, ... ) { - va_list key; - int rc; - - va_start ( key, value ); - rc = xenstore_vread ( xen, value, key ); - va_end ( key ); - return rc; -} - -/** - * Read XenStore numeric value - * - * @v xen Xen hypervisor - * @v num Numeric value to fill in - * @v ... Key path components - * @ret rc Return status code - */ -__attribute__ (( sentinel )) int -xenstore_read_num ( struct xen_hypervisor *xen, unsigned long *num, ... ) { - va_list key; - char *value; - char *endp; - int rc; - - /* Try to read text value */ - va_start ( key, num ); - rc = xenstore_vread ( xen, &value, key ); - va_end ( key ); - if ( rc != 0 ) - goto err_read; - - /* Try to parse as numeric value */ - *num = strtoul ( value, &endp, 10 ); - if ( ( *value == '\0' ) || ( *endp != '\0' ) ) { - DBGC ( xen, "XENSTORE found invalid numeric value \"%s\"\n", - value ); - rc = -EINVAL; - goto err_strtoul; - } - - err_strtoul: - free ( value ); - err_read: - return rc; -} - -/** - * Write XenStore value - * - * @v xen Xen hypervisor - * @v value Value - * @v key Key path components - * @ret rc Return status code - */ -static int xenstore_vwrite ( struct xen_hypervisor *xen, const char *value, - va_list key ) { - - return xenstore_message ( xen, XS_WRITE, NULL, NULL, value, key ); -} - -/** - * Write XenStore value - * - * @v xen Xen hypervisor - * @v value Value - * @v ... Key path components - * @ret rc Return status code - */ -__attribute__ (( sentinel )) int -xenstore_write ( struct xen_hypervisor *xen, const char *value, ... ) { - va_list key; - int rc; - - va_start ( key, value ); - rc = xenstore_vwrite ( xen, value, key ); - va_end ( key ); - return rc; -} - -/** - * Write XenStore numeric value - * - * @v xen Xen hypervisor - * @v num Numeric value - * @v ... Key path components - * @ret rc Return status code - */ -__attribute__ (( sentinel )) int -xenstore_write_num ( struct xen_hypervisor *xen, unsigned long num, ... ) { - char value[ 21 /* "18446744073709551615" + NUL */ ]; - va_list key; - int rc; - - /* Construct value */ - snprintf ( value, sizeof ( value ), "%ld", num ); - - /* Write value */ - va_start ( key, num ); - rc = xenstore_vwrite ( xen, value, key ); - va_end ( key ); - return rc; -} - -/** - * Delete XenStore value - * - * @v xen Xen hypervisor - * @v ... Key path components - * @ret rc Return status code - */ -__attribute__ (( sentinel )) int -xenstore_rm ( struct xen_hypervisor *xen, ... ) { - va_list key; - int rc; - - va_start ( key, xen ); - rc = xenstore_message ( xen, XS_RM, NULL, NULL, NULL, key ); - va_end ( key ); - return rc; -} - -/** - * Read XenStore directory - * - * @v xen Xen hypervisor - * @v children Child key names to fill in - * @v len Length of child key names to fill in - * @v ... Key path components - * @ret rc Return status code - */ -__attribute__ (( sentinel )) int -xenstore_directory ( struct xen_hypervisor *xen, char **children, size_t *len, - ... ) { - va_list key; - int rc; - - va_start ( key, len ); - rc = xenstore_message ( xen, XS_DIRECTORY, children, len, NULL, key ); - va_end ( key ); - return rc; -} - -/** - * Dump XenStore directory contents (for debugging) - * - * @v xen Xen hypervisor - * @v key Key - */ -void xenstore_dump ( struct xen_hypervisor *xen, const char *key ) { - char *value; - char *children; - char *child; - char *child_key; - size_t len; - int rc; - - /* Try to dump current key as a value */ - if ( ( rc = xenstore_read ( xen, &value, key, NULL ) ) == 0 ) { - DBGC ( xen, "%s = \"%s\"\n", key, value ); - free ( value ); - } - - /* Try to recurse into each child in turn */ - if ( ( rc = xenstore_directory ( xen, &children, &len, key, - NULL ) ) == 0 ) { - for ( child = children ; child < ( children + len ) ; - child += ( strlen ( child ) + 1 /* NUL */ ) ) { - - /* Construct child key */ - asprintf ( &child_key, "%s/%s", key, child ); - if ( ! child_key ) { - DBGC ( xen, "XENSTORE could not allocate child " - "key \"%s/%s\"\n", key, child ); - rc = -ENOMEM; - break; - } - - /* Recurse into child key, continuing on error */ - xenstore_dump ( xen, child_key ); - free ( child_key ); - } - free ( children ); - } -} |