2017-03-27 11:57:31 +02:00
|
|
|
/** @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>
|
2017-03-29 13:05:01 +02:00
|
|
|
#include <Library/DtPlatformDtbLoaderLib.h>
|
2017-03-27 11:57:31 +02:00
|
|
|
#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;
|
|
|
|
|
|
|
|
Dtb = NULL;
|
2017-03-29 13:05:01 +02:00
|
|
|
Status = DtPlatformLoadDtb (&Dtb, &DtbSize);
|
2017-03-27 11:57:31 +02:00
|
|
|
if (EFI_ERROR (Status)) {
|
2017-03-29 13:05:01 +02:00
|
|
|
DEBUG ((DEBUG_WARN,
|
|
|
|
"%a: no DTB blob could be loaded, defaulting to ACPI (Status == %r)\n",
|
|
|
|
__FUNCTION__, Status));
|
2017-03-27 11:57:31 +02:00
|
|
|
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)) {
|
2017-03-29 13:05:01 +02:00
|
|
|
goto FreeDtb;
|
2017-03-27 11:57:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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__));
|
2017-03-29 13:05:01 +02:00
|
|
|
goto FreeDtb;
|
2017-03-27 11:57:31 +02:00
|
|
|
}
|
|
|
|
} 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.
|
|
|
|
//
|
2017-03-29 13:05:01 +02:00
|
|
|
Status = gBS->InstallConfigurationTable (&gFdtTableGuid, Dtb);
|
2017-03-27 11:57:31 +02:00
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
DEBUG ((DEBUG_ERROR, "%a: failed to install FDT configuration table\n",
|
|
|
|
__FUNCTION__));
|
2017-03-29 13:05:01 +02:00
|
|
|
goto FreeDtb;
|
2017-03-27 11:57:31 +02:00
|
|
|
}
|
|
|
|
} 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 ();
|
2017-03-29 13:05:01 +02:00
|
|
|
|
|
|
|
FreeDtb:
|
|
|
|
if (Dtb != NULL) {
|
|
|
|
FreePool (Dtb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
2017-03-27 11:57:31 +02:00
|
|
|
}
|