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 <ard.biesheuvel@linaro.org>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Ard Biesheuvel 2017-03-27 10:57:31 +01:00
parent 89ad870fbf
commit 779cc439e8
8 changed files with 432 additions and 0 deletions

View File

@ -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 <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/DevicePathLib.h>
#include <Library/DxeServicesLib.h>
#include <Library/HiiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#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 ();
}

View File

@ -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 <Guid/HiiPlatformSetupFormset.h>
#include <Guid/DtPlatformFormSet.h>
#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

View File

@ -0,0 +1,58 @@
## @file
#
# Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
#
# 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

View File

@ -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 <Enter> 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"

View File

@ -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;

View File

@ -62,6 +62,12 @@
## Include/Guid/PlatformHasDeviceTree.h
gEdkiiPlatformHasDeviceTreeGuid = { 0x7ebb920d, 0x1aaf, 0x46d9, { 0xb2, 0xaf, 0x54, 0x1e, 0x1d, 0xce, 0x14, 0x8b } }
# HII form set GUID for DtPlatformDxe driver
gDtPlatformFormSetGuid = { 0x2b7a240d, 0xd5ad, 0x4fd6, { 0xbe, 0x1c, 0xdf, 0xa4, 0x41, 0x5f, 0x55, 0x26 } }
# File GUID for default DTB image embedded in the firmware volume
gDtPlatformDefaultDtbFileGuid = { 0x25462cda, 0x221f, 0x47df, { 0xac, 0x1d, 0x25, 0x9c, 0xfa, 0xa4, 0xe3, 0x26 } }
[Protocols.common]
gHardwareInterruptProtocolGuid = { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } }
gEfiDebugSupportPeriodicCallbackProtocolGuid = { 0x9546e07c, 0x2cbb, 0x4c88, { 0x98, 0x6c, 0xcd, 0x34, 0x10, 0x86, 0xf0, 0x44 } }

View File

@ -0,0 +1,23 @@
/** @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_DEFAULT_DTB_FILE_H__
#define __DT_PLATFORM_DEFAULT_DTB_FILE_H__
#define DT_PLATFORM_DEFAULT_DTB_FILE_GUID \
{ 0x25462cda, 0x221f, 0x47df, { 0xac, 0x1d, 0x25, 0x9c, 0xfa, 0xa4, 0xe3, 0x26 } }
extern EFI_GUID gDtPlatformDefaultDtbFileGuid;
#endif

View File

@ -0,0 +1,23 @@
/** @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_FORMSET_H__
#define __DT_PLATFORM_FORMSET_H__
#define DT_PLATFORM_FORMSET_GUID \
{ 0x2b7a240d, 0xd5ad, 0x4fd6, { 0xbe, 0x1c, 0xdf, 0xa4, 0x41, 0x5f, 0x55, 0x26 } }
extern EFI_GUID gDtPlatformFormSetGuid;
#endif