|
@@ -0,0 +1,116 @@
|
|
|
+/** @file
|
|
|
+ RISC-V Flattened Device Tree DXE module
|
|
|
+
|
|
|
+ The Linux booting protocol on RISC-V requires the id of the booting hart to
|
|
|
+ be passed as a0. Therefore the EFISTUB needs to get this information. Because
|
|
|
+ it runs in S-Mode, it cannot get this information from mhartid. Instead we
|
|
|
+ insert the id into the device tree, that the EFIFSTUB can read from the config table.
|
|
|
+
|
|
|
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
|
|
|
+
|
|
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
+**/
|
|
|
+
|
|
|
+#include <Library/UefiBootServicesTableLib.h>
|
|
|
+#include <Library/DebugLib.h>
|
|
|
+#include <Library/HobLib.h>
|
|
|
+#include <Library/BaseMemoryLib.h>
|
|
|
+#include <Library/PcdLib.h>
|
|
|
+#include <libfdt.h>
|
|
|
+
|
|
|
+/**
|
|
|
+ Fix up the device tree with booting hartid for the kernel
|
|
|
+
|
|
|
+ @param DtbBlob The device tree. Is extended to fit the hart id.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The device tree was success fixed up with the hart id.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+FixDtb (
|
|
|
+ IN OUT VOID *DtbBlob,
|
|
|
+ IN UINTN BootingHartId
|
|
|
+ )
|
|
|
+{
|
|
|
+ fdt32_t Size;
|
|
|
+ UINT32 ChosenOffset, Err;
|
|
|
+
|
|
|
+ DEBUG ((DEBUG_INFO, "Fixing up device tree with boot hart id: %d\n",
|
|
|
+ BootingHartId));
|
|
|
+
|
|
|
+ Size = fdt_totalsize(DtbBlob);
|
|
|
+ Err = fdt_open_into(DtbBlob, DtbBlob, Size + 32);
|
|
|
+ if (Err < 0) {
|
|
|
+ DEBUG ((DEBUG_ERROR,
|
|
|
+ "Device Tree can't be expanded to accommodate new node\n", __FUNCTION__));
|
|
|
+ return EFI_OUT_OF_RESOURCES;
|
|
|
+ }
|
|
|
+ ChosenOffset = fdt_path_offset(DtbBlob, "/chosen");
|
|
|
+ fdt_setprop_u32(DtbBlob, ChosenOffset, "boot-hartid", BootingHartId);
|
|
|
+
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Install the FDT passed in HOB into EFI system configuration table.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Successfully installed fixed up FDT in config table.
|
|
|
+ @retval EFI_NOT_FOUND Did not find FDT HOB.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+InstallFdtFromHob (VOID)
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_HOB_GUID_TYPE *GuidHob;
|
|
|
+ VOID *DataInHob;
|
|
|
+ UINTN DataSize;
|
|
|
+
|
|
|
+ GuidHob = GetFirstGuidHob (&gFdtHobGuid);
|
|
|
+ if (GuidHob == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "Failed to find RISC-V DTB Hob\n",
|
|
|
+ __FUNCTION__));
|
|
|
+ return EFI_NOT_FOUND;
|
|
|
+ }
|
|
|
+ DataInHob = (VOID *) *((UINTN *) GET_GUID_HOB_DATA (GuidHob));
|
|
|
+ DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
|
|
|
+
|
|
|
+ Status = FixDtb (DataInHob, PcdGet32(PcdBootHartId));
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DataInHob);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: failed to install FDT configuration table\n",
|
|
|
+ __FUNCTION__));
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Install the FDT from the HOB into the EFI system configuration table.
|
|
|
+
|
|
|
+ @param ImageHandle Image handle of this driver.
|
|
|
+ @param SystemTable Pointer to the System Table.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS FDT successfully installed into config table.
|
|
|
+ @retval EFI_NOT_FOUND Did not find FDT HOB.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+InstallFdt (
|
|
|
+ IN EFI_HANDLE ImageHandle,
|
|
|
+ IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+
|
|
|
+ Status = InstallFdtFromHob ();
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|