/** @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; 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", __FUNCTION__, 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 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)) { 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", __FUNCTION__)); 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", __FUNCTION__)); 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; }