[edk2] [RFC PATCH 5/6] OvmfPkg: add Apple boot support

Gabriel L. Somlo posted 6 patches 7 years, 8 months ago
[edk2] [RFC PATCH 5/6] OvmfPkg: add Apple boot support
Posted by Gabriel L. Somlo 7 years, 8 months ago
Apple's boot.efi checks if the ConsoleControl protocol returns
EFI_SUCCESS in both GetMode and SetMode.

Apple uses a kernel extension to make parts of the DataHub protocol
available to the xnu kernel. The xnu kernel then checks for FSB
frequency and if it's not found fails with:

"tsc_init: EFI not supported!"
https://github.com/opensource-apple/xnu/blob/10.9/osfmk/i386/tsc.c

Also, some firmware settings are added to AppleSupport and written
to nvram.

Lastly, use (already present) HFS+ filesystem driver to locate, load,
and launch the Apple-provided OS X bootloader.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Reza Jelveh <reza.jelveh@tuhh.de>
Signed-off-by: Gabriel Somlo <gsomlo@gmail.com>
---
 OvmfPkg/Include/Library/AppleSupportLib.h          |  28 ++++
 OvmfPkg/Library/AppleSupportLib/AppleSupport.c     | 107 +++++++++++++++
 .../Library/AppleSupportLib/AppleSupportLib.inf    |  50 +++++++
 OvmfPkg/Library/AppleSupportLib/Bds.c              | 151 +++++++++++++++++++++
 OvmfPkg/Library/AppleSupportLib/Bds.h              |  21 +++
 OvmfPkg/Library/AppleSupportLib/Common.h           |  24 ++++
 OvmfPkg/Library/AppleSupportLib/Console.c          |  86 ++++++++++++
 OvmfPkg/Library/AppleSupportLib/Console.h          |  28 ++++
 OvmfPkg/Library/AppleSupportLib/Datahub.c          | 104 ++++++++++++++
 OvmfPkg/Library/AppleSupportLib/Datahub.h          |  32 +++++
 10 files changed, 631 insertions(+)
 create mode 100644 OvmfPkg/Include/Library/AppleSupportLib.h
 create mode 100644 OvmfPkg/Library/AppleSupportLib/AppleSupport.c
 create mode 100644 OvmfPkg/Library/AppleSupportLib/AppleSupportLib.inf
 create mode 100644 OvmfPkg/Library/AppleSupportLib/Bds.c
 create mode 100644 OvmfPkg/Library/AppleSupportLib/Bds.h
 create mode 100644 OvmfPkg/Library/AppleSupportLib/Common.h
 create mode 100644 OvmfPkg/Library/AppleSupportLib/Console.c
 create mode 100644 OvmfPkg/Library/AppleSupportLib/Console.h
 create mode 100644 OvmfPkg/Library/AppleSupportLib/Datahub.c
 create mode 100644 OvmfPkg/Library/AppleSupportLib/Datahub.h

diff --git a/OvmfPkg/Include/Library/AppleSupportLib.h b/OvmfPkg/Include/Library/AppleSupportLib.h
new file mode 100644
index 0000000..583d06b
--- /dev/null
+++ b/OvmfPkg/Include/Library/AppleSupportLib.h
@@ -0,0 +1,28 @@
+/** @file
+*
+*  Copyright (c) 2014, Reza Jelveh. 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.
+*
+**/
+
+#ifndef _APPLESUPPORT_LIB_INCLUDED_
+#define _APPLESUPPORT_LIB_INCLUDED_
+
+EFI_STATUS
+EFIAPI
+InitializeAppleSupport (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  );
+
+EFI_STATUS
+BdsBootApple ();
+
+#endif
diff --git a/OvmfPkg/Library/AppleSupportLib/AppleSupport.c b/OvmfPkg/Library/AppleSupportLib/AppleSupport.c
new file mode 100644
index 0000000..92f7d79
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/AppleSupport.c
@@ -0,0 +1,107 @@
+/** @file
+*
+*  Copyright (c) 2014, Reza Jelveh. 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.
+*
+**/
+
+#include "Console.h"
+#include "Datahub.h"
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <FrameworkDxe.h>
+#include <Guid/DataHubRecords.h>
+#include <Protocol/DataHub.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+
+EFI_GUID gAppleFirmwareVariableGuid = {
+    0x4D1EDE05, 0x38C7, 0x4A6A, {0x9C, 0xC6, 0x4B, 0xCC, 0xA8, 0xB3, 0x8C, 0x14 }
+};
+
+/**
+  Register Handler for the specified interrupt source.
+
+  @param This     Instance pointer for this protocol
+  @param Source   Hardware source of the interrupt
+  @param Handler  Callback for interrupt. NULL to unregister
+
+  @retval  EFI_SUCCESS            The firmware has successfully stored the variable and its data as
+  defined by the Attributes.
+  @retval  EFI_INVALID_PARAMETER  An invalid combination of attribute bits was supplied, or the
+  DataSize exceeds the maximum allowed.
+  @retval  EFI_INVALID_PARAMETER  VariableName is an empty Unicode string.
+  @retval  EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
+  @retval  EFI_DEVICE_ERROR       The variable could not be saved due to a hardware failure.
+  @retval  EFI_WRITE_PROTECTED    The variable in question is read-only.
+  @retval  EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
+  @retval  EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
+  set but the AuthInfo does NOT pass the validation check carried
+  out by the firmware.
+
+**/
+EFI_STATUS
+InitializeFirmware ()
+{
+  EFI_STATUS          Status;
+
+  UINT32              BackgroundClear = 0x00000000;
+  UINT32              FwFeatures      = 0x80000015;
+  UINT32              FwFeaturesMask  = 0x800003ff;
+
+  Status = gRT->SetVariable(L"BackgroundClear",
+                            &gAppleFirmwareVariableGuid,
+                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                            sizeof(BackgroundClear), &BackgroundClear);
+
+  Status = gRT->SetVariable(L"FirmwareFeatures",
+                            &gAppleFirmwareVariableGuid,
+                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                            sizeof(FwFeatures), &FwFeatures);
+
+  Status = gRT->SetVariable(L"FirmwareFeaturesMask",
+                            &gAppleFirmwareVariableGuid,
+                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                            sizeof(FwFeaturesMask), &FwFeaturesMask);
+
+  return Status;
+}
+
+/**
+  Register driver.
+
+  @param  ImageHandle   of the loaded driver
+  @param  SystemTable   Pointer to the System Table
+
+  @retval EFI_SUCCESS   Driver registered
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeAppleSupport (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                         Status;
+
+  Status = InitializeConsoleControl(ImageHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = InitializeDatahub(ImageHandle);
+  ASSERT_EFI_ERROR(Status);
+
+  Status = InitializeFirmware();
+  ASSERT_EFI_ERROR(Status);
+
+  return Status;
+}
diff --git a/OvmfPkg/Library/AppleSupportLib/AppleSupportLib.inf b/OvmfPkg/Library/AppleSupportLib/AppleSupportLib.inf
new file mode 100644
index 0000000..6caf29d
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/AppleSupportLib.inf
@@ -0,0 +1,50 @@
+#/* @file
+#  Copyright (c) 2014, Reza Jelveh. 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.
+#
+#*/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AppleSupportLib
+  FILE_GUID                      = CEC880AF-68DF-4CDF-BBA5-FF9B202382AB
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = AppleSupportLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  AppleSupport.c
+  Console.c
+  Datahub.c
+  Bds.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+  IntelFrameworkPkg/IntelFrameworkPkg.dec
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+  EdkCompatibilityPkg/EdkCompatibilityPkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  BaseLib
+  DebugLib
+  MemoryAllocationLib
+  BaseMemoryLib
+
+[Protocols]
+  gEfiConsoleControlProtocolGuid
+  gEfiDataHubProtocolGuid
diff --git a/OvmfPkg/Library/AppleSupportLib/Bds.c b/OvmfPkg/Library/AppleSupportLib/Bds.c
new file mode 100644
index 0000000..88f7437
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/Bds.c
@@ -0,0 +1,151 @@
+#include "Common.h"
+#include "Bds.h"
+
+#include <PiDxe.h>
+
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/GenericBdsLib.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Guid/FileInfo.h>
+
+EFI_STATUS
+BdsFileSystemLoadImage (
+  IN     EFI_HANDLE Handle,
+  IN     EFI_ALLOCATE_TYPE     Type,
+  IN OUT EFI_PHYSICAL_ADDRESS* Image,
+  OUT    UINTN                 *ImageSize
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol;
+  EFI_FILE_PROTOCOL               *Fs;
+  EFI_FILE_INFO                   *FileInfo;
+  EFI_FILE_PROTOCOL               *File;
+  UINTN                           Size;
+
+  /* FilePathDevicePath = (FILEPATH_DEVICE_PATH*)RemainingDevicePath; */
+
+  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Try to Open the volume and get root directory
+  Status = FsProtocol->OpenVolume (FsProtocol, &Fs);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  File = NULL;
+  Status = Fs->Open (Fs, &File, EFI_CORESERVICES, EFI_FILE_MODE_READ, 0);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Size = 0;
+  File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL);
+  FileInfo = AllocatePool (Size);
+  Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Get the file size
+  Size = FileInfo->FileSize;
+  if (ImageSize) {
+    *ImageSize = Size;
+  }
+  FreePool (FileInfo);
+
+  Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);
+  // Try to allocate in any pages if failed to allocate memory at the defined location
+  if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {
+    Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);
+  }
+  if (!EFI_ERROR (Status)) {
+    Status = File->Read (File, &Size, (VOID*)(UINTN)(*Image));
+  }
+
+  return Status;
+}
+
+
+/**
+  Start an EFI Application from a Device Path
+
+  @param  ParentImageHandle     Handle of the calling image
+  @param  DevicePath            Location of the EFI Application
+
+  @retval EFI_SUCCESS           All drivers have been connected
+  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.
+
+**/
+EFI_STATUS
+BdsStartEfiApplication (
+  IN EFI_HANDLE                  Handle,
+  IN EFI_HANDLE                  ParentImageHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_HANDLE                   ImageHandle;
+  EFI_PHYSICAL_ADDRESS         BinaryBuffer;
+  UINTN                        BinarySize;
+
+  // Find the nearest supported file loader
+  Status = BdsFileSystemLoadImage (Handle, AllocateAnyPages, &BinaryBuffer, &BinarySize);
+  if (EFI_ERROR (Status)) {
+    DEBUG((EFI_D_INFO, "== Bds could not load System image =="));
+    return Status;
+  }
+
+  // Load the image from the Buffer with Boot Services function
+  Status = gBS->LoadImage (TRUE, ParentImageHandle, DevicePath, (VOID*)(UINTN)BinaryBuffer, BinarySize, &ImageHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Before calling the image, enable the Watchdog Timer for  the 5 Minute period
+  gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
+  // Start the image
+  Status = gBS->StartImage (ImageHandle, NULL, NULL);
+  // Clear the Watchdog Timer after the image returns
+  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
+
+  return Status;
+}
+
+
+EFI_STATUS
+BdsBootApple ()
+{
+  UINTN                           Index;
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
+  EFI_HANDLE                      *SimpleFileSystemHandles;
+  UINTN                           NumberSimpleFileSystemHandles;
+
+  gBS->LocateHandleBuffer (
+      ByProtocol,
+      &gEfiSimpleFileSystemProtocolGuid,
+      NULL,
+      &NumberSimpleFileSystemHandles,
+      &SimpleFileSystemHandles
+      );
+  DEBUG((EFI_D_INFO, "Number Device File System: %d\n", NumberSimpleFileSystemHandles));
+  for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
+    //
+    // Get the device path size of SimpleFileSystem handle
+    //
+    TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
+    BdsStartEfiApplication (
+      SimpleFileSystemHandles[Index],
+      gImageHandle,
+      TempDevicePath
+      );
+
+  }
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/AppleSupportLib/Bds.h b/OvmfPkg/Library/AppleSupportLib/Bds.h
new file mode 100644
index 0000000..725d03b
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/Bds.h
@@ -0,0 +1,21 @@
+/** @file
+*
+*  Copyright (c) 2014, Reza Jelveh. 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.
+*
+**/
+
+
+#ifndef _APPLESUPPORT_BDS_H_INCLUDED_
+#define _APPLESUPPORT_BDS_H_INCLUDED_
+
+#define EFI_CORESERVICES L"System\\Library\\CoreServices\\boot.efi"
+
+#endif
diff --git a/OvmfPkg/Library/AppleSupportLib/Common.h b/OvmfPkg/Library/AppleSupportLib/Common.h
new file mode 100644
index 0000000..725f2af
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/Common.h
@@ -0,0 +1,24 @@
+/** @file
+*
+*  Copyright (c) 2014, Reza Jelveh. 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.
+*
+**/
+
+
+#ifndef _APPLESUPPORT_COMMON_H_INCLUDED_
+#define _APPLESUPPORT_COMMON_H_INCLUDED_
+
+#include <Uefi.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#endif
diff --git a/OvmfPkg/Library/AppleSupportLib/Console.c b/OvmfPkg/Library/AppleSupportLib/Console.c
new file mode 100644
index 0000000..5f23300
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/Console.c
@@ -0,0 +1,86 @@
+/** @file
+*
+*  Copyright (c) 2014, Reza Jelveh. 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.
+*
+**/
+
+#include "Console.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,
+};
+
+/**
+  Install ConsoleControl protocol, which is needed for Apple's
+  boot.efi
+
+  @param  ImageHandle   of the loaded driver
+
+  @retval EFI_SUCCESS       Successfully installed protocol handler
+  @retval EFI_DEVICE_ERROR  ConsoleProtocol could not be installed
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeConsoleControl (
+  IN EFI_HANDLE         ImageHandle
+  )
+{
+  EFI_STATUS                         Status;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+      &ImageHandle,
+      &gEfiConsoleControlProtocolGuid,
+      &gConsoleController,
+      NULL
+      );
+
+  return Status;
+}
diff --git a/OvmfPkg/Library/AppleSupportLib/Console.h b/OvmfPkg/Library/AppleSupportLib/Console.h
new file mode 100644
index 0000000..dabf902
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/Console.h
@@ -0,0 +1,28 @@
+/** @file
+*
+*  Copyright (c) 2014, Reza Jelveh. 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.
+*
+**/
+
+#ifndef _APPLESUPPORT_CONSOLE_H_INCLUDED_
+#define _APPLESUPPORT_CONSOLE_H_INCLUDED_
+
+#include "Common.h"
+
+#include <Protocol/ConsoleControl/ConsoleControl.h>
+
+EFI_STATUS
+EFIAPI
+InitializeConsoleControl (
+  IN EFI_HANDLE         ImageHandle
+  );
+
+#endif
diff --git a/OvmfPkg/Library/AppleSupportLib/Datahub.c b/OvmfPkg/Library/AppleSupportLib/Datahub.c
new file mode 100644
index 0000000..3f1ec56
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/Datahub.c
@@ -0,0 +1,104 @@
+/** @file
+*
+*  Copyright (c) 2011, Reza Jelveh. 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.
+*
+**/
+
+#include "Datahub.h"
+
+EFI_GUID gAppleSystemInfoProducerNameGuid = {0x64517CC8, 0x6561, 0x4051, {0xB0, 0x3C, 0x59, 0x64, 0xB6, 0x0F, 0x4C, 0x7A}};
+EFI_GUID gAppleFsbFrequencyPropertyGuid = {0xD1A04D55, 0x75B9, 0x41A3, {0x90, 0x36, 0x8F, 0x4A, 0x26, 0x1C, 0xBB, 0xA2}};
+EFI_GUID gAppleDevicePathsSupportedGuid = {0x5BB91CF7, 0xD816, 0x404B, {0x86, 0x72, 0x68, 0xF2, 0x7F, 0x78, 0x31, 0xDC}};
+
+typedef struct {
+  UINT32              DataNameSize;
+  UINT32              DataSize;
+} EFI_PROPERTY_SUBCLASS_RECORD;
+
+typedef struct {
+  EFI_SUBCLASS_TYPE1_HEADER   Header;
+  EFI_PROPERTY_SUBCLASS_RECORD  Record;
+} EFI_PROPERTY_SUBCLASS_DATA;
+
+
+EFI_STATUS
+SetEfiPlatformProperty (
+    IN EFI_DATA_HUB_PROTOCOL *DataHub,
+    IN CONST EFI_STRING Name,
+    EFI_GUID EfiPropertyGuid,
+    VOID *Data,
+    UINT32 DataSize
+    )
+{
+  EFI_STATUS Status;
+  UINT32 DataNameSize;
+  EFI_PROPERTY_SUBCLASS_DATA *DataRecord;
+
+  DataNameSize = (UINT32)StrSize(Name);
+
+  DataRecord = AllocateZeroPool (sizeof (EFI_PROPERTY_SUBCLASS_DATA) + DataNameSize + DataSize);
+  ASSERT (DataRecord != NULL);
+
+  DataRecord->Header.Version = EFI_DATA_RECORD_HEADER_VERSION;
+  DataRecord->Header.HeaderSize = sizeof(EFI_SUBCLASS_TYPE1_HEADER);
+  DataRecord->Header.Instance = 0xFFFF;
+  DataRecord->Header.SubInstance = 0xFFFF;
+  DataRecord->Header.RecordType = 0xFFFFFFFF;
+  DataRecord->Record.DataNameSize = DataNameSize;
+  DataRecord->Record.DataSize = DataSize;
+
+
+  CopyMem((UINT8 *)DataRecord + sizeof(EFI_PROPERTY_SUBCLASS_DATA), Name, DataNameSize);
+  CopyMem((UINT8 *)DataRecord + sizeof(EFI_PROPERTY_SUBCLASS_DATA) + DataNameSize, Data, DataSize);
+
+  Status = DataHub->LogData(DataHub, &EfiPropertyGuid, &gAppleSystemInfoProducerNameGuid,
+                             EFI_DATA_RECORD_CLASS_DATA,
+                             DataRecord,
+                             sizeof(EFI_PROPERTY_SUBCLASS_DATA) + DataNameSize + DataSize);
+
+  if (DataRecord) {
+    gBS->FreePool(DataRecord);
+  }
+
+  return Status;
+}
+
+/**
+  Initialize the DataHub protocols data for the xnu kernel to
+  detect an EFI boot.
+
+  @param  ImageHandle   of the loaded driver
+
+  @retval EFI_SUCCESS Source was updated to support Handler.
+  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeDatahub (
+  IN EFI_HANDLE         ImageHandle
+  )
+{
+  EFI_STATUS                         Status;
+  EFI_DATA_HUB_PROTOCOL              *DataHub;
+
+  Status = gBS->LocateProtocol(&gEfiDataHubProtocolGuid, NULL, (VOID **)&DataHub);
+  ASSERT_EFI_ERROR(Status);
+
+  UINT64 FsbFrequency = 667000000;
+  UINT32 DevicePathsSupported = 1;
+
+  SetEfiPlatformProperty(DataHub, L"FSBFrequency", gAppleFsbFrequencyPropertyGuid, &FsbFrequency, sizeof(UINT64));
+  SetEfiPlatformProperty(DataHub, L"DevicePathsSupported", gAppleDevicePathsSupportedGuid, &DevicePathsSupported, sizeof(UINT32));
+  ASSERT_EFI_ERROR(Status);
+
+  return Status;
+}
diff --git a/OvmfPkg/Library/AppleSupportLib/Datahub.h b/OvmfPkg/Library/AppleSupportLib/Datahub.h
new file mode 100644
index 0000000..d7f8806
--- /dev/null
+++ b/OvmfPkg/Library/AppleSupportLib/Datahub.h
@@ -0,0 +1,32 @@
+/** @file
+*
+*  Copyright (c) 2014, Reza Jelveh. 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.
+*
+**/
+
+#ifndef _APPLESUPPORT_DATAHUB_H_INCLUDED_
+#define _APPLESUPPORT_DATAHUB_H_INCLUDED_
+
+#include "Common.h"
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <FrameworkDxe.h>
+#include <Guid/DataHubRecords.h>
+#include <Protocol/DataHub.h>
+
+EFI_STATUS
+EFIAPI
+InitializeDatahub (
+  IN EFI_HANDLE         ImageHandle
+  );
+
+#endif
-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [RFC PATCH 5/6] OvmfPkg: add Apple boot support
Posted by Laszlo Ersek 7 years, 7 months ago
On 03/07/17 04:14, Gabriel L. Somlo wrote:
> Apple's boot.efi checks if the ConsoleControl protocol returns
> EFI_SUCCESS in both GetMode and SetMode.
> 
> Apple uses a kernel extension to make parts of the DataHub protocol
> available to the xnu kernel. The xnu kernel then checks for FSB
> frequency and if it's not found fails with:
> 
> "tsc_init: EFI not supported!"
> https://github.com/opensource-apple/xnu/blob/10.9/osfmk/i386/tsc.c
> 
> Also, some firmware settings are added to AppleSupport and written
> to nvram.
> 
> Lastly, use (already present) HFS+ filesystem driver to locate, load,
> and launch the Apple-provided OS X bootloader.

Why can't the Apple-provided OS X boot loader be simply launched through
a normal Boot#### option?

More comments below (staying at the level that I announced in my
response to your blurb):

> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Reza Jelveh <reza.jelveh@tuhh.de>
> Signed-off-by: Gabriel Somlo <gsomlo@gmail.com>
> ---
>  OvmfPkg/Include/Library/AppleSupportLib.h          |  28 ++++
>  OvmfPkg/Library/AppleSupportLib/AppleSupport.c     | 107 +++++++++++++++
>  .../Library/AppleSupportLib/AppleSupportLib.inf    |  50 +++++++
>  OvmfPkg/Library/AppleSupportLib/Bds.c              | 151 +++++++++++++++++++++
>  OvmfPkg/Library/AppleSupportLib/Bds.h              |  21 +++
>  OvmfPkg/Library/AppleSupportLib/Common.h           |  24 ++++
>  OvmfPkg/Library/AppleSupportLib/Console.c          |  86 ++++++++++++
>  OvmfPkg/Library/AppleSupportLib/Console.h          |  28 ++++
>  OvmfPkg/Library/AppleSupportLib/Datahub.c          | 104 ++++++++++++++
>  OvmfPkg/Library/AppleSupportLib/Datahub.h          |  32 +++++
>  10 files changed, 631 insertions(+)
>  create mode 100644 OvmfPkg/Include/Library/AppleSupportLib.h
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/AppleSupport.c
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/AppleSupportLib.inf
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/Bds.c
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/Bds.h
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/Common.h
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/Console.c
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/Console.h
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/Datahub.c
>  create mode 100644 OvmfPkg/Library/AppleSupportLib/Datahub.h
> 
> diff --git a/OvmfPkg/Include/Library/AppleSupportLib.h b/OvmfPkg/Include/Library/AppleSupportLib.h
> new file mode 100644
> index 0000000..583d06b
> --- /dev/null
> +++ b/OvmfPkg/Include/Library/AppleSupportLib.h
> @@ -0,0 +1,28 @@
> +/** @file
> +*
> +*  Copyright (c) 2014, Reza Jelveh. 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

This line (and a lot of other lines) are too long. Please stick with a
line length of 80 if possible, across the series.

> +*  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.
> +*
> +**/
> +
> +#ifndef _APPLESUPPORT_LIB_INCLUDED_
> +#define _APPLESUPPORT_LIB_INCLUDED_
> +
> +EFI_STATUS
> +EFIAPI
> +InitializeAppleSupport (
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE   *SystemTable
> +  );
> +
> +EFI_STATUS
> +BdsBootApple ();

