VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxAppleSim/VBoxAppleSim.c

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.8 KB
Line 
1/* $Id: VBoxAppleSim.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxAppleSim.c - VirtualBox Apple Firmware simulation support
4 */
5
6/*
7 * Copyright (C) 2010-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <Library/BaseMemoryLib.h>
42#include <Library/DebugLib.h>
43#include <Library/UefiBootServicesTableLib.h>
44#include <Library/UefiLib.h>
45#include <Library/PrintLib.h>
46
47#include <Protocol/DevicePathToText.h>
48
49#include <IndustryStandard/Acpi10.h>
50#include <IndustryStandard/Acpi20.h>
51#include <IndustryStandard/SmBios.h>
52
53#include <Guid/SmBios.h>
54#include <Guid/Acpi.h>
55#include <Guid/Mps.h>
56
57#include "DataHub.h"
58#include "VBoxPkg.h"
59#include "DevEFI.h"
60#include "iprt/asm.h"
61
62
63/*
64 * External functions
65 */
66EFI_STATUS EFIAPI
67CpuUpdateDataHub(EFI_BOOT_SERVICES * bs,
68 UINT64 FSBFrequency,
69 UINT64 TSCFrequency,
70 UINT64 CPUFrequency);
71
72EFI_STATUS EFIAPI
73InitializeConsoleSim (IN EFI_HANDLE ImageHandle,
74 IN EFI_SYSTEM_TABLE *SystemTable);
75
76
77/*
78 * Internal Functions
79 */
80static UINT32
81GetVmVariable(UINT32 Variable, CHAR8 *pbBuf, UINT32 cbBuf)
82{
83 UINT32 cbVar, offBuf;
84
85 ASMOutU32(EFI_INFO_PORT, Variable);
86 cbVar = ASMInU32(EFI_INFO_PORT);
87
88 for (offBuf = 0; offBuf < cbVar && offBuf < cbBuf; offBuf++)
89 pbBuf[offBuf] = ASMInU8(EFI_INFO_PORT);
90
91 return cbVar;
92}
93
94/*
95 * GUIDs
96 */
97/** The EFI variable GUID for the 'FirmwareFeatures' and friends.
98 * Also known as AppleFirmwareVariableGuid in other sources. */
99EFI_GUID gEfiAppleNvramGuid = {
100 0x4D1EDE05, 0x38C7, 0x4A6A, {0x9C, 0xC6, 0x4B, 0xCC, 0xA8, 0xB3, 0x8C, 0x14 }
101};
102
103/** The EFI variable GUID for the 'boot-args' variable and others.
104 * Also known as AppleNVRAMVariableGuid in other sources. */
105EFI_GUID gEfiAppleBootGuid = {
106 0x7C436110, 0xAB2A, 0x4BBB, {0xA8, 0x80, 0xFE, 0x41, 0x99, 0x5C, 0x9F, 0x82}
107};
108
109
110/*
111 * Device Properoty protocol implementation hack.
112 */
113
114/** gEfiAppleVarGuid is aka AppleDevicePropertyProtocolGuid in other sources. */
115EFI_GUID gEfiAppleVarGuid = {
116 0x91BD12FE, 0xF6C3, 0x44FB, {0xA5, 0xB7, 0x51, 0x22, 0xAB, 0x30, 0x3A, 0xE0}
117};
118
119/** APPLE_GETVAR_PROTOCOL is aka APPLE_DEVICE_PROPERTY_PROTOCOL in other sources. */
120typedef struct _APPLE_GETVAR_PROTOCOL APPLE_GETVAR_PROTOCOL;
121
122struct _APPLE_GETVAR_PROTOCOL
123{
124 /** Magic value or some version thingy. boot.efi doesn't check this, I think. */
125 UINT64 u64Magic;
126
127 EFI_STATUS (EFIAPI *pfnUnknown0)(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2,
128 IN VOID *pvArg3, IN VOID *pvArg4);
129 EFI_STATUS (EFIAPI *pfnUnknown1)(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2,
130 IN VOID *pvArg3, IN VOID *pvArg4);
131 EFI_STATUS (EFIAPI *pfnUnknown2)(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2);
132
133 EFI_STATUS (EFIAPI *pfnGetDevProps)(IN APPLE_GETVAR_PROTOCOL *This, IN CHAR8 *pbBuf, IN OUT UINT32 *pcbBuf);
134};
135/** The value of APPLE_GETVAR_PROTOCOL::u64Magic. */
136#define APPLE_GETVAR_PROTOCOL_MAGIC 0x10000
137
138EFI_STATUS EFIAPI
139AppleGetVar_Unknown0(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2,
140 IN VOID *pvArg3, IN VOID *pvArg4)
141{
142 CHAR8 szMsg[128];
143 AsciiSPrint(szMsg, sizeof(szMsg), "AppleGetVar_Unknown0: pvArg1=%p pvArg2=%p pvArg3=%p pvArg4=%p",
144 pvArg1, pvArg2, pvArg3, pvArg4);
145 DebugAssert(__FILE__, __LINE__, szMsg);
146 return EFI_UNSUPPORTED;
147}
148
149EFI_STATUS EFIAPI
150AppleGetVar_Unknown1(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2,
151 IN VOID *pvArg3, IN VOID *pvArg4)
152{
153 CHAR8 szMsg[128];
154 AsciiSPrint(szMsg, sizeof(szMsg), "AppleGetVar_Unknown1: pvArg1=%p pvArg2=%p pvArg3=%p pvArg4=%p",
155 pvArg1, pvArg2, pvArg3, pvArg4);
156 DebugAssert(__FILE__, __LINE__, szMsg);
157 return EFI_UNSUPPORTED;
158}
159
160EFI_STATUS EFIAPI
161AppleGetVar_Unknown2(IN APPLE_GETVAR_PROTOCOL *This, IN VOID *pvArg1, IN VOID *pvArg2)
162{
163 CHAR8 szMsg[80];
164 AsciiSPrint(szMsg, sizeof(szMsg), "AppleGetVar_Unknown2: pvArg1=%p pvArg2=%p", pvArg1, pvArg2);
165 DebugAssert(__FILE__, __LINE__, szMsg);
166 return EFI_UNSUPPORTED;
167}
168
169
170/**
171 * This method obtains the 'device-properties' that get exposed by
172 * AppleEFIFirmware and parsed by AppleACPIPlatform.
173 *
174 * Check out the data in the IORegisteryExplorer, the device-properties property
175 * under IODeviceTree:/efi.
176 *
177 * @retval EFI_SUCCESS, check *pcbBuf or the number of bytes actually returned.
178 * @retval EFI_BUFFER_TOO_SMALL, check *pcbBuf for the necessary buffer size.
179 * @param pThis Not used.
180 * @param pbBuf The output buffer.
181 * @param pcbBuf On input, the varible pointed to contains the size of the
182 * buffer. The size is generally 4KB from what we've observed.
183 * On output, it contains the amount of data available, this
184 * is always set.
185 */
186EFI_STATUS EFIAPI
187AppleGetVar_GetDeviceProps(IN APPLE_GETVAR_PROTOCOL *pThis, OUT CHAR8 *pbBuf, IN OUT UINT32 *pcbBuf)
188{
189 UINT32 cbBuf = *pcbBuf;
190 UINT32 cbActual;
191
192 cbActual = GetVmVariable(EFI_INFO_INDEX_DEVICE_PROPS, pbBuf, cbBuf);
193 *pcbBuf = cbActual;
194
195 if (cbActual > cbBuf)
196 return EFI_BUFFER_TOO_SMALL;
197
198 return EFI_SUCCESS;
199}
200
201APPLE_GETVAR_PROTOCOL gPrivateVarHandler =
202{
203 /* Magic = */ APPLE_GETVAR_PROTOCOL_MAGIC,
204 AppleGetVar_Unknown0,
205 AppleGetVar_Unknown1,
206 AppleGetVar_Unknown2,
207 AppleGetVar_GetDeviceProps
208};
209
210
211/*
212 * Unknown Protocol #1.
213 */
214
215/** This seems to be related to graphics/display... */
216EFI_GUID gEfiUnknown1ProtocolGuid =
217{
218 0xDD8E06AC, 0x00E2, 0x49A9, {0x88, 0x8F, 0xFA, 0x46, 0xDE, 0xD4, 0x0A, 0x52}
219};
220
221EFI_STATUS EFIAPI
222UnknownHandlerImpl()
223{
224#ifdef DEBUG
225 ASSERT(0);
226#endif
227 Print(L"Unknown called\n");
228 return EFI_SUCCESS;
229}
230
231/* array of pointers to function */
232EFI_STATUS (EFIAPI *gUnknownProtoHandler[])() =
233{
234 UnknownHandlerImpl,
235 UnknownHandlerImpl,
236 UnknownHandlerImpl,
237 UnknownHandlerImpl,
238 UnknownHandlerImpl,
239 UnknownHandlerImpl,
240 UnknownHandlerImpl,
241 UnknownHandlerImpl,
242 UnknownHandlerImpl,
243 UnknownHandlerImpl,
244 UnknownHandlerImpl,
245 UnknownHandlerImpl,
246 UnknownHandlerImpl,
247 UnknownHandlerImpl,
248 UnknownHandlerImpl,
249 UnknownHandlerImpl,
250 UnknownHandlerImpl,
251 UnknownHandlerImpl
252};
253
254EFI_STATUS EFIAPI
255SetProperVariables(IN EFI_HANDLE ImageHandle, EFI_RUNTIME_SERVICES * rs)
256{
257 EFI_STATUS rc;
258 UINT32 vBackgroundClear = 0x00000000;
259 UINT32 vFwFeatures = 0x80000015;
260 UINT32 vFwFeaturesMask = 0x800003ff;
261
262 // -legacy acpi=0xffffffff acpi_debug=0xfffffff panic_io_port=0xef11 io=0xfffffffe trace=4096 io=0xffffffef -v serial=2 serialbaud=9600
263 // 0x10 makes kdb default, thus 0x15e for kdb, 0x14e for gdb
264 // usb=0x800 is required to work around default behavior of the Apple xHCI driver which rejects high-speed
265 // USB devices and tries to force them to EHCI when running on the Intel Panther Point chipset.
266
267 //static const CHAR8 vBootArgs[] = "debug=0x15e keepsyms=1 acpi=0xffffffff acpi_debug=0xff acpi_level=7 -v -x32 -s"; // or just "debug=0x8 -legacy"
268 // 0x14e for serial output
269 //static const CHAR8 vDefBootArgs[] = "debug=0x146 usb=0x800 keepsyms=1 -v -serial=0x1";
270 static const CHAR8 vDefBootArgs[] = "usb=0x800 keepsyms=1 -v -serial=0x1";
271 CHAR8 vBootArgs[256];
272 UINT32 BootArgsLen;
273
274 BootArgsLen = GetVmVariable(EFI_INFO_INDEX_BOOT_ARGS, vBootArgs, sizeof vBootArgs);
275 if (BootArgsLen <= 1)
276 {
277 BootArgsLen = sizeof vDefBootArgs;
278 CopyMem(vBootArgs, vDefBootArgs, BootArgsLen);
279 }
280 rc = rs->SetVariable(L"BackgroundClear",
281 &gEfiAppleNvramGuid,
282 /* EFI_VARIABLE_NON_VOLATILE | */ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
283 sizeof(vBackgroundClear), &vBackgroundClear);
284 ASSERT_EFI_ERROR (rc);
285
286 rc = rs->SetVariable(L"FirmwareFeatures",
287 &gEfiAppleNvramGuid,
288 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
289 sizeof(vFwFeatures), &vFwFeatures);
290 ASSERT_EFI_ERROR (rc);
291
292 rc = rs->SetVariable(L"FirmwareFeaturesMask",
293 &gEfiAppleNvramGuid,
294 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
295 sizeof(vFwFeaturesMask), &vFwFeaturesMask);
296 ASSERT_EFI_ERROR (rc);
297
298 rc = rs->SetVariable(L"boot-args",
299 &gEfiAppleBootGuid,
300 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
301 BootArgsLen, &vBootArgs);
302 ASSERT_EFI_ERROR (rc);
303
304 return EFI_SUCCESS;
305}
306
307/**
308 * VBoxInitAppleSim entry point.
309 *
310 * @returns EFI status code.
311 *
312 * @param ImageHandle The image handle.
313 * @param SystemTable The system table pointer.
314 */
315EFI_STATUS EFIAPI
316VBoxInitAppleSim(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
317{
318 EFI_STATUS rc;
319 UINT64 FSBFrequency;
320 UINT64 TSCFrequency;
321 UINT64 CPUFrequency;
322
323 rc = SetProperVariables(ImageHandle, SystemTable->RuntimeServices);
324 ASSERT_EFI_ERROR(rc);
325
326 rc = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gEfiAppleVarGuid, &gPrivateVarHandler, NULL);
327 ASSERT_EFI_ERROR(rc);
328
329 rc = InitializeDataHub(ImageHandle, SystemTable);
330 ASSERT_EFI_ERROR(rc);
331
332 GetVmVariable(EFI_INFO_INDEX_FSB_FREQUENCY, (CHAR8 *)&FSBFrequency, sizeof(FSBFrequency));
333 GetVmVariable(EFI_INFO_INDEX_TSC_FREQUENCY, (CHAR8 *)&TSCFrequency, sizeof(TSCFrequency));
334 GetVmVariable(EFI_INFO_INDEX_CPU_FREQUENCY, (CHAR8 *)&CPUFrequency, sizeof(CPUFrequency));
335
336 rc = CpuUpdateDataHub(gBS, FSBFrequency, TSCFrequency, CPUFrequency);
337 ASSERT_EFI_ERROR(rc);
338
339 rc = InitializeConsoleSim(ImageHandle, SystemTable);
340 ASSERT_EFI_ERROR(rc);
341
342 rc = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gEfiUnknown1ProtocolGuid, gUnknownProtoHandler, NULL);
343 ASSERT_EFI_ERROR(rc);
344
345 return EFI_SUCCESS;
346}
347
348EFI_STATUS EFIAPI
349VBoxDeinitAppleSim(IN EFI_HANDLE ImageHandle)
350{
351 return EFI_SUCCESS;
352}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use