DevEFI.cpp revision c28fa006ba669ad8f26ae31d00a338379c04ea1b
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * DevEFI - EFI <-> VirtualBox Integration Framework.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Copyright (C) 2006-2009 Sun Microsystems, Inc.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * This file is part of VirtualBox Open Source Edition (OSE), as
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * available from http://www.virtualbox.org. This file is free software;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * you can redistribute it and/or modify it under the terms of the GNU
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * General Public License (GPL) as published by the Free Software
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Foundation, in version 2 as it comes in the "COPYING" file of the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Clara, CA 95054 USA or visit http://www.sun.com if you need
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * additional information or have any questions.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/*******************************************************************************
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk* Header Files *
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk*******************************************************************************/
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* EFI includes */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/*******************************************************************************
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk* Structures and Typedefs *
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk*******************************************************************************/
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenktypedef struct DEVEFI
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer back to the device instance. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** EFI message buffer. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** EFI message buffer index. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** EFI panic message buffer. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** EFI panic message buffer index. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** The system EFI ROM data. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** The size of the system EFI ROM. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** The name of the EFI ROM file. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Thunk page pointer. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** First entry point of the EFI firmware */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Second Entry Point (PeiCore)*/
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** EFI firmware physical load address */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Current info selector */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Current info position */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Number of virtual CPUs. (Config) */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** RAM below 4GB (in bytes). (Config) */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** RAM above 4GB (in bytes). (Config) */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** The DMI tables. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** I/O-APIC enabled? */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Boot parameters passed to the firmware */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Host UUID (for DMI) */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Write to CMOS memory.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * This is used by the init complete code.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic void cmosWrite(PPDMDEVINS pDevIns, int off, uint32_t u32Val)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk int rc = PDMDevHlpCMOSWrite(pDevIns, off, u32Val);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return RTStrNLen(pThis->pszBootArgs, sizeof pThis->pszBootArgs) + 1;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk iValue = VBOX_EFI_TOP_OF_STACK; /* just after stack */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Keep in sync with value in EfiThunk.asm */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk iValue = VBOX_EFI_TOP_OF_STACK - 128*1024; /* 2M - 128 K */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return pThis->pszBootArgs[pThis->iInfoPosition];
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* somewhat ugly, but works atm */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return *((uint8_t*)&iValue+pThis->iInfoPosition);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Port I/O Handler for IN operations.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @returns VBox status code.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param pDevIns The device instance.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param pvUser User argument - ignored.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param Port Port number used for the IN operation.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param pu32 Where to store the result.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param cb Number of bytes read.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic DECLCALLBACK(int) efiIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* So far */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Insert special code here on panic reads */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Reschedule to R3 */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Port I/O Handler for OUT operations.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @returns VBox status code.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param pDevIns The device instance.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param pvUser User argument - ignored.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param Port Port number used for the IN operation.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param u32 The value to output.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param cb The value size in bytes.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic DECLCALLBACK(int) efiIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* The raw version. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk default: Log3(("efi: %c (%02x)\n", u32, u32)); break;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* The readable, buffered version. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk const char *pszVBoxDbg = strstr(pThis->szMsg, "VBoxDbg> ");
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk int rc = RTStrmOpen("./DevEFI.VBoxDbg", "a", &pStrm);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk LogRel(("EFI Panic: You have to fix ORG offset in EfiThunk.asm! Must be 0x%x\n",
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk RTAssertMsg2Weak("Fix ORG offset in EfiThunk.asm: must be 0x%x\n",
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "EFI Panic: Unexpected trap during early bootstrap!\n");
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk AssertReleaseMsgFailed(("Unexpected trap during early EFI bootstrap!!\n"));
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "EFI Panic: %s\n", pThis->szPanicMsg);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Add the message char to the buffer. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk Log(("EFI: Unknown panic command: %#x (cb=%d)\n", u32, cb));
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk Log(("EFI: Write to reserved port %RTiop: %#x (cb=%d)\n", Port, u32, cb));
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Init complete notification.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @returns VBOX status code.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param pDevIns The device instance.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic DECLCALLBACK(int) efiInitComplete(PPDMDEVINS pDevIns)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* PC Bios */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Memory sizes.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk uint64_t const offRamHole = _4G - pThis->cbRamHole;
u32 = (uint32_t)( (RT_MIN(RT_MIN(pThis->cbRam, offRamHole), UINT32_C(0xffe00000)) - 16U * _1M) / _64K );
u32 = 0;
return VINF_SUCCESS;
int rc;
while (cPages > 0)
cPages--;
return VINF_SUCCESS;
efiFwVolFindFileByType(EFI_FFS_FILE_HEADER const *pFfsFile, uint8_t const *pbEnd, EFI_FV_FILETYPE FileType, uint32_t *pcbFile)
return pFfsFile;
return NULL;
static int efiFindEntryPoint(EFI_FFS_FILE_HEADER const *pFfsFile, uint32_t cbFfsFile, RTGCPHYS *pImageBase, uint8_t **ppbImage)
pbImage = (uint8_t const *)&uSecHdrPtr.Pe32Section[1]; /* the PE/PE+/TE headers begins just after the Section Header */
AssertLogRelMsgReturn(pbImage, ("Failed to find PE32 or TE section for the SECURITY_CORE FFS\n"), VERR_INVALID_PARAMETER);
union EfiHdrUnion
AssertLogRelMsgReturn(!(pThis->cbEfiRom & PAGE_OFFSET_MASK), ("%RX64\n", pThis->cbEfiRom), VERR_INVALID_PARAMETER);
EFI_FFS_FILE_HEADER const *pFfsFile = (EFI_FFS_FILE_HEADER const *)(pThis->pu8EfiRom + pFwVolHdr->HeaderLength);
AssertLogRelMsgReturn(pFfsFile, ("No SECURITY_CORE found in the firmware volume\n"), VERR_FILE_NOT_FOUND);
return VINF_SUCCESS;
void *pvFile;
&pvFile,
&cbFile);
return rc;
return rc;
return rc;
return rc;
return VINF_SUCCESS;
int rc;
if (f64BitEntry)
return VERR_NO_MEMORY;
return rc;
return rc;
return rc;
int rc;
#ifdef VBOX_WITH_DMI_OEMSTRINGS
/* Convert the UUID to network byte order. Not entirely straightforward as parts are MSB already... */
return VERR_NO_MEMORY;
#ifdef DEVEFI_WITH_VBOXDBG_SCRIPT
return rc;
return rc;
return rc;
return rc;
return VINF_SUCCESS;
sizeof(DEVEFI),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,