Public library interfaces are required to be EFIAPI.

> +
> +#endif

This library class header uses EFI-level types, such as EFI_STATUS,
EFI_HANDLE, and EFI_SYSTEM_TABLE. If I'm right that implies that the
MODULE_TYPE, for any of the library instances (== the INF files) cannot
be BASE. I think you need MODULE_TYPE=DXE_DRIVER.


> diff --git a/OvmfPkg/Library/AppleSupportLib/AppleSupport.c b/OvmfPkg/Library/AppleSupportLib/AppleSupport.c
> new file mode 100644
> index 0000000..92f7d79
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/AppleSupport.c
> @@ -0,0 +1,107 @@
> +/** @file
> +*
> +*  Copyright (c) 2014, Reza Jelveh. 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.
> +*
> +**/
> +
> +#include "Console.h"
> +#include "Datahub.h"
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <FrameworkDxe.h>
> +#include <Guid/DataHubRecords.h>
> +#include <Protocol/DataHub.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>

Please keep the includes sorted, at least by category. Also,
module-specific includes should go to the bottom.

> +
> +
> +EFI_GUID gAppleFirmwareVariableGuid = {
> +    0x4D1EDE05, 0x38C7, 0x4A6A, {0x9C, 0xC6, 0x4B, 0xCC, 0xA8, 0xB3, 0x8C, 0x14 }
> +};

GUID definitions belong under OvmfPkg/Include/Guid, and to
OvmfPkg/OvmfPkg.dec. Please refer to the examples seen in those places
for the pattern to follow.


> +
> +/**
> +  Register Handler for the specified interrupt source.
> +
> +  @param This     Instance pointer for this protocol
> +  @param Source   Hardware source of the interrupt
> +  @param Handler  Callback for interrupt. NULL to unregister

@param should be annotated with [in] / [out] / [in,out].

> +
> +  @retval  EFI_SUCCESS            The firmware has successfully stored the variable and its data as
> +  defined by the Attributes.

Wrapped line should be aligned to the right column.

> +  @retval  EFI_INVALID_PARAMETER  An invalid combination of attribute bits was supplied, or the
> +  DataSize exceeds the maximum allowed.

Ditto.

> +  @retval  EFI_INVALID_PARAMETER  VariableName is an empty Unicode string.
> +  @retval  EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
> +  @retval  EFI_DEVICE_ERROR       The variable could not be saved due to a hardware failure.
> +  @retval  EFI_WRITE_PROTECTED    The variable in question is read-only.
> +  @retval  EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
> +  @retval  EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
> +  set but the AuthInfo does NOT pass the validation check carried
> +  out by the firmware.

Lines too long etc.

> +
> +**/
> +EFI_STATUS
> +InitializeFirmware ()
> +{
> +  EFI_STATUS          Status;
> +
> +  UINT32              BackgroundClear = 0x00000000;
> +  UINT32              FwFeatures      = 0x80000015;
> +  UINT32              FwFeaturesMask  = 0x800003ff;
> +
> +  Status = gRT->SetVariable(L"BackgroundClear",
> +                            &gAppleFirmwareVariableGuid,
> +                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
> +                            sizeof(BackgroundClear), &BackgroundClear);

Please consult the coding style how to align the second and further
lines -- they should be indented one or (preferably) two characters
relative to the word "SetVariable".

Also, Status is ignored, ...

> +
> +  Status = gRT->SetVariable(L"FirmwareFeatures",
> +                            &gAppleFirmwareVariableGuid,
> +                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
> +                            sizeof(FwFeatures), &FwFeatures);
> +
> +  Status = gRT->SetVariable(L"FirmwareFeaturesMask",
> +                            &gAppleFirmwareVariableGuid,
> +                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
> +                            sizeof(FwFeaturesMask), &FwFeaturesMask);
> +
> +  return Status;
> +}
> +
> +/**
> +  Register driver.
> +
> +  @param  ImageHandle   of the loaded driver
> +  @param  SystemTable   Pointer to the System Table
> +
> +  @retval EFI_SUCCESS   Driver registered
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeAppleSupport (
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE   *SystemTable
> +  )
> +{
> +  EFI_STATUS                         Status;
> +
> +  Status = InitializeConsoleControl(ImageHandle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = InitializeDatahub(ImageHandle);
> +  ASSERT_EFI_ERROR(Status);
> +
> +  Status = InitializeFirmware();
> +  ASSERT_EFI_ERROR(Status);
> +
> +  return Status;
> +}

If these functions fail:
- do we really want to hang the boot process?
- can we roll them back as appropriate, and just return an error?

> diff --git a/OvmfPkg/Library/AppleSupportLib/AppleSupportLib.inf b/OvmfPkg/Library/AppleSupportLib/AppleSupportLib.inf
> new file mode 100644
> index 0000000..6caf29d
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/AppleSupportLib.inf
> @@ -0,0 +1,50 @@
> +#/* @file

Missing note about the purpose of this library instance.

> +#  Copyright (c) 2014, Reza Jelveh. All rights reserved.

Given that these are new files (which you'll likely modify), I think
your (C) should be here as well.

> +#
> +#  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.
> +#
> +#*/
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005

