diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim')
7 files changed, 1233 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/Console.c b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/Console.c new file mode 100644 index 00000000..fc0e9d03 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/Console.c @@ -0,0 +1,106 @@ +/* $Id: Console.c $ */ +/** @file + * Console.c - VirtualBox Console control emulation + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * 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, in version 3 of the + * License. + * + * 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, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ +#include <Uefi.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/DebugLib.h> + +#include "VBoxPkg.h" +#include "ConsoleControl.h" + +EFI_STATUS EFIAPI +GetModeImpl( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *GopUgaExists, OPTIONAL + OUT BOOLEAN *StdInLocked OPTIONAL + ) +{ + *Mode = EfiConsoleControlScreenGraphics; + + if (GopUgaExists) + *GopUgaExists = TRUE; + if (StdInLocked) + *StdInLocked = FALSE; + return EFI_SUCCESS; +} + +EFI_STATUS EFIAPI +SetModeImpl( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS EFIAPI +LockStdInImpl( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ) +{ + return EFI_SUCCESS; +} + + +EFI_CONSOLE_CONTROL_PROTOCOL gConsoleController = +{ + GetModeImpl, + SetModeImpl, + LockStdInImpl +}; + +EFI_GUID gEfiConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; + +EFI_STATUS +EFIAPI +InitializeConsoleSim ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiConsoleControlProtocolGuid, + &gConsoleController, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/ConsoleControl.h b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/ConsoleControl.h new file mode 100644 index 00000000..8dabbb0e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/ConsoleControl.h @@ -0,0 +1,158 @@ +/* $Id: ConsoleControl.h $ */ +/** @file + * ConsoleControl.h + */ + +/* + * Copyright (C) 2009-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * 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, in version 3 of the + * License. + * + * 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, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +/* + * This code is based on: + * + * Copyright (c) 2004 - 2006, Intel Corporation + * All rights reserved. This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + * Module Name: + * + * ConsoleControl.h + * + * Abstract: + * + * Abstraction of a Text mode or GOP/UGA screen + */ + +#ifndef __CONSOLE_CONTROL_H__ +#define __CONSOLE_CONTROL_H__ + +#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ + { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} } + +typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; + + +typedef enum { + EfiConsoleControlScreenText, + EfiConsoleControlScreenGraphics, + EfiConsoleControlScreenMaxValue +} EFI_CONSOLE_CONTROL_SCREEN_MODE; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *GopUgaExists, OPTIONAL + OUT BOOLEAN *StdInLocked OPTIONAL + ) +/*++ + + Routine Description: + Return the current video mode information. Also returns info about existence + of Graphics Output devices or UGA Draw devices in system, and if the Std In + device is locked. All the arguments are optional and only returned if a non + NULL pointer is passed in. + + Arguments: + This - Protocol instance pointer. + Mode - Are we in text of graphics mode. + GopUgaExists - TRUE if Console Splitter has found a GOP or UGA device + StdInLocked - TRUE if StdIn device is keyboard locked + + Returns: + EFI_SUCCESS - Mode information returned. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ) +/*++ + + Routine Description: + Set the current mode to either text or graphics. Graphics is + for Quiet Boot. + + Arguments: + This - Protocol instance pointer. + Mode - Mode to set the + + Returns: + EFI_SUCCESS - Mode information returned. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ) +/*++ + + Routine Description: + Lock Std In devices until Password is typed. + + Arguments: + This - Protocol instance pointer. + Password - Password needed to unlock screen. NULL means unlock keyboard + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_DEVICE_ERROR - Std In not locked + +--*/ +; + + + +struct _EFI_CONSOLE_CONTROL_PROTOCOL { + EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; +}; + +extern EFI_GUID gEfiConsoleControlProtocolGuid; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/Cpu.c b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/Cpu.c new file mode 100644 index 00000000..791475d3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/Cpu.c @@ -0,0 +1,146 @@ +/* $Id: Cpu.c $ */ +/** @file + * Cpu.c - VirtualBox CPU descriptors + */ + +/* + * Copyright (C) 2009-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * 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, in version 3 of the + * License. + * + * 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, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiLib.h> +#include <Library/HiiLib.h> +#include <Library/BaseLib.h> + +#include <Protocol/Cpu.h> + +#include "DataHub.h" + +#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100 + +EFI_GUID gEfiAppleMagicHubGuid = { + 0x64517cc8, 0x6561, 0x4051, {0xb0, 0x3c, 0x59, 0x64, 0xb6, 0x0f, 0x4c, 0x7a } +}; + +EFI_GUID gEfiProcessorSubClassGuid = { + 0x26fdeb7e, 0xb8af, 0x4ccf, { 0xaa, 0x97, 0x02, 0x63, 0x3c, 0xe4, 0x8c, 0xa7 } +}; + +#pragma pack(1) +typedef struct { + UINT8 Pad0[0x10]; /* 0x48 */ + UINT32 NameLen; /* 0x58 , in bytes */ + UINT32 ValLen; /* 0x5c */ + UINT8 Data[1]; /* 0x60 Name Value */ +} MAGIC_HUB_DATA; +#pragma pack() + +UINT32 +CopyRecord(MAGIC_HUB_DATA* Rec, const CHAR16* Name, VOID* Val, UINT32 ValLen) +{ + Rec->NameLen = (UINT32)StrLen(Name) * sizeof(CHAR16); + Rec->ValLen = ValLen; + CopyMem(Rec->Data, Name, Rec->NameLen); + CopyMem(Rec->Data + Rec->NameLen, Val, ValLen); + + return 0x10 + 4 + 4 + Rec->NameLen + Rec->ValLen; +} + +EFI_STATUS EFIAPI +LogData(EFI_DATA_HUB_PROTOCOL *DataHub, + MAGIC_HUB_DATA *MagicData, + CHAR16 *Name, + VOID *Data, + UINT32 DataSize) +{ + UINT32 RecordSize; + EFI_STATUS Status; + + RecordSize = CopyRecord(MagicData, Name, Data, DataSize); + Status = DataHub->LogData ( + DataHub, + &gEfiProcessorSubClassGuid, /* DataRecordGuid */ + &gEfiAppleMagicHubGuid, /* ProducerName */ + EFI_DATA_CLASS_DATA, + MagicData, + RecordSize + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +EFI_STATUS EFIAPI +CpuUpdateDataHub(EFI_BOOT_SERVICES * bs, + UINT64 FSBFrequency, + UINT64 TSCFrequency, + UINT64 CPUFrequency) +{ + EFI_STATUS Status; + EFI_DATA_HUB_PROTOCOL *DataHub; + MAGIC_HUB_DATA *MagicData; + UINT32 Supported = 1; + // + // Locate DataHub protocol. + // + Status = bs->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID**)&DataHub); + if (EFI_ERROR (Status)) { + return Status; + } + + MagicData = (MAGIC_HUB_DATA*)AllocatePool (0x200); + if (MagicData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Log data in format some OSes like + LogData(DataHub, MagicData, L"FSBFrequency", &FSBFrequency, sizeof(FSBFrequency)); + // do that twice, as last variable read not really accounted for + LogData(DataHub, MagicData, L"FSBFrequency", &FSBFrequency, sizeof(FSBFrequency)); + LogData(DataHub, MagicData, L"TSCFrequency", &TSCFrequency, sizeof(TSCFrequency)); + LogData(DataHub, MagicData, L"CPUFrequency", &CPUFrequency, sizeof(CPUFrequency)); + + // The following is required for OS X to construct a SATA boot path. UEFI 2.0 (published + // in Jan 2006, same time as the first Intel Macs) did not standardize SATA device paths; + // if DevicePathsSupported is not set, OS X will create ATA boot paths which will fail + // to boot + LogData(DataHub, MagicData, L"DevicePathsSupported", &Supported, sizeof(Supported)); + + FreePool (MagicData); + + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/DataHub.c b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/DataHub.c new file mode 100644 index 00000000..8268289d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/DataHub.c @@ -0,0 +1,215 @@ +/* $Id: DataHub.c $ */ +/** @file + * Console.c - VirtualBox Console control emulation + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * 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, in version 3 of the + * License. + * + * 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, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ +#include <Uefi.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiLib.h> + +#include "VBoxPkg.h" +#include "DataHub.h" + +/** + * Data hub logged entry. + */ +typedef struct +{ + /** List node for the linked list - must be at the top. */ + LIST_ENTRY NdEntries; + /** The record header. */ + EFI_DATA_RECORD_HEADER RecHdr; + /** The data logged, variable in size. */ + UINT8 abData[1]; +} EFI_DATA_HUB_ENTRY; + +/** + * DataHub instance data. + */ +typedef struct +{ + /** Monotonic increasing counter. */ + UINT64 cMonotonicCnt; + /** Linked list holding the logged entries. */ + LIST_ENTRY LstEntries; + /** The lock protecting the key members above. */ + EFI_LOCK Lck; +} EFI_DATA_HUB_INSTANCE; + + +EFI_DATA_HUB_INSTANCE mDataHubInstance; + +EFI_STATUS EFIAPI +DataHubLogData ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_GUID *DataRecordGuid, + IN EFI_GUID *ProducerName, + IN UINT64 DataRecordClass, + IN VOID *RawData, + IN UINT32 RawDataSize + ) +{ + UINT32 cbEntry = sizeof(EFI_DATA_HUB_ENTRY) + RawDataSize; + EFI_DATA_HUB_ENTRY *pEntry = AllocatePool(cbEntry); + + if (pEntry == NULL) + return EFI_OUT_OF_RESOURCES; + + pEntry->RecHdr.Version = EFI_DATA_RECORD_HEADER_VERSION; + pEntry->RecHdr.HeaderSize = sizeof(EFI_DATA_RECORD_HEADER); + pEntry->RecHdr.RecordSize = RawDataSize + sizeof(EFI_DATA_RECORD_HEADER); + CopyMem(&pEntry->RecHdr.DataRecordGuid, DataRecordGuid, sizeof(pEntry->RecHdr.DataRecordGuid)); + CopyMem(&pEntry->RecHdr.ProducerName, ProducerName, sizeof(pEntry->RecHdr.ProducerName)); + pEntry->RecHdr.DataRecordClass = DataRecordClass; + SetMem(&pEntry->RecHdr.LogTime, sizeof(pEntry->RecHdr.LogTime), 0); + pEntry->RecHdr.LogMonotonicCount = ++mDataHubInstance.cMonotonicCnt; /* Ensure non zero value in record. */ + CopyMem(&pEntry->abData[0], RawData, RawDataSize); + + EfiAcquireLock(&mDataHubInstance.Lck); + InsertTailList(&mDataHubInstance.LstEntries, &pEntry->NdEntries); + EfiReleaseLock(&mDataHubInstance.Lck); + return EFI_SUCCESS; +} + + +EFI_STATUS EFIAPI +DataHubGetNextDataRecord ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN OUT UINT64 *MonotonicCount, + IN EFI_EVENT *FilterDriver OPTIONAL, + OUT EFI_DATA_RECORD_HEADER **Record + ) +{ + EFI_DATA_HUB_ENTRY *pEntry = NULL; + + EfiAcquireLock(&mDataHubInstance.Lck); + if (*MonotonicCount == 0) + { + if (!IsListEmpty(&mDataHubInstance.LstEntries)) + pEntry = (EFI_DATA_HUB_ENTRY *)GetFirstNode(&mDataHubInstance.LstEntries); + } + else + { + /* Ignore filter driver handling for now. */ + LIST_ENTRY *pHead = &mDataHubInstance.LstEntries; + LIST_ENTRY *pIt = NULL; + + for (pIt = GetFirstNode(pHead); pIt != pHead; pIt = GetNextNode(pHead, pIt)) + { + EFI_DATA_HUB_ENTRY *pTmp = (EFI_DATA_HUB_ENTRY *)pIt; + if (pTmp->RecHdr.LogMonotonicCount == *MonotonicCount) + { + pEntry = pTmp; + break; + } + } + } + EfiReleaseLock(&mDataHubInstance.Lck); + + if (pEntry == NULL) + return EFI_NOT_FOUND; + + *Record = &pEntry->RecHdr; + + /* Look for the next entry and set MonotonicCount accordingly. */ + if (!IsNodeAtEnd(&mDataHubInstance.LstEntries, &pEntry->NdEntries)) + { + pEntry = (EFI_DATA_HUB_ENTRY *)GetNextNode(&mDataHubInstance.LstEntries, &pEntry->NdEntries); + *MonotonicCount = pEntry->RecHdr.LogMonotonicCount; + } + else + *MonotonicCount = 0; + + return EFI_SUCCESS; +} + + +EFI_STATUS EFIAPI +DataHubRegisterDataFilterDriver ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_EVENT FilterEvent, + IN EFI_TPL FilterTpl, + IN UINT64 FilterClass, + IN EFI_GUID *FilterDataRecordGui OPTIONAL + ) +{ + return EFI_SUCCESS; +} + + +EFI_STATUS EFIAPI +DataHubUnregisterDataFilterDriver ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_EVENT FilterEvent + ) +{ + return EFI_SUCCESS; +} + + +EFI_DATA_HUB_PROTOCOL gDataHub = +{ + DataHubLogData, + DataHubGetNextDataRecord, + DataHubRegisterDataFilterDriver, + DataHubUnregisterDataFilterDriver +}; + +EFI_GUID gEfiDataHubProtocolGuid = EFI_DATA_HUB_PROTOCOL_GUID; + +EFI_STATUS +EFIAPI +InitializeDataHub ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + + InitializeListHead(&mDataHubInstance.LstEntries); + EfiInitializeLock (&mDataHubInstance.Lck, TPL_NOTIFY); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDataHubProtocolGuid, + &gDataHub, + NULL); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/DataHub.h b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/DataHub.h new file mode 100644 index 00000000..976de54d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/DataHub.h @@ -0,0 +1,178 @@ +/* $Id: DataHub.h $ */ +/** @file + * DataHub.h + */ + +/* + * Copyright (C) 2019-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * 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, in version 3 of the + * License. + * + * 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, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#ifndef __DATA_HUB_H__ +#define __DATA_HUB_H__ + +#define EFI_DATA_HUB_PROTOCOL_GUID \ + { 0xae80d021, 0x618e, 0x11d4, {0xbc, 0xd7, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81} } + +typedef struct _EFI_DATA_HUB_PROTOCOL EFI_DATA_HUB_PROTOCOL; + + +#define EFI_DATA_RECORD_HEADER_VERSION 0x0100 + +#define EFI_DATA_CLASS_DEBUG 0x1ULL +#define EFI_DATA_CLASS_ERROR 0x2ULL +#define EFI_DATA_CLASS_DATA 0x4ULL +#define EFI_DATA_CLASS_PROGRESS_CODE 0x8ULL + +typedef struct { + UINT16 Version; + UINT16 HeaderSize; + UINT32 RecordSize; + EFI_GUID DataRecordGuid; + EFI_GUID ProducerName; + UINT64 DataRecordClass; + EFI_TIME LogTime; + UINT64 LogMonotonicCount; +} EFI_DATA_RECORD_HEADER; + +typedef +EFI_STATUS +(EFIAPI *EFI_DATA_HUB_LOG_DATA) ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_GUID *DataRecordGuid, + IN EFI_GUID *ProducerName, + IN UINT64 DataRecordClass, + IN VOID *RawData, + IN UINT32 RawDataSize + ) +/*++ + + Routine Description: + Logs a data record to the system event log. + + Arguments: + This - Protocol instance pointer. + + + Returns: + EFI_SUCCESS - Data was logged. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_DATA_HUB_GET_NEXT_DATA_RECORD) ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN OUT UINT64 *MonotonicCount, + IN EFI_EVENT *FilterDriver OPTIONAL, + OUT EFI_DATA_RECORD_HEADER **Record + ) +/*++ + + Routine Description: + Allows the system data log to be searched. + + Arguments: + This - Protocol instance pointer. + + + Returns: + EFI_SUCCESS - Data was logged. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_DATA_HUB_REGISTER_DATA_FILTER_DRIVER) ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_EVENT FilterEvent, + IN EFI_TPL FilterTpl, + IN UINT64 FilterClass, + IN EFI_GUID *FilterDataRecordGui OPTIONAL + ) +/*++ + + Routine Description: + Registers an event to be signaled evey time a data record is logged in the system. + + Arguments: + This - Protocol instance pointer. + + + Returns: + EFI_SUCCESS - The filter driver event was registered. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_DATA_HUB_UNREGISTER_DATA_FILTER_DRIVER) ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_EVENT FilterEvent + ) +/*++ + + Routine Description: + Stops a filter driver from being notified when data records are logged. + + Arguments: + This - Protocol instance pointer. + + + Returns: + EFI_SUCCESS - The filter driver represented by FilterEvent was shut off. + +--*/ +; + + +struct _EFI_DATA_HUB_PROTOCOL { + EFI_DATA_HUB_LOG_DATA LogData; + EFI_DATA_HUB_GET_NEXT_DATA_RECORD GetNextDataRecord; + EFI_DATA_HUB_REGISTER_DATA_FILTER_DRIVER RegisterFilterDriver; + EFI_DATA_HUB_UNREGISTER_DATA_FILTER_DRIVER UnregisterFilterDriver; +}; + +extern EFI_GUID gEfiDataHubProtocolGuid; + + +EFI_STATUS +EFIAPI +InitializeDataHub ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/VBoxAppleSim.c b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/VBoxAppleSim.c new file mode 100644 index 00000000..4d2b4ef4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/VBoxAppleSim.c @@ -0,0 +1,352 @@ +/* $Id: VBoxAppleSim.c $ */ +/** @file + * VBoxAppleSim.c - VirtualBox Apple Firmware simulation support + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * 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, in version 3 of the + * License. + * + * 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, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/PrintLib.h> + +#include <Protocol/DevicePathToText.h> + +#include <IndustryStandard/Acpi10.h> +#include <IndustryStandard/Acpi20.h> +#include <IndustryStandard/SmBios.h> + +#include <Guid/SmBios.h> +#include <Guid/Acpi.h> +#include <Guid/Mps.h> + +#include "DataHub.h" +#include "VBoxPkg.h" +#include "DevEFI.h" +#include "iprt/asm.h" + + +/* + * External functions + */ +EFI_STATUS EFIAPI +CpuUpdateDataHub(EFI_BOOT_SERVICES * bs, + UINT64 FSBFrequency, + UINT64 TSCFrequency, + UINT64 CPUFrequency); + +EFI_STATUS EFIAPI +InitializeConsoleSim (IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable); + + +/* + * Internal Functions + */ +static UINT32 +GetVmVariable(UINT32 Variable, CHAR8 *pbBuf, UINT32 cbBuf) +{ + UINT32 cbVar, offBuf; + + ASMOutU32(EFI_INFO_PORT, Variable); + cbVar = ASMInU32(EFI_INFO_PORT); + + for (offBuf = 0; offBuf < cbVar && offBuf < cbBuf; offBuf++) + pbBuf[offBuf] = ASMInU8(EFI_INFO_PORT); + + return cbVar; +} + +/* + * GUIDs + */ +/** The EFI variable GUID for the 'FirmwareFeatures' and friends. + * Also known as AppleFirmwareVariableGuid in other sources. */ +EFI_GUID gEfiAppleNvramGuid = { + 0x4D1EDE05, 0x38C7, 0x4A6A, {0x9C, 0xC6, 0x4B, 0xCC, 0xA8, 0xB3, 0x8C, 0x14 } +}; + +/** The EFI variable GUID for the 'boot-args' variable and others. + * Also known as AppleNVRAMVariableGuid in other sources. */ +EFI_GUID gEfiAppleBootGuid = { + 0x7C436110, 0xAB2A, 0x4BBB, {0xA8, 0x80, 0xFE, 0x41, 0x99, 0x5C, 0x9F, 0x82} +}; + + +/* + * Device Properoty protocol implementation hack. + */ + +/** gEfiAppleVarGuid is aka AppleDevicePropertyProtocolGuid in other sources. */ +EFI_GUID gEfiAppleVarGuid = { + 0x91BD12FE, 0xF6C3, 0x44FB, {0xA5, 0xB7, 0x51, 0x22, 0xAB, 0x30, 0x3A, 0xE0} +}; + +/** APPLE_GETVAR_PROTOCOL is aka APPLE_DEVICE_PROPERTY_PROTOCOL in other sources. */ +typedef struct _APPLE_GETVAR_PROTOCOL APPLE_GETVAR_PROTOCOL; + +struct _APPLE_GETVAR_PROTOCOL +{ + /** Magic value or some version thingy. boot.efi doesn't check this, I think. */ + UINT64 u64Magic; + + EFI_STATUS (EFIAPI *pfnUnknown0)(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2, + IN VOID *pvArg3, IN VOID *pvArg4); + EFI_STATUS (EFIAPI *pfnUnknown1)(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2, + IN VOID *pvArg3, IN VOID *pvArg4); + EFI_STATUS (EFIAPI *pfnUnknown2)(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2); + + EFI_STATUS (EFIAPI *pfnGetDevProps)(IN APPLE_GETVAR_PROTOCOL *This, IN CHAR8 *pbBuf, IN OUT UINT32 *pcbBuf); +}; +/** The value of APPLE_GETVAR_PROTOCOL::u64Magic. */ +#define APPLE_GETVAR_PROTOCOL_MAGIC 0x10000 + +EFI_STATUS EFIAPI +AppleGetVar_Unknown0(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2, + IN VOID *pvArg3, IN VOID *pvArg4) +{ + CHAR8 szMsg[128]; + AsciiSPrint(szMsg, sizeof(szMsg), "AppleGetVar_Unknown0: pvArg1=%p pvArg2=%p pvArg3=%p pvArg4=%p", + pvArg1, pvArg2, pvArg3, pvArg4); + DebugAssert(__FILE__, __LINE__, szMsg); + return EFI_UNSUPPORTED; +} + +EFI_STATUS EFIAPI +AppleGetVar_Unknown1(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2, + IN VOID *pvArg3, IN VOID *pvArg4) +{ + CHAR8 szMsg[128]; + AsciiSPrint(szMsg, sizeof(szMsg), "AppleGetVar_Unknown1: pvArg1=%p pvArg2=%p pvArg3=%p pvArg4=%p", + pvArg1, pvArg2, pvArg3, pvArg4); + DebugAssert(__FILE__, __LINE__, szMsg); + return EFI_UNSUPPORTED; +} + +EFI_STATUS EFIAPI +AppleGetVar_Unknown2(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2) +{ + CHAR8 szMsg[80]; + AsciiSPrint(szMsg, sizeof(szMsg), "AppleGetVar_Unknown2: pvArg1=%p pvArg2=%p", pvArg1, pvArg2); + DebugAssert(__FILE__, __LINE__, szMsg); + return EFI_UNSUPPORTED; +} + + +/** + * This method obtains the 'device-properties' that get exposed by + * AppleEFIFirmware and parsed by AppleACPIPlatform. + * + * Check out the data in the IORegisteryExplorer, the device-properties property + * under IODeviceTree:/efi. + * + * @retval EFI_SUCCESS, check *pcbBuf or the number of bytes actually returned. + * @retval EFI_BUFFER_TOO_SMALL, check *pcbBuf for the necessary buffer size. + * @param pThis Not used. + * @param pbBuf The output buffer. + * @param pcbBuf On input, the varible pointed to contains the size of the + * buffer. The size is generally 4KB from what we've observed. + * On output, it contains the amount of data available, this + * is always set. + */ +EFI_STATUS EFIAPI +AppleGetVar_GetDeviceProps(IN APPLE_GETVAR_PROTOCOL *pThis, OUT CHAR8 *pbBuf, IN OUT UINT32 *pcbBuf) +{ + UINT32 cbBuf = *pcbBuf; + UINT32 cbActual; + + cbActual = GetVmVariable(EFI_INFO_INDEX_DEVICE_PROPS, pbBuf, cbBuf); + *pcbBuf = cbActual; + + if (cbActual > cbBuf) + return EFI_BUFFER_TOO_SMALL; + + return EFI_SUCCESS; +} + +APPLE_GETVAR_PROTOCOL gPrivateVarHandler = +{ + /* Magic = */ APPLE_GETVAR_PROTOCOL_MAGIC, + AppleGetVar_Unknown0, + AppleGetVar_Unknown1, + AppleGetVar_Unknown2, + AppleGetVar_GetDeviceProps +}; + + +/* + * Unknown Protocol #1. + */ + +/** This seems to be related to graphics/display... */ +EFI_GUID gEfiUnknown1ProtocolGuid = +{ + 0xDD8E06AC, 0x00E2, 0x49A9, {0x88, 0x8F, 0xFA, 0x46, 0xDE, 0xD4, 0x0A, 0x52} +}; + +EFI_STATUS EFIAPI +UnknownHandlerImpl() +{ +#ifdef DEBUG + ASSERT(0); +#endif + Print(L"Unknown called\n"); + return EFI_SUCCESS; +} + +/* array of pointers to function */ +EFI_STATUS (EFIAPI *gUnknownProtoHandler[])() = +{ + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl, + UnknownHandlerImpl +}; + +EFI_STATUS EFIAPI +SetProperVariables(IN EFI_HANDLE ImageHandle, EFI_RUNTIME_SERVICES * rs) +{ + EFI_STATUS rc; + UINT32 vBackgroundClear = 0x00000000; + UINT32 vFwFeatures = 0x80000015; + UINT32 vFwFeaturesMask = 0x800003ff; + + // -legacy acpi=0xffffffff acpi_debug=0xfffffff panic_io_port=0xef11 io=0xfffffffe trace=4096 io=0xffffffef -v serial=2 serialbaud=9600 + // 0x10 makes kdb default, thus 0x15e for kdb, 0x14e for gdb + // usb=0x800 is required to work around default behavior of the Apple xHCI driver which rejects high-speed + // USB devices and tries to force them to EHCI when running on the Intel Panther Point chipset. + + //static const CHAR8 vBootArgs[] = "debug=0x15e keepsyms=1 acpi=0xffffffff acpi_debug=0xff acpi_level=7 -v -x32 -s"; // or just "debug=0x8 -legacy" + // 0x14e for serial output + //static const CHAR8 vDefBootArgs[] = "debug=0x146 usb=0x800 keepsyms=1 -v -serial=0x1"; + static const CHAR8 vDefBootArgs[] = "usb=0x800 keepsyms=1 -v -serial=0x1"; + CHAR8 vBootArgs[256]; + UINT32 BootArgsLen; + + BootArgsLen = GetVmVariable(EFI_INFO_INDEX_BOOT_ARGS, vBootArgs, sizeof vBootArgs); + if (BootArgsLen <= 1) + { + BootArgsLen = sizeof vDefBootArgs; + CopyMem(vBootArgs, vDefBootArgs, BootArgsLen); + } + rc = rs->SetVariable(L"BackgroundClear", + &gEfiAppleNvramGuid, + /* EFI_VARIABLE_NON_VOLATILE | */ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(vBackgroundClear), &vBackgroundClear); + ASSERT_EFI_ERROR (rc); + + rc = rs->SetVariable(L"FirmwareFeatures", + &gEfiAppleNvramGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(vFwFeatures), &vFwFeatures); + ASSERT_EFI_ERROR (rc); + + rc = rs->SetVariable(L"FirmwareFeaturesMask", + &gEfiAppleNvramGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(vFwFeaturesMask), &vFwFeaturesMask); + ASSERT_EFI_ERROR (rc); + + rc = rs->SetVariable(L"boot-args", + &gEfiAppleBootGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + BootArgsLen, &vBootArgs); + ASSERT_EFI_ERROR (rc); + + return EFI_SUCCESS; +} + +/** + * VBoxInitAppleSim entry point. + * + * @returns EFI status code. + * + * @param ImageHandle The image handle. + * @param SystemTable The system table pointer. + */ +EFI_STATUS EFIAPI +VBoxInitAppleSim(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS rc; + UINT64 FSBFrequency; + UINT64 TSCFrequency; + UINT64 CPUFrequency; + + rc = SetProperVariables(ImageHandle, SystemTable->RuntimeServices); + ASSERT_EFI_ERROR(rc); + + rc = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gEfiAppleVarGuid, &gPrivateVarHandler, NULL); + ASSERT_EFI_ERROR(rc); + + rc = InitializeDataHub(ImageHandle, SystemTable); + ASSERT_EFI_ERROR(rc); + + GetVmVariable(EFI_INFO_INDEX_FSB_FREQUENCY, (CHAR8 *)&FSBFrequency, sizeof(FSBFrequency)); + GetVmVariable(EFI_INFO_INDEX_TSC_FREQUENCY, (CHAR8 *)&TSCFrequency, sizeof(TSCFrequency)); + GetVmVariable(EFI_INFO_INDEX_CPU_FREQUENCY, (CHAR8 *)&CPUFrequency, sizeof(CPUFrequency)); + + rc = CpuUpdateDataHub(gBS, FSBFrequency, TSCFrequency, CPUFrequency); + ASSERT_EFI_ERROR(rc); + + rc = InitializeConsoleSim(ImageHandle, SystemTable); + ASSERT_EFI_ERROR(rc); + + rc = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gEfiUnknown1ProtocolGuid, gUnknownProtoHandler, NULL); + ASSERT_EFI_ERROR(rc); + + return EFI_SUCCESS; +} + +EFI_STATUS EFIAPI +VBoxDeinitAppleSim(IN EFI_HANDLE ImageHandle) +{ + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/VBoxAppleSim.inf b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/VBoxAppleSim.inf new file mode 100644 index 00000000..48d77335 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/VBoxAppleSim.inf @@ -0,0 +1,78 @@ +# $Id: VBoxAppleSim.inf $ +## @file +# VBoxAppleSim - VBox Apple interfaces simulation support. +# + +# +# Copyright (C) 2010-2022 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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, see <https://www.gnu.org/licenses>. +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VBoxAppleSim + FILE_GUID = 17795471-FD9A-46BE-8806-AE787BA73CD4 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + ENTRY_POINT = VBoxInitAppleSim + UNLOAD_IMAGE = VBoxDeinitAppleSim + +[Sources.common] + VBoxAppleSim.c + Cpu.c + Console.c + DataHub.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + VBoxPkg/VBoxPkg.dec + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + PcdLib + DevicePathLib + +[Protocols] + gEfiDevicePathToTextProtocolGuid + +[BuildOptions.common] + + GCC:*_*_*_CC_FLAGS = + INTEL:*_*_*_CC_FLAGS = + MSFT:*_*_*_CC_FLAGS = |