VirtualBox

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

Last change on this file since 53270 was 53270, checked in by vboxsync, 10 years ago

EFI: Work around Apple xHCI Panther Point HS handoff behavior.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette