From 779cc439e881ba2f0be3a12efc955c548e955d8b Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 27 Mar 2017 10:57:31 +0100 Subject: EmbeddedPkg: add DT platform driver to select between DT and ACPI As a follow up to the changes proposed by Laszlo to make ACPI and DT mutually exclusive on ArmVirtQemu, this patch proposes a DT platform DXE driver that either installs the NULL protocol PlatformHasAcpiGuid, or installs the FV embedded DTB binary as a configuration table under the appropriate GUID, depending on a preference setting recorded as a UEFI variable, and configurable via a HII screen. The DTB binary can be embedded in the firmware image by adding the following to the platform .fdf file: FILE FREEFORM = 25462CDA-221F-47DF-AC1D-259CFAA4E326 { SECTION RAW = SomePkg/path/to/foo.dtb } Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel Reviewed-by: Laszlo Ersek --- EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.c | 213 +++++++++++++++++++++ EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.h | 31 +++ .../Drivers/DtPlatformDxe/DtPlatformDxe.inf | 58 ++++++ .../Drivers/DtPlatformDxe/DtPlatformHii.uni | 27 +++ .../Drivers/DtPlatformDxe/DtPlatformHii.vfr | 51 +++++ 5 files changed, 380 insertions(+) create mode 100644 EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.c create mode 100644 EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.h create mode 100644 EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.inf create mode 100644 EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformHii.uni create mode 100644 EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformHii.vfr (limited to 'EmbeddedPkg/Drivers') diff --git a/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.c b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.c new file mode 100644 index 0000000000..5778633b49 --- /dev/null +++ b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.c @@ -0,0 +1,213 @@ +/** @file +* +* Copyright (c) 2017, Linaro, Ltd. 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DtPlatformDxe.h" + +extern UINT8 DtPlatformHiiBin[]; +extern UINT8 DtPlatformDxeStrings[]; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +STATIC HII_VENDOR_DEVICE_PATH mDtPlatformDxeVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + DT_PLATFORM_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +STATIC +EFI_STATUS +InstallHiiPages ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces (&DriverHandle, + &gEfiDevicePathProtocolGuid, + &mDtPlatformDxeVendorDevicePath, + NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + HiiHandle = HiiAddPackages (&gDtPlatformFormSetGuid, + DriverHandle, + DtPlatformDxeStrings, + DtPlatformHiiBin, + NULL); + + if (HiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces (DriverHandle, + &gEfiDevicePathProtocolGuid, + &mDtPlatformDxeVendorDevicePath, + NULL); + return EFI_OUT_OF_RESOURCES; + } + return EFI_SUCCESS; +} + +/** + The entry point for DtPlatformDxe driver. + + @param[in] ImageHandle The image handle of the driver. + @param[in] SystemTable The system table. + + @retval EFI_ALREADY_STARTED The driver already exists in system. + @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of + resources. + @retval EFI_SUCCES All the related protocols are installed on + the driver. + +**/ +EFI_STATUS +EFIAPI +DtPlatformDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + DT_ACPI_VARSTORE_DATA DtAcpiPref; + UINTN BufferSize; + VOID *Dtb; + UINTN DtbSize; + VOID *DtbCopy; + + // + // Check whether a DTB blob is included in the firmware image. + // + Dtb = NULL; + Status = GetSectionFromAnyFv (&gDtPlatformDefaultDtbFileGuid, + EFI_SECTION_RAW, 0, &Dtb, &DtbSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a: no DTB blob found, defaulting to ACPI\n", + __FUNCTION__)); + DtAcpiPref.Pref = DT_ACPI_SELECT_ACPI; + } else { + // + // Get the current DT/ACPI preference from the DtAcpiPref variable. + // + BufferSize = sizeof (DtAcpiPref); + Status = gRT->GetVariable(DT_ACPI_VARIABLE_NAME, &gDtPlatformFormSetGuid, + NULL, &BufferSize, &DtAcpiPref); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a: no DT/ACPI preference found, defaulting to DT\n", + __FUNCTION__)); + DtAcpiPref.Pref = DT_ACPI_SELECT_DT; + } + } + + if (!EFI_ERROR (Status) && + DtAcpiPref.Pref != DT_ACPI_SELECT_ACPI && + DtAcpiPref.Pref != DT_ACPI_SELECT_DT) { + DEBUG ((DEBUG_WARN, "%a: invalid value for %s, defaulting to DT\n", + __FUNCTION__, DT_ACPI_VARIABLE_NAME)); + DtAcpiPref.Pref = DT_ACPI_SELECT_DT; + Status = EFI_INVALID_PARAMETER; // trigger setvar below + } + + // + // Write the newly selected default value back to the variable store. + // + if (EFI_ERROR (Status)) { + Status = gRT->SetVariable(DT_ACPI_VARIABLE_NAME, &gDtPlatformFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (DtAcpiPref), &DtAcpiPref); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (DtAcpiPref.Pref == DT_ACPI_SELECT_ACPI) { + // + // ACPI was selected: install the gEdkiiPlatformHasAcpiGuid GUID as a + // NULL protocol to unlock dispatch of ACPI related drivers. + // + Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle, + &gEdkiiPlatformHasAcpiGuid, NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: failed to install gEdkiiPlatformHasAcpiGuid as a protocol\n", + __FUNCTION__)); + return Status; + } + } else if (DtAcpiPref.Pref == DT_ACPI_SELECT_DT) { + // + // DT was selected: copy the blob into newly allocated memory and install + // a reference to it as the FDT configuration table. + // + DtbCopy = AllocateCopyPool (DtbSize, Dtb); + if (DtbCopy == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DtbCopy); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to install FDT configuration table\n", + __FUNCTION__)); + FreePool (DtbCopy); + return Status; + } + } else { + ASSERT (FALSE); + } + + // + // No point in installing the HII pages if ACPI is the only description + // we have + // + if (Dtb == NULL) { + return EFI_SUCCESS; + } + + // + // Note that we don't uninstall the gEdkiiPlatformHasAcpiGuid protocol nor + // the FDT configuration table if the following call fails. While that will + // cause loading of this driver to fail, proceeding with ACPI and DT both + // disabled will guarantee a failed boot, and so it is better to leave them + // installed in that case. + // + return InstallHiiPages (); +} diff --git a/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.h b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.h new file mode 100644 index 0000000000..2369367277 --- /dev/null +++ b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.h @@ -0,0 +1,31 @@ +/** @file +* +* Copyright (c) 2017, Linaro Limited. 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 __DT_PLATFORM_DXE_H__ +#define __DT_PLATFORM_DXE_H__ + +#include +#include + +#define DT_ACPI_SELECT_DT 0x0 +#define DT_ACPI_SELECT_ACPI 0x1 + +#define DT_ACPI_VARIABLE_NAME L"DtAcpiPref" + +typedef struct { + UINT8 Pref; + UINT8 Reserved[3]; +} DT_ACPI_VARSTORE_DATA; + +#endif diff --git a/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.inf b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.inf new file mode 100644 index 0000000000..b73877a608 --- /dev/null +++ b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.inf @@ -0,0 +1,58 @@ +## @file +# +# Copyright (c) 2017, Linaro, Ltd. 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 = 0x00010019 + BASE_NAME = DtPlatformDxe + FILE_GUID = FC097B3C-2EBD-4A75-A3DA-121DCAB365CC + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DtPlatformDxeEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + DtPlatformDxe.c + DtPlatformHii.vfr + DtPlatformHii.uni + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DxeServicesLib + HiiLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + +[Guids] + gDtPlatformFormSetGuid + gDtPlatformDefaultDtbFileGuid + gEdkiiPlatformHasAcpiGuid + gFdtTableGuid + +[Depex] + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid diff --git a/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformHii.uni b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformHii.uni new file mode 100644 index 0000000000..bc995c1d0f --- /dev/null +++ b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformHii.uni @@ -0,0 +1,27 @@ +/** @file +* +* Copyright (c) 2017, Linaro, Ltd. 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. +* +**/ + +#langdef en-US "English" + +#string STR_FORM_SET_TITLE #language en-US "O/S Hardware Description Selection" +#string STR_FORM_SET_TITLE_HELP #language en-US "Press to choose between ACPI and DT hardware descriptions." + +#string STR_MAIN_FORM_TITLE #language en-US "O/S Hardware Description Selection" +#string STR_NULL_STRING #language en-US "" + +#string STR_DT_ACPI_SELECT_PROMPT #language en-US "O/S Hardware Description" +#string STR_DT_ACPI_SELECT_HELP #language en-US "Select the hardware description that will be exposed to the O/S." + +#string STR_DT_ACPI_SELECT_DT #language en-US "Device Tree" +#string STR_DT_ACPI_SELECT_ACPI #language en-US "ACPI" diff --git a/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformHii.vfr b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformHii.vfr new file mode 100644 index 0000000000..3516746c4d --- /dev/null +++ b/EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformHii.vfr @@ -0,0 +1,51 @@ +/** @file +* +* Copyright (c) 2017, Linaro, Ltd. 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 "DtPlatformDxe.h" + +// +// EFI Variable attributes +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_READ_ONLY 0x00000008 + +formset + guid = DT_PLATFORM_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_SET_TITLE), + help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP), + classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + + efivarstore DT_ACPI_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, // EFI variable attributes + name = DtAcpiPref, + guid = DT_PLATFORM_FORMSET_GUID; + + form formid = 0x1000, + title = STRING_TOKEN(STR_MAIN_FORM_TITLE); + + oneof varid = DtAcpiPref.Pref, + prompt = STRING_TOKEN(STR_DT_ACPI_SELECT_PROMPT), + help = STRING_TOKEN(STR_DT_ACPI_SELECT_HELP), + flags = NUMERIC_SIZE_1 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_DT_ACPI_SELECT_DT), value = DT_ACPI_SELECT_DT, flags = DEFAULT; + option text = STRING_TOKEN(STR_DT_ACPI_SELECT_ACPI), value = DT_ACPI_SELECT_ACPI, flags = 0; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + endform; + +endformset; -- cgit v1.2.3