Skip to content

Commit

Permalink
OvmfPkg: Add no hardcode version of FdtNorFlashQemuLib
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Leif Lindholm <[email protected]>
Cc: Sami Mujawar <[email protected]>
Cc: Gerd Hoffmann <[email protected]>
Cc: Jiewen Yao <[email protected]>
Signed-off-by: Chao Li <[email protected]>
Co-authored-by: Xianglai Li <[email protected]>
Tested-by: Gerd Hoffmann <[email protected]>
Acked-by: Gerd Hoffmann <[email protected]>
  • Loading branch information
2 people authored and mergify[bot] committed Jun 4, 2024
1 parent de4cc40 commit cac1ea6
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 0 deletions.
165 changes: 165 additions & 0 deletions OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.c
Original file line number Diff line number Diff line change
@@ -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;
}
46 changes: 46 additions & 0 deletions OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit cac1ea6

Please sign in to comment.