Please use the most recent version of the INF spec here. (The INF spec
documents the INF_VERSION define.)

> +  BASE_NAME                      = AppleSupportLib
> +  FILE_GUID                      = CEC880AF-68DF-4CDF-BBA5-FF9B202382AB
> +  MODULE_TYPE                    = BASE

Shouldn't be BASE, pls. see above.

> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = AppleSupportLib
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  AppleSupport.c
> +  Console.c
> +  Datahub.c
> +  Bds.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +  IntelFrameworkPkg/IntelFrameworkPkg.dec
> +  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
> +  EdkCompatibilityPkg/EdkCompatibilityPkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  BaseLib
> +  DebugLib
> +  MemoryAllocationLib
> +  BaseMemoryLib
> +
> +[Protocols]
> +  gEfiConsoleControlProtocolGuid
> +  gEfiDataHubProtocolGuid
> diff --git a/OvmfPkg/Library/AppleSupportLib/Bds.c b/OvmfPkg/Library/AppleSupportLib/Bds.c
> new file mode 100644
> index 0000000..88f7437
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/Bds.c
> @@ -0,0 +1,151 @@
> +#include "Common.h"
> +#include "Bds.h"
> +
> +#include <PiDxe.h>
> +
> +#include <Library/DevicePathLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/GenericBdsLib.h>
> +#include <Protocol/SimpleFileSystem.h>
> +
> +#include <Guid/FileInfo.h>
> +
> +EFI_STATUS
> +BdsFileSystemLoadImage (
> +  IN     EFI_HANDLE Handle,
> +  IN     EFI_ALLOCATE_TYPE     Type,
> +  IN OUT EFI_PHYSICAL_ADDRESS* Image,
> +  OUT    UINTN                 *ImageSize
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol;
> +  EFI_FILE_PROTOCOL               *Fs;
> +  EFI_FILE_INFO                   *FileInfo;
> +  EFI_FILE_PROTOCOL               *File;
> +  UINTN                           Size;
> +
> +  /* FilePathDevicePath = (FILEPATH_DEVICE_PATH*)RemainingDevicePath; */

Dead code, please remove this.

> +
> +  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // Try to Open the volume and get root directory

The comment format is:

//
// comment
//

> +  Status = FsProtocol->OpenVolume (FsProtocol, &Fs);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  File = NULL;
> +  Status = Fs->Open (Fs, &File, EFI_CORESERVICES, EFI_FILE_MODE_READ, 0);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }

Resource leak, the volume has not been closed. (But, again, I'm not sure
why normal Boot#### options are not suitable for loading whatever is
being loaded here.)

> +
> +  Size = 0;
> +  File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL);
> +  FileInfo = AllocatePool (Size);
> +  Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }

More resource leaks. I know you didn't write this code, but can we
please at least *pretend* to not leak resources left and right on error?

> +
> +  // Get the file size
> +  Size = FileInfo->FileSize;
> +  if (ImageSize) {
> +    *ImageSize = Size;
> +  }
> +  FreePool (FileInfo);
> +
> +  Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);
> +  // Try to allocate in any pages if failed to allocate memory at the defined location
> +  if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {
> +    Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);
> +  }
> +  if (!EFI_ERROR (Status)) {
> +    Status = File->Read (File, &Size, (VOID*)(UINTN)(*Image));
> +  }
> +
> +  return Status;

Leaks resources even on success. Splendid.

Sorry if I'm sarcastic, but this has nothing to do with UEFI or
firmware; releasing resources is just plain C.

Again, I know you didn't write this, but I shouldn't be the *first*
person actually reading this code and gasping.


> +}
> +
> +
> +/**
> +  Start an EFI Application from a Device Path
> +
> +  @param  ParentImageHandle     Handle of the calling image
> +  @param  DevicePath            Location of the EFI Application
> +
> +  @retval EFI_SUCCESS           All drivers have been connected
> +  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found
> +  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.
> +
> +**/
> +EFI_STATUS
> +BdsStartEfiApplication (
> +  IN EFI_HANDLE                  Handle,
> +  IN EFI_HANDLE                  ParentImageHandle,
> +  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_HANDLE                   ImageHandle;
> +  EFI_PHYSICAL_ADDRESS         BinaryBuffer;
> +  UINTN                        BinarySize;
> +
> +  // Find the nearest supported file loader
> +  Status = BdsFileSystemLoadImage (Handle, AllocateAnyPages, &BinaryBuffer, &BinarySize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG((EFI_D_INFO, "== Bds could not load System image =="));

New code should use DEBUG_INFO, not EFI_D_INFO (same for all other
similar constants).

Additionally, the coding style requires a space between DEBUG and "((".

> +    return Status;
> +  }
> +
> +  // Load the image from the Buffer with Boot Services function
> +  Status = gBS->LoadImage (TRUE, ParentImageHandle, DevicePath, (VOID*)(UINTN)BinaryBuffer, BinarySize, &ImageHandle);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // Before calling the image, enable the Watchdog Timer for  the 5 Minute period
> +  gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
> +  // Start the image
> +  Status = gBS->StartImage (ImageHandle, NULL, NULL);
> +  // Clear the Watchdog Timer after the image returns
> +  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);

So this appears to come from the boot manager requirements in the UEFI
spec, but I still don't understand why we can't just boot this thing via
plain Boot#### / BootOrder.

> +
> +  return Status;
> +}
> +
> +
> +EFI_STATUS
> +BdsBootApple ()
> +{
> +  UINTN                           Index;
> +  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
> +  EFI_HANDLE                      *SimpleFileSystemHandles;
> +  UINTN                           NumberSimpleFileSystemHandles;
> +
> +  gBS->LocateHandleBuffer (
> +      ByProtocol,
> +      &gEfiSimpleFileSystemProtocolGuid,
> +      NULL,
> +      &NumberSimpleFileSystemHandles,
> +      &SimpleFileSystemHandles
> +      );

Return code not checked.

I'm sorry, I got exhausted by now. There are so many issues even on the
surface that I don't know what to comment on.

I recommend the following approach:

- distill all the information necessary for booting OSX into a design /
requirements document. Make it a TechNotes.txt somewhere, or a detailed
commit message. In particular, painstakingly list where the OSX boot
process diverges from the normal UEFI boot process, please.

- implement the functionality from the bottom up, adhering to the coding
standard at every step. Doing three iterations just to clean up the
surface (without any consideration for the functionality) doesn't look
fun. PatchCheck.py should help with most of the warts.

Again, I don't intend to verify the functionality of this code, but to
some extent I do feel responsible for ascertaining the superficial
quality of this code -- not for myself, but for the next poor bloke that
will have to look at it.

Even though my main goal here is the perfect isolation of this feature
from the default build, in order to keep regressions out, and that
implies I shouldn't dig into the code very deeply, there seem to be so
many issues with the basics that I couldn't, with a clear conscience,
say *only*: "okay, after isolating this, please dump this into a
separate directory, and take onwership of it". I do wish for you to own
this in OVMF, but it needs a lot of code improvement even for that.

Thanks
Laszlo

> +  DEBUG((EFI_D_INFO, "Number Device File System: %d\n", NumberSimpleFileSystemHandles));
> +  for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
> +    //
> +    // Get the device path size of SimpleFileSystem handle
> +    //
> +    TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
> +    BdsStartEfiApplication (
> +      SimpleFileSystemHandles[Index],
> +      gImageHandle,
> +      TempDevicePath
> +      );
> +
> +  }
> +  return EFI_SUCCESS;
> +}
> diff --git a/OvmfPkg/Library/AppleSupportLib/Bds.h b/OvmfPkg/Library/AppleSupportLib/Bds.h
> new file mode 100644
> index 0000000..725d03b
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/Bds.h
> @@ -0,0 +1,21 @@
> +/** @file
> +*
> +*  Copyright (c) 2014, Reza Jelveh. 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.
> +*
> +**/
> +
> +
> +#ifndef _APPLESUPPORT_BDS_H_INCLUDED_
> +#define _APPLESUPPORT_BDS_H_INCLUDED_
> +
> +#define EFI_CORESERVICES L"System\\Library\\CoreServices\\boot.efi"
> +
> +#endif
> diff --git a/OvmfPkg/Library/AppleSupportLib/Common.h b/OvmfPkg/Library/AppleSupportLib/Common.h
> new file mode 100644
> index 0000000..725f2af
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/Common.h
> @@ -0,0 +1,24 @@
> +/** @file
> +*
> +*  Copyright (c) 2014, Reza Jelveh. 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.
> +*
> +**/
> +
> +
> +#ifndef _APPLESUPPORT_COMMON_H_INCLUDED_
> +#define _APPLESUPPORT_COMMON_H_INCLUDED_
> +
> +#include <Uefi.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +
> +#endif
> diff --git a/OvmfPkg/Library/AppleSupportLib/Console.c b/OvmfPkg/Library/AppleSupportLib/Console.c
> new file mode 100644
> index 0000000..5f23300
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/Console.c
> @@ -0,0 +1,86 @@
> +/** @file
> +*
> +*  Copyright (c) 2014, Reza Jelveh. 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.
> +*
> +**/
> +
> +#include "Console.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,
> +};
> +
> +/**
> +  Install ConsoleControl protocol, which is needed for Apple's
> +  boot.efi
> +
> +  @param  ImageHandle   of the loaded driver
> +
> +  @retval EFI_SUCCESS       Successfully installed protocol handler
> +  @retval EFI_DEVICE_ERROR  ConsoleProtocol could not be installed
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeConsoleControl (
> +  IN EFI_HANDLE         ImageHandle
> +  )
> +{
> +  EFI_STATUS                         Status;
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +      &ImageHandle,
> +      &gEfiConsoleControlProtocolGuid,
> +      &gConsoleController,
> +      NULL
> +      );
> +
> +  return Status;
> +}
> diff --git a/OvmfPkg/Library/AppleSupportLib/Console.h b/OvmfPkg/Library/AppleSupportLib/Console.h
> new file mode 100644
> index 0000000..dabf902
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/Console.h
> @@ -0,0 +1,28 @@
> +/** @file
> +*
> +*  Copyright (c) 2014, Reza Jelveh. 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.
> +*
> +**/
> +
> +#ifndef _APPLESUPPORT_CONSOLE_H_INCLUDED_
> +#define _APPLESUPPORT_CONSOLE_H_INCLUDED_
> +
> +#include "Common.h"
> +
> +#include <Protocol/ConsoleControl/ConsoleControl.h>
> +
> +EFI_STATUS
> +EFIAPI
> +InitializeConsoleControl (
> +  IN EFI_HANDLE         ImageHandle
> +  );
> +
> +#endif
> diff --git a/OvmfPkg/Library/AppleSupportLib/Datahub.c b/OvmfPkg/Library/AppleSupportLib/Datahub.c
> new file mode 100644
> index 0000000..3f1ec56
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/Datahub.c
> @@ -0,0 +1,104 @@
> +/** @file
> +*
> +*  Copyright (c) 2011, Reza Jelveh. 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.
> +*
> +**/
> +
> +#include "Datahub.h"
> +
> +EFI_GUID gAppleSystemInfoProducerNameGuid = {0x64517CC8, 0x6561, 0x4051, {0xB0, 0x3C, 0x59, 0x64, 0xB6, 0x0F, 0x4C, 0x7A}};
> +EFI_GUID gAppleFsbFrequencyPropertyGuid = {0xD1A04D55, 0x75B9, 0x41A3, {0x90, 0x36, 0x8F, 0x4A, 0x26, 0x1C, 0xBB, 0xA2}};
> +EFI_GUID gAppleDevicePathsSupportedGuid = {0x5BB91CF7, 0xD816, 0x404B, {0x86, 0x72, 0x68, 0xF2, 0x7F, 0x78, 0x31, 0xDC}};
> +
> +typedef struct {
> +  UINT32              DataNameSize;
> +  UINT32              DataSize;
> +} EFI_PROPERTY_SUBCLASS_RECORD;
> +
> +typedef struct {
> +  EFI_SUBCLASS_TYPE1_HEADER   Header;
> +  EFI_PROPERTY_SUBCLASS_RECORD  Record;
> +} EFI_PROPERTY_SUBCLASS_DATA;
> +
> +
> +EFI_STATUS
> +SetEfiPlatformProperty (
> +    IN EFI_DATA_HUB_PROTOCOL *DataHub,
> +    IN CONST EFI_STRING Name,
> +    EFI_GUID EfiPropertyGuid,
> +    VOID *Data,
> +    UINT32 DataSize
> +    )
> +{
> +  EFI_STATUS Status;
> +  UINT32 DataNameSize;
> +  EFI_PROPERTY_SUBCLASS_DATA *DataRecord;
> +
> +  DataNameSize = (UINT32)StrSize(Name);
> +
> +  DataRecord = AllocateZeroPool (sizeof (EFI_PROPERTY_SUBCLASS_DATA) + DataNameSize + DataSize);
> +  ASSERT (DataRecord != NULL);
> +
> +  DataRecord->Header.Version = EFI_DATA_RECORD_HEADER_VERSION;
> +  DataRecord->Header.HeaderSize = sizeof(EFI_SUBCLASS_TYPE1_HEADER);
> +  DataRecord->Header.Instance = 0xFFFF;
> +  DataRecord->Header.SubInstance = 0xFFFF;
> +  DataRecord->Header.RecordType = 0xFFFFFFFF;
> +  DataRecord->Record.DataNameSize = DataNameSize;
> +  DataRecord->Record.DataSize = DataSize;
> +
> +
> +  CopyMem((UINT8 *)DataRecord + sizeof(EFI_PROPERTY_SUBCLASS_DATA), Name, DataNameSize);
> +  CopyMem((UINT8 *)DataRecord + sizeof(EFI_PROPERTY_SUBCLASS_DATA) + DataNameSize, Data, DataSize);
> +
> +  Status = DataHub->LogData(DataHub, &EfiPropertyGuid, &gAppleSystemInfoProducerNameGuid,
> +                             EFI_DATA_RECORD_CLASS_DATA,
> +                             DataRecord,
> +                             sizeof(EFI_PROPERTY_SUBCLASS_DATA) + DataNameSize + DataSize);
> +
> +  if (DataRecord) {
> +    gBS->FreePool(DataRecord);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Initialize the DataHub protocols data for the xnu kernel to
> +  detect an EFI boot.
> +
> +  @param  ImageHandle   of the loaded driver
> +
> +  @retval EFI_SUCCESS Source was updated to support Handler.
> +  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeDatahub (
> +  IN EFI_HANDLE         ImageHandle
> +  )
> +{
> +  EFI_STATUS                         Status;
> +  EFI_DATA_HUB_PROTOCOL              *DataHub;
> +
> +  Status = gBS->LocateProtocol(&gEfiDataHubProtocolGuid, NULL, (VOID **)&DataHub);
> +  ASSERT_EFI_ERROR(Status);
> +
> +  UINT64 FsbFrequency = 667000000;
> +  UINT32 DevicePathsSupported = 1;
> +
> +  SetEfiPlatformProperty(DataHub, L"FSBFrequency", gAppleFsbFrequencyPropertyGuid, &FsbFrequency, sizeof(UINT64));
> +  SetEfiPlatformProperty(DataHub, L"DevicePathsSupported", gAppleDevicePathsSupportedGuid, &DevicePathsSupported, sizeof(UINT32));
> +  ASSERT_EFI_ERROR(Status);
> +
> +  return Status;
> +}
> diff --git a/OvmfPkg/Library/AppleSupportLib/Datahub.h b/OvmfPkg/Library/AppleSupportLib/Datahub.h
> new file mode 100644
> index 0000000..d7f8806
> --- /dev/null
> +++ b/OvmfPkg/Library/AppleSupportLib/Datahub.h
> @@ -0,0 +1,32 @@
> +/** @file
> +*
> +*  Copyright (c) 2014, Reza Jelveh. 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.
> +*
> +**/
> +
> +#ifndef _APPLESUPPORT_DATAHUB_H_INCLUDED_
> +#define _APPLESUPPORT_DATAHUB_H_INCLUDED_
> +
> +#include "Common.h"
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <FrameworkDxe.h>
> +#include <Guid/DataHubRecords.h>
> +#include <Protocol/DataHub.h>
> +
> +EFI_STATUS
> +EFIAPI
> +InitializeDatahub (
> +  IN EFI_HANDLE         ImageHandle
> +  );
> +
> +#endif
> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel