Re: [edk2-devel] [PATCH v6 30/36] OvmfPkg/LoongArchVirt: Add NorFlashQemuLib

2024-01-09 Thread maobibo




On 2024/1/5 下午5:46, Chao Li wrote:

Add NorFlashQemuLib for LoongArch, it is referenced from ArmVirtPkg.

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584

Cc: Ard Biesheuvel 
Cc: Jiewen Yao 
Cc: Jordan Justen 
Cc: Gerd Hoffmann 
Cc: Bibo Mao 
Cc: Dongyan Qian 
Signed-off-by: Chao Li 
Co-authored-by: Xianglai Li 
Co-authored-by: Bibo Mao 
---
  .../Library/NorFlashQemuLib/NorFlashQemuLib.c | 140 ++
  .../NorFlashQemuLib/NorFlashQemuLib.inf   |  43 ++
  2 files changed, 183 insertions(+)
  create mode 100644 
OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.c
  create mode 100644 
OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.inf

diff --git a/OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.c 
b/OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.c
new file mode 100644
index 00..ae9af09c4c
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.c
@@ -0,0 +1,140 @@
+/** @file
+
+  Copyright (c) 2024 Loongson Technology Corporation Limited. All rights 
reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define QEMU_NOR_BLOCK_SIZE  SIZE_128KB
+
+EFI_STATUS
+VirtNorFlashPlatformInitialization (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+STATIC VIRT_NOR_FLASH_DESCRIPTION  mNorFlashDevices;
+
+EFI_STATUS
+VirtNorFlashPlatformGetDevices (
+  OUT VIRT_NOR_FLASH_DESCRIPTION  **NorFlashDescriptions,
+  OUT UINT32  *Count
+  )
+{
+  FDT_CLIENT_PROTOCOL  *FdtClient;
+  INT32Node;
+  EFI_STATUS   Status;
+  EFI_STATUS   FindNodeStatus;
+  CONST UINT32 *Reg;
+  UINT32   PropSize;
+  UINT64   Base;
+  UINT64   Size;
+
+  Status = gBS->LocateProtocol (
+  &gFdtClientProtocolGuid,
+  NULL,
+  (VOID **)&FdtClient
+  );
+  ASSERT_EFI_ERROR (Status);
+
+  FindNodeStatus = FdtClient->FindCompatibleNode (
+FdtClient,
+"cfi-flash",
+&Node
+);
+  ASSERT_EFI_ERROR (FindNodeStatus);
+
+  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
+  ));
+return Status;
+  }
+
+  ASSERT ((PropSize % (4 * sizeof (UINT32))) == 0);
+
+  if (PropSize < (4 * sizeof (UINT32))) {
+DEBUG ((
+  DEBUG_ERROR,
+  "%a: reg node size(%d) is too small \n",
+  __func__,
+  PropSize
+  ));
+return EFI_NOT_FOUND;
+  }
+
+  Base = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[0]));
+  Size = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[2]));
+
+  mNorFlashDevices.DeviceBaseAddress = (UINTN)Base;
+  mNorFlashDevices.RegionBaseAddress = (UINTN)Base;
+  mNorFlashDevices.Size  = (UINTN)Size;
+  mNorFlashDevices.BlockSize = QEMU_NOR_BLOCK_SIZE;
+
+  Status = PcdSet32S (PcdFlashNvStorageVariableBase, Base);
+  ASSERT_EFI_ERROR (Status);
+
+  /*
+   * 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,Base is the value of PcdFlashNvStorageFtwWorkingBase,
+   * PcdFlashNvStorageFtwSpareBase can be got by
+   *   PcdFlashNvStorageFtwWorkingBase + PcdFlashNvStorageFtwWorkingSize.
+   */
+  Base  += PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+  Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, Base);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // 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

[edk2-devel] [PATCH v6 30/36] OvmfPkg/LoongArchVirt: Add NorFlashQemuLib

2024-01-05 Thread Chao Li
Add NorFlashQemuLib for LoongArch, it is referenced from ArmVirtPkg.

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584

Cc: Ard Biesheuvel 
Cc: Jiewen Yao 
Cc: Jordan Justen 
Cc: Gerd Hoffmann 
Cc: Bibo Mao 
Cc: Dongyan Qian 
Signed-off-by: Chao Li 
Co-authored-by: Xianglai Li 
Co-authored-by: Bibo Mao 
---
 .../Library/NorFlashQemuLib/NorFlashQemuLib.c | 140 ++
 .../NorFlashQemuLib/NorFlashQemuLib.inf   |  43 ++
 2 files changed, 183 insertions(+)
 create mode 100644 
OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.c
 create mode 100644 
OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.inf

diff --git a/OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.c 
b/OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.c
new file mode 100644
index 00..ae9af09c4c
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/NorFlashQemuLib/NorFlashQemuLib.c
@@ -0,0 +1,140 @@
+/** @file
+
+  Copyright (c) 2024 Loongson Technology Corporation Limited. All rights 
reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define QEMU_NOR_BLOCK_SIZE  SIZE_128KB
+
+EFI_STATUS
+VirtNorFlashPlatformInitialization (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+STATIC VIRT_NOR_FLASH_DESCRIPTION  mNorFlashDevices;
+
+EFI_STATUS
+VirtNorFlashPlatformGetDevices (
+  OUT VIRT_NOR_FLASH_DESCRIPTION  **NorFlashDescriptions,
+  OUT UINT32  *Count
+  )
+{
+  FDT_CLIENT_PROTOCOL  *FdtClient;
+  INT32Node;
+  EFI_STATUS   Status;
+  EFI_STATUS   FindNodeStatus;
+  CONST UINT32 *Reg;
+  UINT32   PropSize;
+  UINT64   Base;
+  UINT64   Size;
+
+  Status = gBS->LocateProtocol (
+  &gFdtClientProtocolGuid,
+  NULL,
+  (VOID **)&FdtClient
+  );
+  ASSERT_EFI_ERROR (Status);
+
+  FindNodeStatus = FdtClient->FindCompatibleNode (
+FdtClient,
+"cfi-flash",
+&Node
+);
+  ASSERT_EFI_ERROR (FindNodeStatus);
+
+  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
+  ));
+return Status;
+  }
+
+  ASSERT ((PropSize % (4 * sizeof (UINT32))) == 0);
+
+  if (PropSize < (4 * sizeof (UINT32))) {
+DEBUG ((
+  DEBUG_ERROR,
+  "%a: reg node size(%d) is too small \n",
+  __func__,
+  PropSize
+  ));
+return EFI_NOT_FOUND;
+  }
+
+  Base = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[0]));
+  Size = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[2]));
+
+  mNorFlashDevices.DeviceBaseAddress = (UINTN)Base;
+  mNorFlashDevices.RegionBaseAddress = (UINTN)Base;
+  mNorFlashDevices.Size  = (UINTN)Size;
+  mNorFlashDevices.BlockSize = QEMU_NOR_BLOCK_SIZE;
+
+  Status = PcdSet32S (PcdFlashNvStorageVariableBase, Base);
+  ASSERT_EFI_ERROR (Status);
+
+  /*
+   * 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,Base is the value of PcdFlashNvStorageFtwWorkingBase,
+   * PcdFlashNvStorageFtwSpareBase can be got by
+   *   PcdFlashNvStorageFtwWorkingBase + PcdFlashNvStorageFtwWorkingSize.
+   */
+  Base  += PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+  Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, Base);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // 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"));
+  }
+
+  *NorFlashDescr