summaryrefslogtreecommitdiff
path: root/OvmfPkg
diff options
context:
space:
mode:
authorChao Li <lichao@loongson.cn>2024-05-06 11:13:41 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-06-04 22:51:09 +0000
commitcac1ea6c2a6eac1772556e718154a00fcb093b88 (patch)
tree8c2b228db35acfe00fdb65690e0b5419a973deb0 /OvmfPkg
parentde4cc40b8c1d9044df82e077e72ef6e192ea12e2 (diff)
downloadedk2-cac1ea6c2a6eac1772556e718154a00fcb093b88.zip
edk2-cac1ea6c2a6eac1772556e718154a00fcb093b88.tar.gz
edk2-cac1ea6c2a6eac1772556e718154a00fcb093b88.tar.bz2
OvmfPkg: Add no hardcode version of FdtNorFlashQemuLib
This library is copied from ArmVirtPkg, in the Arm version, the value of PcdFlashNvStorageVariableBase, PcdFlashNvStorageFtwWorkingBase and PcdFlashNvStorageFtwSpareBase are hardcoded in INC file. This version will calculate them from FDT resource and using the set PCD to store when the NorFlashInitialise is called. By default, the first available flash(not used for storage UEFI code) as NV variable storage medium. In this way, UEFI can better handle the change of flash base address, which is suitable for different cpu architecture board implementation. BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4770 Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Leif Lindholm <quic_llindhol@quicinc.com> Cc: Sami Mujawar <sami.mujawar@arm.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Chao Li <lichao@loongson.cn> Co-authored-by: Xianglai Li <lixianglai@loongson.cn> Tested-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'OvmfPkg')
-rw-r--r--OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.c165
-rw-r--r--OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf46
2 files changed, 211 insertions, 0 deletions
diff --git a/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.c b/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.c
new file mode 100644
index 0000000..e5c7d4c
--- /dev/null
+++ b/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.c
@@ -0,0 +1,165 @@
+/** @file
+
+ Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/VirtNorFlashPlatformLib.h>
+
+#include <Protocol/FdtClient.h>
+#include <stdbool.h>
+
+#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
+#define MAX_FLASH_BANKS 4
+
+STATIC VIRT_NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
+
+EFI_STATUS
+VirtNorFlashPlatformInitialization (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VirtNorFlashPlatformGetDevices (
+ OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
+ OUT UINT32 *Count
+ )
+{
+ FDT_CLIENT_PROTOCOL *FdtClient;
+ INT32 Node;
+ EFI_STATUS Status;
+ EFI_STATUS FindNodeStatus;
+ CONST UINT32 *Reg;
+ UINT32 PropSize;
+ UINT32 Num;
+ UINT64 Base;
+ UINT64 Size;
+ BOOLEAN Found;
+
+ Status = gBS->LocateProtocol (
+ &gFdtClientProtocolGuid,
+ NULL,
+ (VOID **)&FdtClient
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Num = 0;
+ Found = FALSE;
+ for (FindNodeStatus = FdtClient->FindCompatibleNode (
+ FdtClient,
+ "cfi-flash",
+ &Node
+ );
+ !EFI_ERROR (FindNodeStatus) && Num < MAX_FLASH_BANKS;
+ FindNodeStatus = FdtClient->FindNextCompatibleNode (
+ FdtClient,
+ "cfi-flash",
+ Node,
+ &Node
+ ))
+ {
+ Status = FdtClient->GetNodeProperty (
+ FdtClient,
+ Node,
+ "reg",
+ (CONST VOID **)&Reg,
+ &PropSize
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: GetNodeProperty () failed (Status == %r)\n",
+ __func__,
+ Status
+ ));
+ continue;
+ }
+
+ ASSERT ((PropSize % (4 * sizeof (UINT32))) == 0);
+
+ while (PropSize >= (4 * sizeof (UINT32)) && Num < MAX_FLASH_BANKS) {
+ Base = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[0]));
+ Size = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[2]));
+ Reg += 4;
+
+ PropSize -= 4 * sizeof (UINT32);
+
+ //
+ // Disregard any flash devices that overlap with the primary FV.
+ // The firmware is not updatable from inside the guest anyway.
+ //
+ if ((PcdGet32 (PcdOvmfFdBaseAddress) + PcdGet32 (PcdOvmfFirmwareFdSize) > Base) &&
+ ((Base + Size) > PcdGet32 (PcdOvmfFdBaseAddress)))
+ {
+ continue;
+ }
+
+ mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base;
+ mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base;
+ mNorFlashDevices[Num].Size = (UINTN)Size;
+ mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE;
+ Num++;
+ if (!Found) {
+ //
+ // By default, the second available flash is stored as a non-volatile variable.
+ //
+ Status = PcdSet32S (PcdFlashNvStorageVariableBase, Base);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // The Base is the value of PcdFlashNvStorageVariableBase,
+ // PcdFlashNvStorageFtwWorkingBase can be got by
+ // PcdFlashNvStorageVariableBase + PcdFlashNvStorageVariableSize
+ //
+ Base += PcdGet32 (PcdFlashNvStorageVariableSize);
+ Status = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, Base);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Now, the Base is the value of PcdFlashNvStorageFtwWorkingBase,
+ // PcdFlashNvStorageFtwSpareBase can be got by
+ // PcdFlashNvStorageFtwWorkingBase + PcdFlashNvStorageFtwWorkingSize.
+ //
+ Base += PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+ Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, Base);
+ ASSERT_EFI_ERROR (Status);
+ Found = TRUE;
+ }
+ }
+
+ //
+ // UEFI takes ownership of the NOR flash, and exposes its functionality
+ // through the UEFI Runtime Services GetVariable, SetVariable, etc. This
+ // means we need to disable it in the device tree to prevent the OS from
+ // attaching its device driver as well.
+ // Note that this also hides other flash banks, but the only other flash
+ // bank we expect to encounter is the one that carries the UEFI executable
+ // code, which is not intended to be guest updatable, and is usually backed
+ // in a readonly manner by QEMU anyway.
+ //
+ Status = FdtClient->SetNodeProperty (
+ FdtClient,
+ Node,
+ "status",
+ "disabled",
+ sizeof ("disabled")
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "Failed to set NOR flash status to 'disabled'\n"));
+ }
+ }
+
+ *NorFlashDescriptions = mNorFlashDevices;
+ *Count = Num;
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf b/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf
new file mode 100644
index 0000000..14ddb4c
--- /dev/null
+++ b/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf
@@ -0,0 +1,46 @@
+## @file
+#
+# Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
+# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = NorFlashQemuLib
+ FILE_GUID = E225C90F-6CB9-8AF3-095B-2668FC633A57
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NorFlashQemuLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+[Sources]
+ FdtNorFlashQemuLib.c
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gFdtClientProtocolGuid ## CONSUMES
+
+[Depex]
+ gFdtClientProtocolGuid
+
+[Pcd]
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase