/** @file * * Copyright (c) 2017, Linaro, Ltd. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * **/ #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_SUCCESS 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; Status = DtPlatformLoadDtb (&Dtb, &DtbSize); if (EFI_ERROR (Status)) { DEBUG (( DEBUG_WARN, "%a: no DTB blob could be loaded, defaulting to ACPI (Status == %r)\n", __func__, Status )); 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 %a\n", __func__, PcdGetBool (PcdDefaultDtPref) ? "DT" : "ACPI" )); DtAcpiPref.Pref = PcdGetBool (PcdDefaultDtPref) ? DT_ACPI_SELECT_DT : DT_ACPI_SELECT_ACPI; } } 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 %a\n", __func__, DT_ACPI_VARIABLE_NAME, PcdGetBool (PcdDefaultDtPref) ? "DT" : "ACPI" )); DtAcpiPref.Pref = PcdGetBool (PcdDefaultDtPref) ? DT_ACPI_SELECT_DT : DT_ACPI_SELECT_ACPI; 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)) { goto FreeDtb; } } 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", __func__ )); goto FreeDtb; } } 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. // Status = gBS->InstallConfigurationTable (&gFdtTableGuid, Dtb); if (EFI_ERROR (Status)) { DEBUG (( DEBUG_ERROR, "%a: failed to install FDT configuration table\n", __func__ )); goto FreeDtb; } } 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 (); FreeDtb: if (Dtb != NULL) { FreePool (Dtb); } return Status; }