* [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine
@ 2022-10-10 10:11 Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 01/29] MdePkg/Register: Add register definition header files for RISC-V Sunil V L
` (28 more replies)
0 siblings, 29 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Abner Chang, Daniel Schaefer, Michael D Kinney, Liming Gao,
Zhiguang Liu, Ard Biesheuvel, Jiewen Yao, Jordan Justen,
Gerd Hoffmann, Rebecca Cran, Peter Grehan, Brijesh Singh,
Erdem Aktas, James Bottomley, Min Xu, Tom Lendacky, Eric Dong,
Ray Ni, Rahul Kumar, Leif Lindholm, Sami Mujawar, Andrew Fish,
Anup Patel
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Add support for RISC-V qemu virt machine. Most of the changes are migrated from
edk2-platforms repo and followed the latest guidelines for EDK2 code structuring.
The changes at a high level are,
1) MdePkg:
- Add RISC-V register definitions
- Add RISCV_EFI_BOOT_PROTOCOL related definitions
- Add BaseRiscVSbiLib library to make ecall to machine mode firmware
2) UefiCpuPkg:
- Refactor modules/libraries as per latest guidelines
- Add RISC-V support in below modules/libraries.
- CpuTimerLib, CpuExceptionHandlerLib, CpuDxe
- Add new CpuTimerDxe module
3) ArmVirtPkg:
- Migrate below libraries/modules to OvmfPkg
- PlatformBootManagerLib, PlatformHasAcpiDtDxe
- Fix up the consumers of these modules
4) OvmfPkg:
- Refactor the libraries/modules as per latest guidelines
- Add RISC-V support for below libraries/modules.
- Sec, ResetSystemLib, PlatformInitLib, PlatformPei
- Add NorFlashDxe driver and NorFlashQemuLib (Copied from ARM)
- Add new DSC/FDF files to build for RISC-V virt machine
The changes are tested on risc-v qemu with an additional patch series to
enable pflash available at https://github.com/vlsunil/qemu/tree/pflash_v3
Cc: Abner Chang <abner.chang@amd.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Rebecca Cran <rebecca@bsdio.com>
Cc: Peter Grehan <grehan@freebsd.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Anup Patel <apatel@ventanamicro.com>
Sunil V L (29):
MdePkg/Register: Add register definition header files for RISC-V
MdePkg: Add RISCV_EFI_BOOT_PROTOCOL related definitions
MdePkg/BaseLib: RISC-V: Add few more helper functions
MdePkg: Add BaseRiscVSbiLib Library for RISC-V
OvmfPkg/PlatformInitLib: Refactor to allow other architectures
OvmfPkg/PlatformInitLib: Add support for RISC-V
OvmfPkg/ResetSystemLib: Refactor to allow other architectures.
OvmfPkg/ResetSystemLib: Add support for RISC-V
OvmfPkg/Sec: Refactor to allow other architectures
OvmfPkg/Sec: Add RISC-V support
OvmfPkg/PlatformPei: Refactor to allow other architectures
OvmfPkg/PlatformPei: Add support for RISC-V
UefiCpuPkg/CpuTimerLib: Refactor to allow other architectures
UefiCpuPkg/CpuTimerLib: Add support for RISC-V
UefiCpuPkg/CpuExceptionHandlerLib: Refactor to allow other
architectures
UefiCpuPkg/CpuExceptionHandlerLib: Add support for RISC-V
UefiCpuPkg/CpuDxe: Refactor to allow other architectures
UefiCpuPkg/CpuDxe: Add support for RISC-V
UefiCpuPkg/CpuDxe: Add RISC-V Boot protocol support
UefiCpuPkg: Add CpuTimerDxe module
ArmVirtPkg/PlatformHasAcpiDtDxe: Move to OvmfPkg
ArmVirtPkg: Fix up the location of PlatformHasAcpiDtDxe
ArmVirtPkg/PlatformBootManagerLib: Move to OvmfPkg
ArmVirtPkg: Fix up the paths to PlatformBootManagerLib
OvmfPkg: Add NorFlashQemuLib library
OvmfPkg: Add generic Qemu NOR flash DXE driver
OvmfPkg: RiscVVirt: Add Qemu Virt platform support
Maintainers.txt: Add entry for OvmfPkg/RiscVVirt
UefiCpuPkg/UefiCpuPkg.ci.yaml: Ignore RISC-V file
ArmVirtPkg/ArmVirtPkg.dec | 9 -
MdePkg/MdePkg.dec | 10 +
OvmfPkg/OvmfPkg.dec | 22 +
ArmVirtPkg/ArmVirtCloudHv.dsc | 2 +-
ArmVirtPkg/ArmVirtQemu.dsc | 8 +-
ArmVirtPkg/ArmVirtQemuKernel.dsc | 6 +-
MdePkg/MdePkg.dsc | 3 +
OvmfPkg/Platforms/RiscVVirt/RiscVVirt.dsc | 726 +++++++++++++
UefiCpuPkg/UefiCpuPkg.dsc | 15 +-
OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf | 406 ++++++++
.../CloudHvHasAcpiDtDxe.inf | 2 +-
.../KvmtoolPlatformDxe/KvmtoolPlatformDxe.inf | 2 +-
MdePkg/Library/BaseLib/BaseLib.inf | 2 +
.../BaseRiscVSbiLib/BaseRiscVSbiLib.inf | 25 +
OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf | 69 ++
.../NorFlashQemuLib/NorFlashQemuLib.inf | 40 +
.../NorFlashQemuUnifiedLib.inf | 30 +
.../PlatformBootManagerLib.inf | 3 +-
.../PlatformInitLib/PlatformInitLib.inf | 31 +-
.../ResetSystemLib/BaseResetSystemLib.inf | 12 +-
.../BaseResetSystemLibBhyve.inf | 4 +-
.../BaseResetSystemLibMicrovm.inf | 2 +-
.../ResetSystemLib/DxeResetSystemLib.inf | 15 +-
.../PlatformHasAcpiDtDxe.inf | 3 +-
OvmfPkg/PlatformPei/PlatformPei.inf | 43 +-
OvmfPkg/Sec/SecMain.inf | 34 +-
UefiCpuPkg/CpuDxe/CpuDxe.inf | 39 +-
UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf | 51 +
.../DxeCpuExceptionHandlerLib.inf | 21 +-
.../PeiCpuExceptionHandlerLib.inf | 8 +-
.../SecPeiCpuExceptionHandlerLib.inf | 19 +-
.../SmmCpuExceptionHandlerLib.inf | 8 +-
.../Xcode5SecPeiCpuExceptionHandlerLib.inf | 6 +-
.../Library/CpuTimerLib/BaseCpuTimerLib.inf | 9 +-
MdePkg/Include/Library/BaseLib.h | 50 +
MdePkg/Include/Library/BaseRiscVSbiLib.h | 127 +++
MdePkg/Include/Protocol/RiscVBootProtocol.h | 32 +
.../Include/Register/RiscV64/RiscVEncoding.h | 124 +++
MdePkg/Include/Register/RiscV64/RiscVImpl.h | 24 +
OvmfPkg/Drivers/NorFlashDxe/NorFlash.h | 422 ++++++++
OvmfPkg/Include/Library/NorFlashPlatformLib.h | 30 +
OvmfPkg/Include/Library/PlatformInitLib.h | 6 +
.../PlatformBootManagerLibVirt}/PlatformBm.h | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/Platform.h | 0
OvmfPkg/PlatformPei/RiscV64/Platform.h | 97 ++
OvmfPkg/Sec/{ => Ia32_X64}/AmdSev.h | 0
OvmfPkg/Sec/RiscV64/SecMain.h | 65 ++
OvmfPkg/Sec/SecMainCommon.h | 73 ++
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuDxe.h | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuGdt.h | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuMp.h | 0
.../CpuDxe/{ => Ia32_X64}/CpuPageTable.h | 0
UefiCpuPkg/CpuDxe/{ => RiscV64}/CpuDxe.h | 122 +--
UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.h | 177 ++++
.../{ => Ia32_X64}/CpuExceptionCommon.h | 0
.../RiscV64/CpuExceptionHandlerLib.h | 116 +++
.../Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c | 227 ++++
OvmfPkg/Drivers/NorFlashDxe/NorFlash.c | 972 ++++++++++++++++++
.../Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | 123 +++
OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c | 506 +++++++++
OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c | 777 ++++++++++++++
.../Library/NorFlashQemuLib/NorFlashQemuLib.c | 136 +++
.../NorFlashQemuLib/NorFlashQemuUnifiedLib.c | 40 +
.../PlatformBootManagerLibVirt}/PlatformBm.c | 0
.../PlatformBootManagerLibVirt}/QemuKernel.c | 0
.../PlatformInitLib/{ => Ia32_X64}/Cmos.c | 0
.../PlatformInitLib/{ => Ia32_X64}/IntelTdx.c | 0
.../{ => Ia32_X64}/IntelTdxNull.c | 0
.../{ => Ia32_X64}/MemDetect.c | 0
.../PlatformInitLib/{ => Ia32_X64}/Platform.c | 0
.../PlatformInitLib/RiscV64/PlatformPeiLib.c | 73 ++
.../{ => Ia32_X64}/BaseResetShutdown.c | 0
.../{ => Ia32_X64}/BaseResetShutdownBhyve.c | 0
.../{ => Ia32_X64}/DxeResetShutdown.c | 0
.../{ => Ia32_X64}/DxeResetSystemLibMicrovm.c | 0
.../{ => Ia32_X64}/ResetSystemLib.c | 0
.../{ => Ia32_X64}/ResetSystemLibMicrovm.c | 0
.../ResetSystemLib/RiscV64/DxeResetShutdown.c | 20 +
.../ResetSystemLib/RiscV64/ResetSystemLib.c | 128 +++
.../PlatformHasAcpiDtDxe.c | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/AmdSev.c | 0
.../PlatformPei/{ => Ia32_X64}/ClearCache.c | 0
.../{ => Ia32_X64}/FeatureControl.c | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/Fv.c | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/IntelTdx.c | 0
.../PlatformPei/{ => Ia32_X64}/MemDetect.c | 0
.../PlatformPei/{ => Ia32_X64}/MemTypeInfo.c | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/Platform.c | 0
OvmfPkg/PlatformPei/{ => RiscV64}/Fv.c | 43 +-
OvmfPkg/PlatformPei/RiscV64/MemDetect.c | 212 ++++
OvmfPkg/PlatformPei/RiscV64/Platform.c | 372 +++++++
OvmfPkg/Sec/{ => Ia32_X64}/AmdSev.c | 0
OvmfPkg/Sec/{ => Ia32_X64}/SecMain.c | 227 +---
OvmfPkg/Sec/RiscV64/SecMain.c | 573 +++++++++++
OvmfPkg/Sec/SecMainCommon.c | 238 +++++
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuDxe.c | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuGdt.c | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuMp.c | 0
.../CpuDxe/{ => Ia32_X64}/CpuPageTable.c | 0
UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c | 365 +++++++
UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.c | 294 ++++++
.../{ => Ia32_X64}/CpuExceptionCommon.c | 0
.../{ => Ia32_X64}/DxeException.c | 0
.../{ => Ia32_X64}/PeiCpuException.c | 0
.../{ => Ia32_X64}/PeiDxeSmmCpuException.c | 0
.../{ => Ia32_X64}/SecPeiCpuException.c | 0
.../{ => Ia32_X64}/SmmException.c | 0
.../CpuExceptionHandlerLib.c} | 83 +-
.../{ => Ia32_X64}/BaseCpuTimerLib.c | 0
.../CpuTimerLib/{ => Ia32_X64}/CpuTimerLib.c | 0
.../Library/CpuTimerLib/RiscV64/CpuTimerLib.c | 199 ++++
ArmVirtPkg/ArmVirtPkg.ci.yaml | 1 -
ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc | 2 +-
Maintainers.txt | 4 +
MdePkg/Library/BaseLib/RiscV64/CpuScratch.S | 31 +
MdePkg/Library/BaseLib/RiscV64/ReadTimer.S | 24 +
.../Library/BaseLib/RiscV64/RiscVInterrupt.S | 53 +-
OvmfPkg/OvmfPkg.ci.yaml | 1 +
OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf.inc | 66 ++
OvmfPkg/Platforms/RiscVVirt/VarStore.fdf.inc | 79 ++
OvmfPkg/Sec/RiscV64/SecEntry.S | 23 +
UefiCpuPkg/CpuTimerDxe/CpuTimer.uni | 15 +
UefiCpuPkg/CpuTimerDxe/CpuTimerExtra.uni | 13 +
.../RiscV64/SupervisorTrapHandler.S | 105 ++
UefiCpuPkg/UefiCpuPkg.ci.yaml | 1 +
125 files changed, 8658 insertions(+), 518 deletions(-)
create mode 100644 OvmfPkg/Platforms/RiscVVirt/RiscVVirt.dsc
create mode 100644 OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf
create mode 100644 MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
rename {ArmVirtPkg/Library/PlatformBootManagerLib => OvmfPkg/Library/PlatformBootManagerLibVirt}/PlatformBootManagerLib.inf (92%)
rename {ArmVirtPkg => OvmfPkg}/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf (89%)
create mode 100644 UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf
create mode 100644 MdePkg/Include/Library/BaseRiscVSbiLib.h
create mode 100644 MdePkg/Include/Protocol/RiscVBootProtocol.h
create mode 100644 MdePkg/Include/Register/RiscV64/RiscVEncoding.h
create mode 100644 MdePkg/Include/Register/RiscV64/RiscVImpl.h
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
create mode 100644 OvmfPkg/Include/Library/NorFlashPlatformLib.h
rename {ArmVirtPkg/Library/PlatformBootManagerLib => OvmfPkg/Library/PlatformBootManagerLibVirt}/PlatformBm.h (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/Platform.h (100%)
create mode 100644 OvmfPkg/PlatformPei/RiscV64/Platform.h
rename OvmfPkg/Sec/{ => Ia32_X64}/AmdSev.h (100%)
create mode 100644 OvmfPkg/Sec/RiscV64/SecMain.h
create mode 100644 OvmfPkg/Sec/SecMainCommon.h
copy UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuDxe.h (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuGdt.h (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuMp.h (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuPageTable.h (100%)
rename UefiCpuPkg/CpuDxe/{ => RiscV64}/CpuDxe.h (69%)
create mode 100644 UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.h
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/CpuExceptionCommon.h (100%)
create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.h
create mode 100644 MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
rename {ArmVirtPkg/Library/PlatformBootManagerLib => OvmfPkg/Library/PlatformBootManagerLibVirt}/PlatformBm.c (100%)
rename {ArmVirtPkg/Library/PlatformBootManagerLib => OvmfPkg/Library/PlatformBootManagerLibVirt}/QemuKernel.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/Cmos.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/IntelTdx.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/IntelTdxNull.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/MemDetect.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/Platform.c (100%)
create mode 100644 OvmfPkg/Library/PlatformInitLib/RiscV64/PlatformPeiLib.c
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/BaseResetShutdown.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/BaseResetShutdownBhyve.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/DxeResetShutdown.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/DxeResetSystemLibMicrovm.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/ResetSystemLib.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/ResetSystemLibMicrovm.c (100%)
create mode 100644 OvmfPkg/Library/ResetSystemLib/RiscV64/DxeResetShutdown.c
create mode 100644 OvmfPkg/Library/ResetSystemLib/RiscV64/ResetSystemLib.c
rename {ArmVirtPkg => OvmfPkg}/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/AmdSev.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/ClearCache.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/FeatureControl.c (100%)
copy OvmfPkg/PlatformPei/{ => Ia32_X64}/Fv.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/IntelTdx.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/MemDetect.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/MemTypeInfo.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/Platform.c (100%)
rename OvmfPkg/PlatformPei/{ => RiscV64}/Fv.c (63%)
create mode 100644 OvmfPkg/PlatformPei/RiscV64/MemDetect.c
create mode 100644 OvmfPkg/PlatformPei/RiscV64/Platform.c
rename OvmfPkg/Sec/{ => Ia32_X64}/AmdSev.c (100%)
rename OvmfPkg/Sec/{ => Ia32_X64}/SecMain.c (75%)
create mode 100644 OvmfPkg/Sec/RiscV64/SecMain.c
create mode 100644 OvmfPkg/Sec/SecMainCommon.c
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuDxe.c (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuGdt.c (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuMp.c (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuPageTable.c (100%)
create mode 100644 UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c
create mode 100644 UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.c
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/CpuExceptionCommon.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/DxeException.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/PeiCpuException.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/PeiDxeSmmCpuException.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/SecPeiCpuException.c (100%)
copy UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/SmmException.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{SmmException.c => RiscV64/CpuExceptionHandlerLib.c} (67%)
rename UefiCpuPkg/Library/CpuTimerLib/{ => Ia32_X64}/BaseCpuTimerLib.c (100%)
rename UefiCpuPkg/Library/CpuTimerLib/{ => Ia32_X64}/CpuTimerLib.c (100%)
create mode 100644 UefiCpuPkg/Library/CpuTimerLib/RiscV64/CpuTimerLib.c
create mode 100644 MdePkg/Library/BaseLib/RiscV64/CpuScratch.S
create mode 100644 MdePkg/Library/BaseLib/RiscV64/ReadTimer.S
create mode 100644 OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf.inc
create mode 100644 OvmfPkg/Platforms/RiscVVirt/VarStore.fdf.inc
create mode 100644 OvmfPkg/Sec/RiscV64/SecEntry.S
create mode 100644 UefiCpuPkg/CpuTimerDxe/CpuTimer.uni
create mode 100644 UefiCpuPkg/CpuTimerDxe/CpuTimerExtra.uni
create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/SupervisorTrapHandler.S
--
2.25.1
^ permalink raw reply [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 01/29] MdePkg/Register: Add register definition header files for RISC-V
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 02/29] MdePkg: Add RISCV_EFI_BOOT_PROTOCOL related definitions Sunil V L
` (27 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Daniel Schaefer, Michael D Kinney, Liming Gao, Zhiguang Liu
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Add register definitions and access routines for RISC-V. These
headers are leveraged from opensbi repo.
Cc: Daniel Schaefer <git@danielschaefer.me>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
.../Include/Register/RiscV64/RiscVEncoding.h | 124 ++++++++++++++++++
MdePkg/Include/Register/RiscV64/RiscVImpl.h | 24 ++++
2 files changed, 148 insertions(+)
create mode 100644 MdePkg/Include/Register/RiscV64/RiscVEncoding.h
create mode 100644 MdePkg/Include/Register/RiscV64/RiscVImpl.h
diff --git a/MdePkg/Include/Register/RiscV64/RiscVEncoding.h b/MdePkg/Include/Register/RiscV64/RiscVEncoding.h
new file mode 100644
index 000000000000..c98c36ac4cde
--- /dev/null
+++ b/MdePkg/Include/Register/RiscV64/RiscVEncoding.h
@@ -0,0 +1,124 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates. All rights reserved.<BR>
+ * Copyright (c) 2022 Ventana Micro Systems Inc. All rights reserved.<BR>
+ *
+ */
+
+#ifndef __RISCV_ENCODING_H__
+#define __RISCV_ENCODING_H__
+
+/* clang-format off */
+#define MSTATUS_SIE 0x00000002UL
+#define MSTATUS_MIE 0x00000008UL
+#define MSTATUS_SPIE_SHIFT 5
+#define MSTATUS_SPIE (1UL << MSTATUS_SPIE_SHIFT)
+#define MSTATUS_UBE 0x00000040UL
+#define MSTATUS_MPIE 0x00000080UL
+#define MSTATUS_SPP_SHIFT 8
+#define MSTATUS_SPP (1UL << MSTATUS_SPP_SHIFT)
+#define MSTATUS_MPP_SHIFT 11
+#define MSTATUS_MPP (3UL << MSTATUS_MPP_SHIFT)
+
+#define SSTATUS_SIE MSTATUS_SIE
+#define SSTATUS_SPIE_SHIFT MSTATUS_SPIE_SHIFT
+#define SSTATUS_SPIE MSTATUS_SPIE
+#define SSTATUS_SPP_SHIFT MSTATUS_SPP_SHIFT
+#define SSTATUS_SPP MSTATUS_SPP
+
+#define IRQ_S_SOFT 1
+#define IRQ_VS_SOFT 2
+#define IRQ_M_SOFT 3
+#define IRQ_S_TIMER 5
+#define IRQ_VS_TIMER 6
+#define IRQ_M_TIMER 7
+#define IRQ_S_EXT 9
+#define IRQ_VS_EXT 10
+#define IRQ_M_EXT 11
+#define IRQ_S_GEXT 12
+#define IRQ_PMU_OVF 13
+
+#define MIP_SSIP (1UL << IRQ_S_SOFT)
+#define MIP_VSSIP (1UL << IRQ_VS_SOFT)
+#define MIP_MSIP (1UL << IRQ_M_SOFT)
+#define MIP_STIP (1UL << IRQ_S_TIMER)
+#define MIP_VSTIP (1UL << IRQ_VS_TIMER)
+#define MIP_MTIP (1UL << IRQ_M_TIMER)
+#define MIP_SEIP (1UL << IRQ_S_EXT)
+#define MIP_VSEIP (1UL << IRQ_VS_EXT)
+#define MIP_MEIP (1UL << IRQ_M_EXT)
+#define MIP_SGEIP (1UL << IRQ_S_GEXT)
+#define MIP_LCOFIP (1UL << IRQ_PMU_OVF)
+
+#define SIP_SSIP MIP_SSIP
+#define SIP_STIP MIP_STIP
+
+#define PRV_U 0UL
+#define PRV_S 1UL
+#define PRV_M 3UL
+
+#define SATP64_MODE 0xF000000000000000ULL
+#define SATP64_ASID 0x0FFFF00000000000ULL
+#define SATP64_PPN 0x00000FFFFFFFFFFFULL
+
+#define SATP_MODE_OFF 0UL
+#define SATP_MODE_SV32 1UL
+#define SATP_MODE_SV39 8UL
+#define SATP_MODE_SV48 9UL
+#define SATP_MODE_SV57 10UL
+#define SATP_MODE_SV64 11UL
+
+#define SATP_MODE SATP64_MODE
+
+/* ===== User-level CSRs ===== */
+
+/* User Counters/Timers */
+#define CSR_CYCLE 0xc00
+#define CSR_TIME 0xc01
+
+/* ===== Supervisor-level CSRs ===== */
+
+/* Supervisor Trap Setup */
+#define CSR_SSTATUS 0x100
+#define CSR_SEDELEG 0x102
+#define CSR_SIDELEG 0x103
+#define CSR_SIE 0x104
+#define CSR_STVEC 0x105
+
+/* Supervisor Configuration */
+#define CSR_SENVCFG 0x10a
+
+/* Supervisor Trap Handling */
+#define CSR_SSCRATCH 0x140
+#define CSR_SEPC 0x141
+#define CSR_SCAUSE 0x142
+#define CSR_STVAL 0x143
+#define CSR_SIP 0x144
+
+/* Supervisor Protection and Translation */
+#define CSR_SATP 0x180
+
+/* ===== Trap/Exception Causes ===== */
+
+#define CAUSE_MISALIGNED_FETCH 0x0
+#define CAUSE_FETCH_ACCESS 0x1
+#define CAUSE_ILLEGAL_INSTRUCTION 0x2
+#define CAUSE_BREAKPOINT 0x3
+#define CAUSE_MISALIGNED_LOAD 0x4
+#define CAUSE_LOAD_ACCESS 0x5
+#define CAUSE_MISALIGNED_STORE 0x6
+#define CAUSE_STORE_ACCESS 0x7
+#define CAUSE_USER_ECALL 0x8
+#define CAUSE_SUPERVISOR_ECALL 0x9
+#define CAUSE_VIRTUAL_SUPERVISOR_ECALL 0xa
+#define CAUSE_MACHINE_ECALL 0xb
+#define CAUSE_FETCH_PAGE_FAULT 0xc
+#define CAUSE_LOAD_PAGE_FAULT 0xd
+#define CAUSE_STORE_PAGE_FAULT 0xf
+#define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14
+#define CAUSE_LOAD_GUEST_PAGE_FAULT 0x15
+#define CAUSE_VIRTUAL_INST_FAULT 0x16
+#define CAUSE_STORE_GUEST_PAGE_FAULT 0x17
+
+#endif
diff --git a/MdePkg/Include/Register/RiscV64/RiscVImpl.h b/MdePkg/Include/Register/RiscV64/RiscVImpl.h
new file mode 100644
index 000000000000..7dc100ecf510
--- /dev/null
+++ b/MdePkg/Include/Register/RiscV64/RiscVImpl.h
@@ -0,0 +1,24 @@
+/** @file
+ RISC-V package definitions.
+
+ Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Register/RiscV64/RiscVEncoding.h>
+
+#ifndef __RISCV_IMPL_H_
+#define __RISCV_IMPL_H_
+
+#define _ASM_FUNC(Name, Section) \
+ .global Name ; \
+ .section #Section, "ax" ; \
+ .type Name, %function ; \
+ .p2align 2 ; \
+ Name:
+
+#define ASM_FUNC(Name) _ASM_FUNC(ASM_PFX(Name), .text. ## Name)
+#define RISCV_TIMER_COMPARE_BITS 32
+
+#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 02/29] MdePkg: Add RISCV_EFI_BOOT_PROTOCOL related definitions
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 01/29] MdePkg/Register: Add register definition header files for RISC-V Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 03/29] MdePkg/BaseLib: RISC-V: Add few more helper functions Sunil V L
` (26 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Zhiguang Liu
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
RISC-V UEFI based platforms need to support RISCV_EFI_BOOT_PROTOCOL.
Add this protocol GUID definition and the header file required.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
MdePkg/MdePkg.dec | 6 ++++
MdePkg/Include/Protocol/RiscVBootProtocol.h | 32 +++++++++++++++++++++
2 files changed, 38 insertions(+)
create mode 100644 MdePkg/Include/Protocol/RiscVBootProtocol.h
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index f1ebf9e251c1..8f1bcfdc3e97 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -1915,6 +1915,12 @@ [Protocols]
## Include/Protocol/ShellDynamicCommand.h
gEfiShellDynamicCommandProtocolGuid = { 0x3c7200e9, 0x005f, 0x4ea4, {0x87, 0xde, 0xa3, 0xdf, 0xac, 0x8a, 0x27, 0xc3 }}
+ #
+ # Protocols defined for RISC-V systems
+ #
+ ## Include/Protocol/RiscVBootProtocol.h
+ gRiscVEfiBootProtocolGuid = { 0xccd15fec, 0x6f73, 0x4eec, { 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf }}
+
#
# [Error.gEfiMdePkgTokenSpaceGuid]
# 0x80000001 | Invalid value provided.
diff --git a/MdePkg/Include/Protocol/RiscVBootProtocol.h b/MdePkg/Include/Protocol/RiscVBootProtocol.h
new file mode 100644
index 000000000000..d0d40618b483
--- /dev/null
+++ b/MdePkg/Include/Protocol/RiscVBootProtocol.h
@@ -0,0 +1,32 @@
+/** @file
+ RISC-V Boot Protocol mandatory for RISC-V UEFI platforms.
+
+ Specification available at
+ https://github.com/riscv-non-isa/riscv-uefi
+
+ Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __RISCV_BOOT_PROTOCOL_H__
+#define __RISCV_BOOT_PROTOCOL_H__
+
+typedef struct _RISCV_EFI_BOOT_PROTOCOL RISCV_EFI_BOOT_PROTOCOL;
+
+#define RISCV_EFI_BOOT_PROTOCOL_REVISION 0x00010000
+#define RISCV_EFI_BOOT_PROTOCOL_LATEST_VERSION \
+ RISCV_EFI_BOOT_PROTOCOL_REVISION
+
+typedef EFI_STATUS
+(EFIAPI *EFI_GET_BOOT_HARTID)(
+ IN RISCV_EFI_BOOT_PROTOCOL *This,
+ OUT UINTN *BootHartId
+ );
+
+typedef struct _RISCV_EFI_BOOT_PROTOCOL {
+ UINT64 Revision;
+ EFI_GET_BOOT_HARTID GetBootHartId;
+} RISCV_EFI_BOOT_PROTOCOL;
+
+#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 03/29] MdePkg/BaseLib: RISC-V: Add few more helper functions
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 01/29] MdePkg/Register: Add register definition header files for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 02/29] MdePkg: Add RISCV_EFI_BOOT_PROTOCOL related definitions Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 04/29] MdePkg: Add BaseRiscVSbiLib Library for RISC-V Sunil V L
` (25 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Few of the basic helper functions required for any
RISC-V CPU were added in edk2-platforms. To support
qemu virt, they need to be added in BaseLib.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
MdePkg/Library/BaseLib/BaseLib.inf | 2 +
MdePkg/Include/Library/BaseLib.h | 50 +++++++++++++++++
MdePkg/Library/BaseLib/RiscV64/CpuScratch.S | 31 +++++++++++
MdePkg/Library/BaseLib/RiscV64/ReadTimer.S | 24 +++++++++
.../Library/BaseLib/RiscV64/RiscVInterrupt.S | 53 +++++++++++++++++--
5 files changed, 156 insertions(+), 4 deletions(-)
create mode 100644 MdePkg/Library/BaseLib/RiscV64/CpuScratch.S
create mode 100644 MdePkg/Library/BaseLib/RiscV64/ReadTimer.S
diff --git a/MdePkg/Library/BaseLib/BaseLib.inf b/MdePkg/Library/BaseLib/BaseLib.inf
index 6be5be9428f2..86d7bb080971 100644
--- a/MdePkg/Library/BaseLib/BaseLib.inf
+++ b/MdePkg/Library/BaseLib/BaseLib.inf
@@ -401,6 +401,8 @@ [Sources.RISCV64]
RiscV64/RiscVCpuPause.S | GCC
RiscV64/RiscVInterrupt.S | GCC
RiscV64/FlushCache.S | GCC
+ RiscV64/CpuScratch.S | GCC
+ RiscV64/ReadTimer.S | GCC
[Packages]
MdePkg/MdePkg.dec
diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h
index a6f9a194ef1c..9724b84eef89 100644
--- a/MdePkg/Include/Library/BaseLib.h
+++ b/MdePkg/Include/Library/BaseLib.h
@@ -150,6 +150,56 @@ typedef struct {
#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8
+VOID
+ RiscVSetSupervisorScratch (
+ UINT64
+ );
+
+UINT64
+RiscVGetSupervisorScratch (
+ VOID
+ );
+
+VOID
+ RiscVSetSupervisorStvec (
+ UINT64
+ );
+
+UINT64
+RiscVGetSupervisorStvec (
+ VOID
+ );
+
+UINT64
+RiscVGetSupervisorTrapCause (
+ VOID
+ );
+
+VOID
+ RiscVSetSupervisorAddressTranslationRegister (
+ UINT64
+ );
+
+UINT64
+RiscVReadTimer (
+ VOID
+ );
+
+VOID
+RiscVEnableTimerInterrupt (
+ VOID
+ );
+
+VOID
+RiscVDisableTimerInterrupt (
+ VOID
+ );
+
+VOID
+RiscVClearPendingTimerInterrupt (
+ VOID
+ );
+
#endif // defined (MDE_CPU_RISCV64)
//
diff --git a/MdePkg/Library/BaseLib/RiscV64/CpuScratch.S b/MdePkg/Library/BaseLib/RiscV64/CpuScratch.S
new file mode 100644
index 000000000000..dd7adc21eb07
--- /dev/null
+++ b/MdePkg/Library/BaseLib/RiscV64/CpuScratch.S
@@ -0,0 +1,31 @@
+//------------------------------------------------------------------------------
+//
+// CPU scratch register related functions for RISC-V
+//
+// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//------------------------------------------------------------------------------
+
+#include <Register/RiscV64/RiscVImpl.h>
+
+.data
+.align 3
+.section .text
+
+//
+// Set Supervisor mode scratch.
+// @param a0 : Value set to Supervisor mode scratch
+//
+ASM_FUNC (RiscVSetSupervisorScratch)
+ csrrw a1, CSR_SSCRATCH, a0
+ ret
+
+//
+// Get Supervisor mode scratch.
+// @retval a0 : Value in Supervisor mode scratch
+//
+ASM_FUNC (RiscVGetSupervisorScratch)
+ csrr a0, CSR_SSCRATCH
+ ret
diff --git a/MdePkg/Library/BaseLib/RiscV64/ReadTimer.S b/MdePkg/Library/BaseLib/RiscV64/ReadTimer.S
new file mode 100644
index 000000000000..bdddb67618ab
--- /dev/null
+++ b/MdePkg/Library/BaseLib/RiscV64/ReadTimer.S
@@ -0,0 +1,24 @@
+//------------------------------------------------------------------------------
+//
+// Read CPU timer
+//
+// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+// Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//------------------------------------------------------------------------------
+
+#include <Register/RiscV64/RiscVImpl.h>
+
+.data
+.align 3
+.section .text
+
+//
+// Read TIME CSR.
+// @retval a0 : 64-bit timer.
+//
+ASM_FUNC (RiscVReadTimer)
+ csrr a0, CSR_TIME
+ ret
diff --git a/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S b/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S
index 87b3468fc7fd..6a1b90a7e45c 100644
--- a/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S
+++ b/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S
@@ -8,13 +8,13 @@
//
//------------------------------------------------------------------------------
+#include <Register/RiscV64/RiscVImpl.h>
+
ASM_GLOBAL ASM_PFX(RiscVDisableSupervisorModeInterrupts)
ASM_GLOBAL ASM_PFX(RiscVEnableSupervisorModeInterrupt)
ASM_GLOBAL ASM_PFX(RiscVGetSupervisorModeInterrupts)
-#define SSTATUS_SIE 0x00000002
-#define CSR_SSTATUS 0x100
- #define SSTATUS_SPP_BIT_POSITION 8
+#define SSTATUS_SPP_BIT_POSITION 8
//
// This routine disables supervisor mode interrupt
@@ -53,11 +53,56 @@ InTrap:
ret
//
+// Set Supervisor mode trap vector.
+// @param a0 : Value set to Supervisor mode trap vector
+//
+ASM_FUNC (RiscVSetSupervisorStvec)
+ csrrw a1, CSR_STVEC, a0
+ ret
+
+//
+// Get Supervisor mode trap vector.
+// @retval a0 : Value in Supervisor mode trap vector
+//
+ASM_FUNC (RiscVGetSupervisorStvec)
+ csrr a0, CSR_STVEC
+ ret
+
+//
+// Get Supervisor trap cause CSR.
+//
+ASM_FUNC (RiscVGetSupervisorTrapCause)
+ csrrs a0, CSR_SCAUSE, 0
+ ret
+//
// This routine returns supervisor mode interrupt
// status.
//
-ASM_PFX(RiscVGetSupervisorModeInterrupts):
+ASM_FUNC (RiscVGetSupervisorModeInterrupts)
csrr a0, CSR_SSTATUS
andi a0, a0, SSTATUS_SIE
ret
+//
+// This routine disables supervisor mode timer interrupt
+//
+ASM_FUNC (RiscVDisableTimerInterrupt)
+ li a0, SIP_STIP
+ csrc CSR_SIE, a0
+ ret
+
+//
+// This routine enables supervisor mode timer interrupt
+//
+ASM_FUNC (RiscVEnableTimerInterrupt)
+ li a0, SIP_STIP
+ csrs CSR_SIE, a0
+ ret
+
+//
+// This routine clears pending supervisor mode timer interrupt
+//
+ASM_FUNC (RiscVClearPendingTimerInterrupt)
+ li a0, SIP_STIP
+ csrc CSR_SIP, a0
+ ret
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 04/29] MdePkg: Add BaseRiscVSbiLib Library for RISC-V
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (2 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 03/29] MdePkg/BaseLib: RISC-V: Add few more helper functions Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 05/29] OvmfPkg/PlatformInitLib: Refactor to allow other architectures Sunil V L
` (24 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Zhiguang Liu
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This library is required to make SBI ecalls from the S-mode EDK2.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
MdePkg/MdePkg.dec | 4 +
MdePkg/MdePkg.dsc | 3 +
.../BaseRiscVSbiLib/BaseRiscVSbiLib.inf | 25 ++
MdePkg/Include/Library/BaseRiscVSbiLib.h | 127 ++++++++++
.../Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c | 227 ++++++++++++++++++
5 files changed, 386 insertions(+)
create mode 100644 MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf
create mode 100644 MdePkg/Include/Library/BaseRiscVSbiLib.h
create mode 100644 MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 8f1bcfdc3e97..1762068ffad7 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -307,6 +307,10 @@ [LibraryClasses.IA32, LibraryClasses.X64]
## @libraryclass Provides function to support TDX processing.
TdxLib|Include/Library/TdxLib.h
+[LibraryClasses.RISCV64]
+ ## @libraryclass Provides function to make ecalls to SBI
+ BaseRiscVSbiLib|Include/Library/BaseRiscVSbiLib.h
+
[Guids]
#
# GUID defined in UEFI2.1/UEFI2.0/EFI1.1
diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index cc1ac196a931..fd08122f441d 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -188,4 +188,7 @@ [Components.ARM, Components.AARCH64]
MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf
MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+[Components.RISCV64]
+ MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf
+
[BuildOptions]
diff --git a/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf b/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf
new file mode 100644
index 000000000000..d03132bf01c1
--- /dev/null
+++ b/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf
@@ -0,0 +1,25 @@
+## @file
+# RISC-V Library to call SBI ecalls
+#
+# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = BaseRiscVSbiLib
+ FILE_GUID = D742CF3D-E600-4009-8FB5-318073008508
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RiscVSbiLib
+
+[Sources]
+ BaseRiscVSbiLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
diff --git a/MdePkg/Include/Library/BaseRiscVSbiLib.h b/MdePkg/Include/Library/BaseRiscVSbiLib.h
new file mode 100644
index 000000000000..e9886187526a
--- /dev/null
+++ b/MdePkg/Include/Library/BaseRiscVSbiLib.h
@@ -0,0 +1,127 @@
+/** @file
+ Library to call the RISC-V SBI ecalls
+
+ Copyright (c) 2021-2022, Hewlett Packard Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Hart - Hardware Thread, similar to a CPU core
+
+ Currently, EDK2 needs to call SBI only to set the time and to do system reset.
+
+**/
+
+#ifndef RISCV_SBI_LIB_H_
+#define RISCV_SBI_LIB_H_
+
+#include <Uefi.h>
+
+/* SBI Extension IDs */
+#define SBI_EXT_TIME 0x54494D45
+#define SBI_EXT_SRST 0x53525354
+
+/* SBI function IDs for TIME extension*/
+#define SBI_EXT_TIME_SET_TIMER 0x0
+
+/* SBI function IDs for SRST extension */
+#define SBI_EXT_SRST_RESET 0x0
+
+#define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0
+#define SBI_SRST_RESET_TYPE_COLD_REBOOT 0x1
+#define SBI_SRST_RESET_TYPE_WARM_REBOOT 0x2
+#define SBI_SRST_RESET_TYPE_LAST SBI_SRST_RESET_TYPE_WARM_REBOOT
+
+#define SBI_SRST_RESET_REASON_NONE 0x0
+#define SBI_SRST_RESET_REASON_SYSFAIL 0x1
+
+/* SBI return error codes */
+#define SBI_SUCCESS 0
+#define SBI_ERR_FAILED -1
+#define SBI_ERR_NOT_SUPPORTED -2
+#define SBI_ERR_INVALID_PARAM -3
+#define SBI_ERR_DENIED -4
+#define SBI_ERR_INVALID_ADDRESS -5
+#define SBI_ERR_ALREADY_AVAILABLE -6
+#define SBI_ERR_ALREADY_STARTED -7
+#define SBI_ERR_ALREADY_STOPPED -8
+
+#define SBI_LAST_ERR SBI_ERR_ALREADY_STOPPED
+
+typedef struct {
+ UINT64 BootHartId;
+ VOID *PeiServiceTable; // PEI Service table
+ UINT64 FlattenedDeviceTree; // Pointer to Flattened Device tree
+} EFI_RISCV_FIRMWARE_CONTEXT;
+
+//
+// EDK2 OpenSBI firmware extension return status.
+//
+typedef struct {
+ UINTN Error; ///< SBI status code
+ UINTN Value; ///< Value returned
+} SBI_RET;
+
+VOID
+EFIAPI
+SbiSetTimer (
+ IN UINT64 Time
+ );
+
+EFI_STATUS
+EFIAPI
+SbiSystemReset (
+ IN UINTN ResetType,
+ IN UINTN ResetReason
+ );
+
+/**
+ Get firmware context of the calling hart.
+
+ @param[out] FirmwareContext The firmware context pointer.
+**/
+VOID
+EFIAPI
+GetFirmwareContext (
+ OUT EFI_RISCV_FIRMWARE_CONTEXT **FirmwareContext
+ );
+
+/**
+ Set firmware context of the calling hart.
+
+ @param[in] FirmwareContext The firmware context pointer.
+**/
+VOID
+EFIAPI
+SetFirmwareContext (
+ IN EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext
+ );
+
+/**
+ Get pointer to OpenSBI Firmware Context
+
+ Get the pointer of firmware context.
+
+ @param FirmwareContextPtr Pointer to retrieve pointer to the
+ Firmware Context.
+**/
+VOID
+EFIAPI
+GetFirmwareContextPointer (
+ IN OUT EFI_RISCV_FIRMWARE_CONTEXT **FirmwareContextPtr
+ );
+
+/**
+ Set pointer to OpenSBI Firmware Context
+
+ Set the pointer of firmware context.
+
+ @param FirmwareContextPtr Pointer to Firmware Context.
+**/
+VOID
+EFIAPI
+SetFirmwareContextPointer (
+ IN EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContextPtr
+ );
+
+#endif
diff --git a/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c b/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c
new file mode 100644
index 000000000000..5db95a008069
--- /dev/null
+++ b/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c
@@ -0,0 +1,227 @@
+/** @file
+ Instance of the SBI ecall library.
+
+ It allows calling an SBI function via an ecall from S-Mode.
+
+ Copyright (c) 2021-2022, Hewlett Packard Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+
+//
+// Maximum arguments for SBI ecall
+// It's possible to pass more but no SBI call uses more as of SBI 0.2.
+// The additional arguments would have to be passed on the stack instead of as
+// registers, like it's done now.
+//
+#define SBI_CALL_MAX_ARGS 6
+
+/**
+ Call SBI call using ecall instruction.
+
+ Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
+
+ @param[in] ExtId SBI extension ID.
+ @param[in] FuncId SBI function ID.
+ @param[in] NumArgs Number of arguments to pass to the ecall.
+ @param[in] ... Argument list for the ecall.
+
+ @retval Returns SBI_RET structure with value and error code.
+
+**/
+STATIC
+SBI_RET
+EFIAPI
+SbiCall (
+ IN UINTN ExtId,
+ IN UINTN FuncId,
+ IN UINTN NumArgs,
+ ...
+ )
+{
+ UINTN I;
+ SBI_RET Ret;
+ UINTN Args[SBI_CALL_MAX_ARGS];
+ VA_LIST ArgList;
+
+ VA_START (ArgList, NumArgs);
+
+ ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
+
+ for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
+ if (I < NumArgs) {
+ Args[I] = VA_ARG (ArgList, UINTN);
+ } else {
+ // Default to 0 for all arguments that are not given
+ Args[I] = 0;
+ }
+ }
+
+ VA_END (ArgList);
+
+ register UINTN a0 asm ("a0") = Args[0];
+ register UINTN a1 asm ("a1") = Args[1];
+ register UINTN a2 asm ("a2") = Args[2];
+ register UINTN a3 asm ("a3") = Args[3];
+ register UINTN a4 asm ("a4") = Args[4];
+ register UINTN a5 asm ("a5") = Args[5];
+ register UINTN a6 asm ("a6") = (UINTN)(FuncId);
+ register UINTN a7 asm ("a7") = (UINTN)(ExtId);
+
+ asm volatile ("ecall" \
+ : "+r" (a0), "+r" (a1) \
+ : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \
+ : "memory"); \
+ Ret.Error = a0;
+ Ret.Value = a1;
+ return Ret;
+}
+
+/**
+ Translate SBI error code to EFI status.
+
+ @param[in] SbiError SBI error code
+ @retval EFI_STATUS
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+TranslateError (
+ IN UINTN SbiError
+ )
+{
+ switch (SbiError) {
+ case SBI_SUCCESS:
+ return EFI_SUCCESS;
+ case SBI_ERR_FAILED:
+ return EFI_DEVICE_ERROR;
+ break;
+ case SBI_ERR_NOT_SUPPORTED:
+ return EFI_UNSUPPORTED;
+ break;
+ case SBI_ERR_INVALID_PARAM:
+ return EFI_INVALID_PARAMETER;
+ break;
+ case SBI_ERR_DENIED:
+ return EFI_ACCESS_DENIED;
+ break;
+ case SBI_ERR_INVALID_ADDRESS:
+ return EFI_LOAD_ERROR;
+ break;
+ case SBI_ERR_ALREADY_AVAILABLE:
+ return EFI_ALREADY_STARTED;
+ break;
+ default:
+ //
+ // Reaches here only if SBI has defined a new error type
+ //
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+}
+
+/**
+ Clear pending timer interrupt bit and set timer for next event after Time.
+
+ To clear the timer without scheduling a timer event, set Time to a
+ practically infinite value or mask the timer interrupt by clearing sie.STIE.
+
+ @param[in] Time The time offset to the next scheduled timer interrupt.
+**/
+VOID
+EFIAPI
+SbiSetTimer (
+ IN UINT64 Time
+ )
+{
+ SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1, Time);
+}
+
+EFI_STATUS
+EFIAPI
+SbiSystemReset (
+ IN UINTN ResetType,
+ IN UINTN ResetReason
+ )
+{
+ SBI_RET Ret;
+
+ Ret = SbiCall (
+ SBI_EXT_SRST,
+ SBI_EXT_SRST_RESET,
+ 2,
+ ResetType,
+ ResetReason
+ );
+
+ return TranslateError (Ret.Error);
+}
+
+/**
+ Get firmware context of the calling hart.
+
+ @param[out] FirmwareContext The firmware context pointer.
+ @retval EFI_SUCCESS The operation succeeds.
+**/
+VOID
+EFIAPI
+GetFirmwareContext (
+ OUT EFI_RISCV_FIRMWARE_CONTEXT **FirmwareContext
+ )
+{
+ *FirmwareContext = (EFI_RISCV_FIRMWARE_CONTEXT *)RiscVGetSupervisorScratch ();
+}
+
+/**
+ Set firmware context of the calling hart.
+
+ @param[in] FirmwareContext The firmware context pointer.
+**/
+VOID
+EFIAPI
+SetFirmwareContext (
+ IN EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext
+ )
+{
+ RiscVSetSupervisorScratch ((UINT64)FirmwareContext);
+}
+
+/**
+ Get pointer to OpenSBI Firmware Context
+
+ Get the pointer of firmware context through OpenSBI FW Extension SBI.
+
+ @param FirmwareContextPtr Pointer to retrieve pointer to the
+ Firmware Context.
+**/
+VOID
+EFIAPI
+GetFirmwareContextPointer (
+ IN OUT EFI_RISCV_FIRMWARE_CONTEXT **FirmwareContextPtr
+ )
+{
+ GetFirmwareContext (FirmwareContextPtr);
+}
+
+/**
+ Set the pointer to OpenSBI Firmware Context
+
+ Set the pointer of firmware context through OpenSBI FW Extension SBI.
+
+ @param FirmwareContextPtr Pointer to Firmware Context.
+**/
+VOID
+EFIAPI
+SetFirmwareContextPointer (
+ IN EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContextPtr
+ )
+{
+ SetFirmwareContext (FirmwareContextPtr);
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 05/29] OvmfPkg/PlatformInitLib: Refactor to allow other architectures
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (3 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 04/29] MdePkg: Add BaseRiscVSbiLib Library for RISC-V Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 06/29] OvmfPkg/PlatformInitLib: Add support for RISC-V Sunil V L
` (23 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Currently, PlatformInitLib supports only X86 architecture. So,
refactor to allow adding other architectures like RISC-V.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
.../PlatformInitLib/PlatformInitLib.inf | 22 ++++++++++---------
.../PlatformInitLib/{ => Ia32_X64}/Cmos.c | 0
.../PlatformInitLib/{ => Ia32_X64}/IntelTdx.c | 0
.../{ => Ia32_X64}/IntelTdxNull.c | 0
.../{ => Ia32_X64}/MemDetect.c | 0
.../PlatformInitLib/{ => Ia32_X64}/Platform.c | 0
6 files changed, 12 insertions(+), 10 deletions(-)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/Cmos.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/IntelTdx.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/IntelTdxNull.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/MemDetect.c (100%)
rename OvmfPkg/Library/PlatformInitLib/{ => Ia32_X64}/Platform.c (100%)
diff --git a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
index 86a82ad3e084..d4449e40af61 100644
--- a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
+++ b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
@@ -22,16 +22,16 @@ [Defines]
# VALID_ARCHITECTURES = IA32 X64 EBC
#
-[Sources]
- Cmos.c
- MemDetect.c
- Platform.c
+[Sources.IA32, Sources.X64]
+ Ia32_X64/Cmos.c
+ Ia32_X64/MemDetect.c
+ Ia32_X64/Platform.c
[Sources.IA32]
- IntelTdxNull.c
+ Ia32_X64/IntelTdxNull.c
[Sources.X64]
- IntelTdx.c
+ Ia32_X64/IntelTdx.c
[Packages]
EmbeddedPkg/EmbeddedPkg.dec
@@ -45,12 +45,14 @@ [LibraryClasses]
DebugLib
IoLib
HobLib
+ PcdLib
+ PciLib
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ MtrrLib
QemuFwCfgLib
QemuFwCfgSimpleParserLib
MemoryAllocationLib
- MtrrLib
- PcdLib
- PciLib
PeiHardwareInfoLib
[LibraryClasses.X64]
@@ -100,5 +102,5 @@ [FixedPcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase
gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataSize
-[FeaturePcd]
+[FeaturePcd.IA32, FeaturePcd.X64]
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
diff --git a/OvmfPkg/Library/PlatformInitLib/Cmos.c b/OvmfPkg/Library/PlatformInitLib/Ia32_X64/Cmos.c
similarity index 100%
rename from OvmfPkg/Library/PlatformInitLib/Cmos.c
rename to OvmfPkg/Library/PlatformInitLib/Ia32_X64/Cmos.c
diff --git a/OvmfPkg/Library/PlatformInitLib/IntelTdx.c b/OvmfPkg/Library/PlatformInitLib/Ia32_X64/IntelTdx.c
similarity index 100%
rename from OvmfPkg/Library/PlatformInitLib/IntelTdx.c
rename to OvmfPkg/Library/PlatformInitLib/Ia32_X64/IntelTdx.c
diff --git a/OvmfPkg/Library/PlatformInitLib/IntelTdxNull.c b/OvmfPkg/Library/PlatformInitLib/Ia32_X64/IntelTdxNull.c
similarity index 100%
rename from OvmfPkg/Library/PlatformInitLib/IntelTdxNull.c
rename to OvmfPkg/Library/PlatformInitLib/Ia32_X64/IntelTdxNull.c
diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/Ia32_X64/MemDetect.c
similarity index 100%
rename from OvmfPkg/Library/PlatformInitLib/MemDetect.c
rename to OvmfPkg/Library/PlatformInitLib/Ia32_X64/MemDetect.c
diff --git a/OvmfPkg/Library/PlatformInitLib/Platform.c b/OvmfPkg/Library/PlatformInitLib/Ia32_X64/Platform.c
similarity index 100%
rename from OvmfPkg/Library/PlatformInitLib/Platform.c
rename to OvmfPkg/Library/PlatformInitLib/Ia32_X64/Platform.c
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 06/29] OvmfPkg/PlatformInitLib: Add support for RISC-V
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (4 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 05/29] OvmfPkg/PlatformInitLib: Refactor to allow other architectures Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 07/29] OvmfPkg/ResetSystemLib: Refactor to allow other architectures Sunil V L
` (22 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This is copied from
edk2-platforms/Platform/RISC-V/PlatformPkg/Universal/FdtPeim
but added as part of library instead of a separate module.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
.../PlatformInitLib/PlatformInitLib.inf | 9 ++-
OvmfPkg/Include/Library/PlatformInitLib.h | 6 ++
.../PlatformInitLib/RiscV64/PlatformPeiLib.c | 73 +++++++++++++++++++
3 files changed, 87 insertions(+), 1 deletion(-)
create mode 100644 OvmfPkg/Library/PlatformInitLib/RiscV64/PlatformPeiLib.c
diff --git a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
index d4449e40af61..ef8675999583 100644
--- a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
+++ b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
@@ -19,7 +19,7 @@ [Defines]
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64 EBC
+# VALID_ARCHITECTURES = IA32 X64 EBC RISCV64
#
[Sources.IA32, Sources.X64]
@@ -33,6 +33,9 @@ [Sources.IA32]
[Sources.X64]
Ia32_X64/IntelTdx.c
+[Sources.RISCV64]
+ RiscV64/PlatformPeiLib.c
+
[Packages]
EmbeddedPkg/EmbeddedPkg.dec
MdeModulePkg/MdeModulePkg.dec
@@ -58,6 +61,10 @@ [LibraryClasses.IA32, LibraryClasses.X64]
[LibraryClasses.X64]
TdxLib
+[LibraryClasses.RISCV64]
+ RiscVSbiLib
+ FdtLib
+
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
diff --git a/OvmfPkg/Include/Library/PlatformInitLib.h b/OvmfPkg/Include/Library/PlatformInitLib.h
index c5234bf26d45..1b8d1fad3b49 100644
--- a/OvmfPkg/Include/Library/PlatformInitLib.h
+++ b/OvmfPkg/Include/Library/PlatformInitLib.h
@@ -285,4 +285,10 @@ PlatformInitEmuVariableNvStore (
IN VOID *EmuVariableNvStore
);
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+ VOID
+ );
+
#endif // PLATFORM_INIT_LIB_H_
diff --git a/OvmfPkg/Library/PlatformInitLib/RiscV64/PlatformPeiLib.c b/OvmfPkg/Library/PlatformInitLib/RiscV64/PlatformPeiLib.c
new file mode 100644
index 000000000000..c5db7777c849
--- /dev/null
+++ b/OvmfPkg/Library/PlatformInitLib/RiscV64/PlatformPeiLib.c
@@ -0,0 +1,73 @@
+/** @file
+The library call to pass the device tree to DXE via HOB.
+
+Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+//// The package level header files this module uses
+////
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+
+#include <libfdt.h>
+
+#include <Guid/FdtHob.h>
+
+/**
+ @retval EFI_SUCCESS The address of FDT is passed in HOB.
+ EFI_UNSUPPORTED Can't locate FDT.
+**/
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+ VOID
+ )
+{
+ EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
+ VOID *FdtPointer;
+ VOID *Base;
+ VOID *NewBase;
+ UINTN FdtSize;
+ UINTN FdtPages;
+ UINT64 *FdtHobData;
+
+ FirmwareContext = NULL;
+ GetFirmwareContextPointer (&FirmwareContext);
+
+ if (FirmwareContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Firmware Context is NULL\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ FdtPointer = (VOID *)FirmwareContext->FlattenedDeviceTree;
+ if (FdtPointer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid FDT pointer\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a: Build FDT HOB - FDT at address: 0x%x \n", __FUNCTION__, FdtPointer));
+ Base = FdtPointer;
+ ASSERT (Base != NULL);
+ ASSERT (fdt_check_header (Base) == 0);
+
+ FdtSize = fdt_totalsize (Base);
+ FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
+ NewBase = AllocatePages (FdtPages);
+ ASSERT (NewBase != NULL);
+ fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
+
+ FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
+ ASSERT (FdtHobData != NULL);
+ *FdtHobData = (UINTN)NewBase;
+
+ return EFI_SUCCESS;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 07/29] OvmfPkg/ResetSystemLib: Refactor to allow other architectures.
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (5 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 06/29] OvmfPkg/PlatformInitLib: Add support for RISC-V Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 08/29] OvmfPkg/ResetSystemLib: Add support for RISC-V Sunil V L
` (21 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Rebecca Cran, Peter Grehan
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Currently, the ResetSystemLib library supports only X86 architecture.
Refactor it to allow adding other CPU architectures like RISC-V.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Rebecca Cran <rebecca@bsdio.com>
Cc: Peter Grehan <grehan@freebsd.org>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf | 6 +++---
OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibBhyve.inf | 4 ++--
.../Library/ResetSystemLib/BaseResetSystemLibMicrovm.inf | 2 +-
OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf | 6 +++---
.../ResetSystemLib/{ => Ia32_X64}/BaseResetShutdown.c | 0
.../ResetSystemLib/{ => Ia32_X64}/BaseResetShutdownBhyve.c | 0
.../ResetSystemLib/{ => Ia32_X64}/DxeResetShutdown.c | 0
.../{ => Ia32_X64}/DxeResetSystemLibMicrovm.c | 0
.../Library/ResetSystemLib/{ => Ia32_X64}/ResetSystemLib.c | 0
.../ResetSystemLib/{ => Ia32_X64}/ResetSystemLibMicrovm.c | 0
10 files changed, 9 insertions(+), 9 deletions(-)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/BaseResetShutdown.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/BaseResetShutdownBhyve.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/DxeResetShutdown.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/DxeResetSystemLibMicrovm.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/ResetSystemLib.c (100%)
rename OvmfPkg/Library/ResetSystemLib/{ => Ia32_X64}/ResetSystemLibMicrovm.c (100%)
diff --git a/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf b/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
index 35d317f1e0b3..4397f90a24dd 100644
--- a/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
+++ b/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
@@ -21,9 +21,9 @@ [Defines]
# VALID_ARCHITECTURES = IA32 X64
#
-[Sources]
- BaseResetShutdown.c
- ResetSystemLib.c
+[Sources.IA32, Sources.X64]
+ Ia32_X64/BaseResetShutdown.c
+ Ia32_X64/ResetSystemLib.c
[Packages]
MdeModulePkg/MdeModulePkg.dec
diff --git a/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibBhyve.inf b/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibBhyve.inf
index 74124aed38e8..3e52a9e3d7f9 100644
--- a/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibBhyve.inf
+++ b/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibBhyve.inf
@@ -25,8 +25,8 @@ [Defines]
#
[Sources]
- BaseResetShutdownBhyve.c
- ResetSystemLib.c
+ Ia32_X64/BaseResetShutdownBhyve.c
+ Ia32_X64/ResetSystemLib.c
[Packages]
MdeModulePkg/MdeModulePkg.dec
diff --git a/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibMicrovm.inf b/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibMicrovm.inf
index 564b1d3022a6..c66720771d82 100644
--- a/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibMicrovm.inf
+++ b/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibMicrovm.inf
@@ -23,7 +23,7 @@ [Defines]
#
[Sources]
- ResetSystemLibMicrovm.c
+ Ia32_X64/ResetSystemLibMicrovm.c
[Packages]
MdeModulePkg/MdeModulePkg.dec
diff --git a/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf b/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
index a9b4ce90000a..79478453d7cb 100644
--- a/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+++ b/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
@@ -23,9 +23,9 @@ [Defines]
# VALID_ARCHITECTURES = IA32 X64
#
-[Sources]
- DxeResetShutdown.c
- ResetSystemLib.c
+[Sources.IA32, Sources.X64]
+ Ia32_X64/DxeResetShutdown.c
+ Ia32_X64/ResetSystemLib.c
[Packages]
MdeModulePkg/MdeModulePkg.dec
diff --git a/OvmfPkg/Library/ResetSystemLib/BaseResetShutdown.c b/OvmfPkg/Library/ResetSystemLib/Ia32_X64/BaseResetShutdown.c
similarity index 100%
rename from OvmfPkg/Library/ResetSystemLib/BaseResetShutdown.c
rename to OvmfPkg/Library/ResetSystemLib/Ia32_X64/BaseResetShutdown.c
diff --git a/OvmfPkg/Library/ResetSystemLib/BaseResetShutdownBhyve.c b/OvmfPkg/Library/ResetSystemLib/Ia32_X64/BaseResetShutdownBhyve.c
similarity index 100%
rename from OvmfPkg/Library/ResetSystemLib/BaseResetShutdownBhyve.c
rename to OvmfPkg/Library/ResetSystemLib/Ia32_X64/BaseResetShutdownBhyve.c
diff --git a/OvmfPkg/Library/ResetSystemLib/DxeResetShutdown.c b/OvmfPkg/Library/ResetSystemLib/Ia32_X64/DxeResetShutdown.c
similarity index 100%
rename from OvmfPkg/Library/ResetSystemLib/DxeResetShutdown.c
rename to OvmfPkg/Library/ResetSystemLib/Ia32_X64/DxeResetShutdown.c
diff --git a/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLibMicrovm.c b/OvmfPkg/Library/ResetSystemLib/Ia32_X64/DxeResetSystemLibMicrovm.c
similarity index 100%
rename from OvmfPkg/Library/ResetSystemLib/DxeResetSystemLibMicrovm.c
rename to OvmfPkg/Library/ResetSystemLib/Ia32_X64/DxeResetSystemLibMicrovm.c
diff --git a/OvmfPkg/Library/ResetSystemLib/ResetSystemLib.c b/OvmfPkg/Library/ResetSystemLib/Ia32_X64/ResetSystemLib.c
similarity index 100%
rename from OvmfPkg/Library/ResetSystemLib/ResetSystemLib.c
rename to OvmfPkg/Library/ResetSystemLib/Ia32_X64/ResetSystemLib.c
diff --git a/OvmfPkg/Library/ResetSystemLib/ResetSystemLibMicrovm.c b/OvmfPkg/Library/ResetSystemLib/Ia32_X64/ResetSystemLibMicrovm.c
similarity index 100%
rename from OvmfPkg/Library/ResetSystemLib/ResetSystemLibMicrovm.c
rename to OvmfPkg/Library/ResetSystemLib/Ia32_X64/ResetSystemLibMicrovm.c
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 08/29] OvmfPkg/ResetSystemLib: Add support for RISC-V
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (6 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 07/29] OvmfPkg/ResetSystemLib: Refactor to allow other architectures Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 09/29] OvmfPkg/Sec: Refactor to allow other architectures Sunil V L
` (20 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Rebecca Cran, Peter Grehan, Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This is mostly copied from
edk2-platforms/Platform/RISC-V/PlatformPkg/Library/ResetSystemLib
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Rebecca Cran <rebecca@bsdio.com>
Cc: Peter Grehan <grehan@freebsd.org>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
.../ResetSystemLib/BaseResetSystemLib.inf | 6 +
.../ResetSystemLib/DxeResetSystemLib.inf | 9 +-
.../ResetSystemLib/RiscV64/DxeResetShutdown.c | 20 +++
.../ResetSystemLib/RiscV64/ResetSystemLib.c | 128 ++++++++++++++++++
4 files changed, 162 insertions(+), 1 deletion(-)
create mode 100644 OvmfPkg/Library/ResetSystemLib/RiscV64/DxeResetShutdown.c
create mode 100644 OvmfPkg/Library/ResetSystemLib/RiscV64/ResetSystemLib.c
diff --git a/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf b/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
index 4397f90a24dd..797eedb195ee 100644
--- a/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
+++ b/OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
@@ -25,6 +25,9 @@ [Sources.IA32, Sources.X64]
Ia32_X64/BaseResetShutdown.c
Ia32_X64/ResetSystemLib.c
+[Sources.RISCV64]
+ RiscV64/ResetSystemLib.c
+
[Packages]
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
@@ -36,3 +39,6 @@ [LibraryClasses]
IoLib
PciLib
TimerLib
+
+[LibraryClasses]
+ RiscVSbiLib
diff --git a/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf b/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
index 79478453d7cb..abab573f2f06 100644
--- a/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+++ b/OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
@@ -20,13 +20,17 @@ [Defines]
# The following information is for reference only and not required by the build
# tools.
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 RISCV64
#
[Sources.IA32, Sources.X64]
Ia32_X64/DxeResetShutdown.c
Ia32_X64/ResetSystemLib.c
+[Sources.RISCV64]
+ RiscV64/ResetSystemLib.c
+ RiscV64/DxeResetShutdown.c
+
[Packages]
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
@@ -39,5 +43,8 @@ [LibraryClasses]
PcdLib
TimerLib
+[LibraryClasses.RISCV64]
+ RiscVSbiLib
+
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId ## CONSUMES
diff --git a/OvmfPkg/Library/ResetSystemLib/RiscV64/DxeResetShutdown.c b/OvmfPkg/Library/ResetSystemLib/RiscV64/DxeResetShutdown.c
new file mode 100644
index 000000000000..027e235cad11
--- /dev/null
+++ b/OvmfPkg/Library/ResetSystemLib/RiscV64/DxeResetShutdown.c
@@ -0,0 +1,20 @@
+/** @file
+ DXE Reset System Library Shutdown API implementation for OVMF.
+
+ Copyright (C) 2020, Red Hat, Inc.
+ Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // CpuDeadLoop()
+#include <Library/ResetSystemLib.h> // ResetShutdown()
+
+EFI_STATUS
+EFIAPI
+DxeResetInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/ResetSystemLib/RiscV64/ResetSystemLib.c b/OvmfPkg/Library/ResetSystemLib/RiscV64/ResetSystemLib.c
new file mode 100644
index 000000000000..14f7653aa8de
--- /dev/null
+++ b/OvmfPkg/Library/ResetSystemLib/RiscV64/ResetSystemLib.c
@@ -0,0 +1,128 @@
+/** @file
+ Reset System Library functions for RISC-V
+
+ Copyright (c) 2021, Hewlett Packard Development LP. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+
+/**
+ This function causes a system-wide reset (cold reset), in which
+ all circuitry within the system returns to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ If this function returns, it means that the system does not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ // Warm Reset via SBI ecall
+ SbiSystemReset (SBI_SRST_RESET_TYPE_COLD_REBOOT, SBI_SRST_RESET_REASON_NONE);
+}
+
+/**
+ This function causes a system-wide initialization (warm reset), in which all processors
+ are set to their initial state. Pending cycles are not corrupted.
+
+ If this function returns, it means that the system does not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ // Warm Reset via SBI ecall
+ SbiSystemReset (SBI_SRST_RESET_TYPE_WARM_REBOOT, SBI_SRST_RESET_REASON_NONE);
+}
+
+/**
+ This function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ If this function returns, it means that the system does not support shutdown reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ // Shut down via SBI ecall
+ SbiSystemReset (SBI_SRST_RESET_TYPE_SHUTDOWN, SBI_SRST_RESET_REASON_NONE);
+}
+
+/**
+ This function causes a systemwide reset. The exact type of the reset is
+ defined by the EFI_GUID that follows the Null-terminated Unicode string passed
+ into ResetData. If the platform does not recognize the EFI_GUID in ResetData
+ the platform must pick a supported reset type to perform. The platform may
+ optionally log the parameters from any non-normal reset that occurs.
+
+ @param[in] DataSize The size, in bytes, of ResetData.
+ @param[in] ResetData The data buffer starts with a Null-terminated string,
+ followed by the EFI_GUID.
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN UINTN DataSize,
+ IN VOID *ResetData
+ )
+{
+ //
+ // Can map to OpenSBI vendor or platform specific reset type.
+ //
+ return;
+}
+
+/**
+ The ResetSystem function resets the entire platform.
+
+ @param[in] ResetType The type of reset to perform.
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size, in bytes, of ResetData.
+ @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown
+ the data buffer starts with a Null-terminated string, optionally
+ followed by additional binary data. The string is a description
+ that the caller may use to further indicate the reason for the
+ system reset.
+**/
+VOID
+EFIAPI
+ResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ switch (ResetType) {
+ case EfiResetWarm:
+ ResetWarm ();
+ break;
+
+ case EfiResetCold:
+ ResetCold ();
+ break;
+
+ case EfiResetShutdown:
+ ResetShutdown ();
+ return;
+
+ case EfiResetPlatformSpecific:
+ ResetPlatformSpecific (DataSize, ResetData);
+ return;
+
+ default:
+ return;
+ }
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 09/29] OvmfPkg/Sec: Refactor to allow other architectures
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (7 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 08/29] OvmfPkg/ResetSystemLib: Add support for RISC-V Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 10/29] OvmfPkg/Sec: Add RISC-V support Sunil V L
` (19 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Brijesh Singh, Erdem Aktas, James Bottomley, Min Xu, Tom Lendacky
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Currently, the Sec module supports only X86 architecture.
Refactor the module to allow other CPU architectures.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/Sec/SecMain.inf | 18 +-
OvmfPkg/Sec/{ => Ia32_X64}/AmdSev.h | 0
OvmfPkg/Sec/SecMainCommon.h | 73 ++++++++
OvmfPkg/Sec/{ => Ia32_X64}/AmdSev.c | 0
OvmfPkg/Sec/{ => Ia32_X64}/SecMain.c | 227 +------------------------
OvmfPkg/Sec/SecMainCommon.c | 238 +++++++++++++++++++++++++++
6 files changed, 323 insertions(+), 233 deletions(-)
rename OvmfPkg/Sec/{ => Ia32_X64}/AmdSev.h (100%)
create mode 100644 OvmfPkg/Sec/SecMainCommon.h
rename OvmfPkg/Sec/{ => Ia32_X64}/AmdSev.c (100%)
rename OvmfPkg/Sec/{ => Ia32_X64}/SecMain.c (75%)
create mode 100644 OvmfPkg/Sec/SecMainCommon.c
diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf
index 561a840f29c5..7c80ecaaf49b 100644
--- a/OvmfPkg/Sec/SecMain.inf
+++ b/OvmfPkg/Sec/SecMain.inf
@@ -21,10 +21,12 @@ [Defines]
# VALID_ARCHITECTURES = IA32 X64 EBC
#
-[Sources]
- SecMain.c
- AmdSev.c
- AmdSev.h
+[Sources.IA32, Sources.X64]
+ SecMainCommon.c
+ SecMainCommon.h
+ Ia32_X64/SecMain.c
+ Ia32_X64/AmdSev.c
+ Ia32_X64/AmdSev.h
[Sources.IA32]
Ia32/SecEntry.nasm
@@ -42,19 +44,21 @@ [LibraryClasses]
BaseLib
DebugLib
BaseMemoryLib
- PeiServicesLib
PcdLib
CpuLib
- UefiCpuLib
DebugAgentLib
IoLib
PeCoffLib
PeCoffGetEntryPointLib
PeCoffExtraActionLib
ExtractGuidedSectionLib
+ CpuExceptionHandlerLib
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ UefiCpuLib
LocalApicLib
MemEncryptSevLib
- CpuExceptionHandlerLib
+ PeiServicesLib
CcProbeLib
[Ppis]
diff --git a/OvmfPkg/Sec/AmdSev.h b/OvmfPkg/Sec/Ia32_X64/AmdSev.h
similarity index 100%
rename from OvmfPkg/Sec/AmdSev.h
rename to OvmfPkg/Sec/Ia32_X64/AmdSev.h
diff --git a/OvmfPkg/Sec/SecMainCommon.h b/OvmfPkg/Sec/SecMainCommon.h
new file mode 100644
index 000000000000..c3cc16e2c8cf
--- /dev/null
+++ b/OvmfPkg/Sec/SecMainCommon.h
@@ -0,0 +1,73 @@
+/** @file
+ Header file for common functions of Sec.
+
+ Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/**
+ Locates a section within a series of sections
+ with the specified section type.
+
+ The Instance parameter indicates which instance of the section
+ type to return. (0 is first instance, 1 is second...)
+
+ @param[in] Sections The sections to search
+ @param[in] SizeOfSections Total size of all sections
+ @param[in] SectionType The section type to locate
+ @param[in] Instance The section instance number
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInstance (
+ IN VOID *Sections,
+ IN UINTN SizeOfSections,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ );
+
+/**
+ Locates a FFS file with the specified file type and a section
+ within that file with the specified section type.
+
+ @param[in] Fv The firmware volume to search
+ @param[in] FileType The file type to locate
+ @param[in] SectionType The section type to locate
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsFileAndSection (
+ IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
+ IN EFI_FV_FILETYPE FileType,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ );
+
+/**
+ Locates the PEI Core entry point address
+
+ @param[in] Fv The firmware volume to search
+ @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindPeiCoreImageBaseInFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
+ OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
+ );
diff --git a/OvmfPkg/Sec/AmdSev.c b/OvmfPkg/Sec/Ia32_X64/AmdSev.c
similarity index 100%
rename from OvmfPkg/Sec/AmdSev.c
rename to OvmfPkg/Sec/Ia32_X64/AmdSev.c
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/Ia32_X64/SecMain.c
similarity index 75%
rename from OvmfPkg/Sec/SecMain.c
rename to OvmfPkg/Sec/Ia32_X64/SecMain.c
index 1167d22a68cc..096bab074f35 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/Ia32_X64/SecMain.c
@@ -32,6 +32,7 @@
#include <Library/PlatformInitLib.h>
#include <Library/CcProbeLib.h>
#include "AmdSev.h"
+#include "SecMainCommon.h"
#define SEC_IDT_ENTRY_COUNT 34
@@ -143,189 +144,6 @@ FindMainFv (
} while (TRUE);
}
-/**
- Locates a section within a series of sections
- with the specified section type.
-
- The Instance parameter indicates which instance of the section
- type to return. (0 is first instance, 1 is second...)
-
- @param[in] Sections The sections to search
- @param[in] SizeOfSections Total size of all sections
- @param[in] SectionType The section type to locate
- @param[in] Instance The section instance number
- @param[out] FoundSection The FFS section if found
-
- @retval EFI_SUCCESS The file and section was found
- @retval EFI_NOT_FOUND The file and section was not found
- @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
-
-**/
-EFI_STATUS
-FindFfsSectionInstance (
- IN VOID *Sections,
- IN UINTN SizeOfSections,
- IN EFI_SECTION_TYPE SectionType,
- IN UINTN Instance,
- OUT EFI_COMMON_SECTION_HEADER **FoundSection
- )
-{
- EFI_PHYSICAL_ADDRESS CurrentAddress;
- UINT32 Size;
- EFI_PHYSICAL_ADDRESS EndOfSections;
- EFI_COMMON_SECTION_HEADER *Section;
- EFI_PHYSICAL_ADDRESS EndOfSection;
-
- //
- // Loop through the FFS file sections within the PEI Core FFS file
- //
- EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)Sections;
- EndOfSections = EndOfSection + SizeOfSections;
- for ( ; ;) {
- if (EndOfSection == EndOfSections) {
- break;
- }
-
- CurrentAddress = (EndOfSection + 3) & ~(3ULL);
- if (CurrentAddress >= EndOfSections) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;
-
- Size = SECTION_SIZE (Section);
- if (Size < sizeof (*Section)) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- EndOfSection = CurrentAddress + Size;
- if (EndOfSection > EndOfSections) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- //
- // Look for the requested section type
- //
- if (Section->Type == SectionType) {
- if (Instance == 0) {
- *FoundSection = Section;
- return EFI_SUCCESS;
- } else {
- Instance--;
- }
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Locates a section within a series of sections
- with the specified section type.
-
- @param[in] Sections The sections to search
- @param[in] SizeOfSections Total size of all sections
- @param[in] SectionType The section type to locate
- @param[out] FoundSection The FFS section if found
-
- @retval EFI_SUCCESS The file and section was found
- @retval EFI_NOT_FOUND The file and section was not found
- @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
-
-**/
-EFI_STATUS
-FindFfsSectionInSections (
- IN VOID *Sections,
- IN UINTN SizeOfSections,
- IN EFI_SECTION_TYPE SectionType,
- OUT EFI_COMMON_SECTION_HEADER **FoundSection
- )
-{
- return FindFfsSectionInstance (
- Sections,
- SizeOfSections,
- SectionType,
- 0,
- FoundSection
- );
-}
-
-/**
- Locates a FFS file with the specified file type and a section
- within that file with the specified section type.
-
- @param[in] Fv The firmware volume to search
- @param[in] FileType The file type to locate
- @param[in] SectionType The section type to locate
- @param[out] FoundSection The FFS section if found
-
- @retval EFI_SUCCESS The file and section was found
- @retval EFI_NOT_FOUND The file and section was not found
- @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
-
-**/
-EFI_STATUS
-FindFfsFileAndSection (
- IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
- IN EFI_FV_FILETYPE FileType,
- IN EFI_SECTION_TYPE SectionType,
- OUT EFI_COMMON_SECTION_HEADER **FoundSection
- )
-{
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS CurrentAddress;
- EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
- EFI_FFS_FILE_HEADER *File;
- UINT32 Size;
- EFI_PHYSICAL_ADDRESS EndOfFile;
-
- if (Fv->Signature != EFI_FVH_SIGNATURE) {
- DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv));
- return EFI_VOLUME_CORRUPTED;
- }
-
- CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv;
- EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
-
- //
- // Loop through the FFS files in the Boot Firmware Volume
- //
- for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
- CurrentAddress = (EndOfFile + 7) & ~(7ULL);
- if (CurrentAddress > EndOfFirmwareVolume) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;
- Size = FFS_FILE_SIZE (File);
- if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- EndOfFile = CurrentAddress + Size;
- if (EndOfFile > EndOfFirmwareVolume) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- //
- // Look for the request file type
- //
- if (File->Type != FileType) {
- continue;
- }
-
- Status = FindFfsSectionInSections (
- (VOID *)(File + 1),
- (UINTN)EndOfFile - (UINTN)(File + 1),
- SectionType,
- FoundSection
- );
- if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
- return Status;
- }
- }
-}
-
/**
Locates the compressed main firmware volume and decompresses it.
@@ -474,49 +292,6 @@ DecompressMemFvs (
return EFI_SUCCESS;
}
-/**
- Locates the PEI Core entry point address
-
- @param[in] Fv The firmware volume to search
- @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
-
- @retval EFI_SUCCESS The file and section was found
- @retval EFI_NOT_FOUND The file and section was not found
- @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
-
-**/
-EFI_STATUS
-FindPeiCoreImageBaseInFv (
- IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
- OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
- )
-{
- EFI_STATUS Status;
- EFI_COMMON_SECTION_HEADER *Section;
-
- Status = FindFfsFileAndSection (
- Fv,
- EFI_FV_FILETYPE_PEI_CORE,
- EFI_SECTION_PE32,
- &Section
- );
- if (EFI_ERROR (Status)) {
- Status = FindFfsFileAndSection (
- Fv,
- EFI_FV_FILETYPE_PEI_CORE,
- EFI_SECTION_TE,
- &Section
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n"));
- return Status;
- }
- }
-
- *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
- return EFI_SUCCESS;
-}
-
/**
Reads 8-bits of CMOS data.
diff --git a/OvmfPkg/Sec/SecMainCommon.c b/OvmfPkg/Sec/SecMainCommon.c
new file mode 100644
index 000000000000..f360e63a7c26
--- /dev/null
+++ b/OvmfPkg/Sec/SecMainCommon.c
@@ -0,0 +1,238 @@
+/** @file
+ Locate the entry point for the PEI Core
+
+ Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+
+/**
+ Locates a section within a series of sections
+ with the specified section type.
+
+ The Instance parameter indicates which instance of the section
+ type to return. (0 is first instance, 1 is second...)
+
+ @param[in] Sections The sections to search
+ @param[in] SizeOfSections Total size of all sections
+ @param[in] SectionType The section type to locate
+ @param[in] Instance The section instance number
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInstance (
+ IN VOID *Sections,
+ IN UINTN SizeOfSections,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfSections;
+ EFI_COMMON_SECTION_HEADER *Section;
+ EFI_PHYSICAL_ADDRESS EndOfSection;
+
+ //
+ // Loop through the FFS file sections within the PEI Core FFS file
+ //
+ EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)Sections;
+ EndOfSections = EndOfSection + SizeOfSections;
+ for ( ; ;) {
+ if (EndOfSection == EndOfSections) {
+ break;
+ }
+
+ CurrentAddress = (EndOfSection + 3) & ~(3ULL);
+ if (CurrentAddress >= EndOfSections) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;
+
+ Size = SECTION_SIZE (Section);
+ if (Size < sizeof (*Section)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ EndOfSection = CurrentAddress + Size;
+ if (EndOfSection > EndOfSections) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ //
+ // Look for the requested section type
+ //
+ if (Section->Type == SectionType) {
+ if (Instance == 0) {
+ *FoundSection = Section;
+ return EFI_SUCCESS;
+ } else {
+ Instance--;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Locates a section within a series of sections
+ with the specified section type.
+
+ @param[in] Sections The sections to search
+ @param[in] SizeOfSections Total size of all sections
+ @param[in] SectionType The section type to locate
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInSections (
+ IN VOID *Sections,
+ IN UINTN SizeOfSections,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ return FindFfsSectionInstance (
+ Sections,
+ SizeOfSections,
+ SectionType,
+ 0,
+ FoundSection
+ );
+}
+
+/**
+ Locates a FFS file with the specified file type and a section
+ within that file with the specified section type.
+
+ @param[in] Fv The firmware volume to search
+ @param[in] FileType The file type to locate
+ @param[in] SectionType The section type to locate
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsFileAndSection (
+ IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
+ IN EFI_FV_FILETYPE FileType,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
+ EFI_FFS_FILE_HEADER *File;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfFile;
+
+ if (Fv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv));
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv;
+ EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
+
+ //
+ // Loop through the FFS files in the Boot Firmware Volume
+ //
+ for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
+ CurrentAddress = (EndOfFile + 7) & ~(7ULL);
+ if (CurrentAddress > EndOfFirmwareVolume) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;
+ Size = FFS_FILE_SIZE (File);
+ if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ EndOfFile = CurrentAddress + Size;
+ if (EndOfFile > EndOfFirmwareVolume) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ //
+ // Look for the request file type
+ //
+ if (File->Type != FileType) {
+ continue;
+ }
+
+ Status = FindFfsSectionInSections (
+ (VOID *)(File + 1),
+ (UINTN)EndOfFile - (UINTN)(File + 1),
+ SectionType,
+ FoundSection
+ );
+ if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
+ return Status;
+ }
+ }
+}
+
+/**
+ Locates the PEI Core entry point address
+
+ @param[in] Fv The firmware volume to search
+ @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindPeiCoreImageBaseInFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
+ OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
+ )
+{
+ EFI_STATUS Status;
+ EFI_COMMON_SECTION_HEADER *Section;
+
+ Status = FindFfsFileAndSection (
+ Fv,
+ EFI_FV_FILETYPE_PEI_CORE,
+ EFI_SECTION_PE32,
+ &Section
+ );
+ if (EFI_ERROR (Status)) {
+ Status = FindFfsFileAndSection (
+ Fv,
+ EFI_FV_FILETYPE_PEI_CORE,
+ EFI_SECTION_TE,
+ &Section
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n"));
+ return Status;
+ }
+ }
+
+ *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+ return EFI_SUCCESS;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 10/29] OvmfPkg/Sec: Add RISC-V support
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (8 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 09/29] OvmfPkg/Sec: Refactor to allow other architectures Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 11/29] OvmfPkg/PlatformPei: Refactor to allow other architectures Sunil V L
` (18 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Brijesh Singh, Erdem Aktas, James Bottomley, Min Xu, Tom Lendacky,
Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Add the SEC module for RISC-V. EDK2 is launched as the payload
for machine mode firmware in RISC-V.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/Sec/SecMain.inf | 16 +-
OvmfPkg/Sec/RiscV64/SecMain.h | 65 ++++
OvmfPkg/Sec/RiscV64/SecMain.c | 573 +++++++++++++++++++++++++++++++++
OvmfPkg/Sec/RiscV64/SecEntry.S | 23 ++
4 files changed, 676 insertions(+), 1 deletion(-)
create mode 100644 OvmfPkg/Sec/RiscV64/SecMain.h
create mode 100644 OvmfPkg/Sec/RiscV64/SecMain.c
create mode 100644 OvmfPkg/Sec/RiscV64/SecEntry.S
diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf
index 7c80ecaaf49b..76c47778ce8c 100644
--- a/OvmfPkg/Sec/SecMain.inf
+++ b/OvmfPkg/Sec/SecMain.inf
@@ -18,7 +18,7 @@ [Defines]
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64 EBC
+# VALID_ARCHITECTURES = IA32 X64 EBC RISCV64
#
[Sources.IA32, Sources.X64]
@@ -34,6 +34,13 @@ [Sources.IA32]
[Sources.X64]
X64/SecEntry.nasm
+[Sources.RISCV64]
+ SecMainCommon.c
+ SecMainCommon.h
+ RiscV64/SecEntry.S
+ RiscV64/SecMain.c
+ RiscV64/SecMain.h
+
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
@@ -61,11 +68,17 @@ [LibraryClasses.IA32, LibraryClasses.X64]
PeiServicesLib
CcProbeLib
+[LibraryClasses.RISCV64]
+ RiscVSbiLib
+
[Ppis]
gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
gEfiPeiMpInitLibMpDepPpiGuid
gEfiPeiMpInitLibUpDepPpiGuid
+[Ppis.RISCV64]
+ gEfiTemporaryRamDonePpiGuid ## PRODUCES
+
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
@@ -88,6 +101,7 @@ [Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/OvmfPkg/Sec/RiscV64/SecMain.h b/OvmfPkg/Sec/RiscV64/SecMain.h
new file mode 100644
index 000000000000..11e3daa090b5
--- /dev/null
+++ b/OvmfPkg/Sec/RiscV64/SecMain.h
@@ -0,0 +1,65 @@
+/** @file
+ Master header file for SecCore.
+
+ Copyright (c) 2019-2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+ Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SEC_MAIN_H_
+#define _SEC_MAIN_H_
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ExtractGuidedSectionLib.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/DebugPrintErrorLevelLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+#include <Register/RiscV64/RiscVImpl.h>
+#include <Ppi/TemporaryRamDone.h>
+#include <Ppi/TemporaryRamSupport.h>
+
+#include "SecMainCommon.h"
+
+/**
+ Entry point to the C language phase of SEC. After the SEC assembly
+ code has initialized some temporary memory and set up the stack,
+ the control is transferred to this function.
+
+ @param SizeOfRam Size of the temporary memory available for use.
+ @param TempRamBase Base address of temporary ram
+ @param BootFirmwareVolume Base address of the Boot Firmware Volume.
+**/
+VOID
+NORETURN
+EFIAPI
+SecStartup (
+ IN UINTN BootHartId,
+ IN VOID *DeviceTreeAddress
+ );
+
+/**
+ Auto-generated function that calls the library constructors for all of the module's
+ dependent libraries. This function must be called by the SEC Core once a stack has
+ been established.
+
+**/
+VOID
+EFIAPI
+ProcessLibraryConstructorList (
+ VOID
+ );
+
+#endif
diff --git a/OvmfPkg/Sec/RiscV64/SecMain.c b/OvmfPkg/Sec/RiscV64/SecMain.c
new file mode 100644
index 000000000000..c8c852714a32
--- /dev/null
+++ b/OvmfPkg/Sec/RiscV64/SecMain.c
@@ -0,0 +1,573 @@
+/** @file
+ RISC-V SEC phase module.
+
+ Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SecMain.h"
+
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+EFI_STATUS
+EFIAPI
+TemporaryRamDone (
+ VOID
+ );
+
+STATIC EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
+ TemporaryRamMigration
+};
+
+STATIC EFI_PEI_TEMPORARY_RAM_DONE_PPI mTemporaryRamDonePpi = {
+ TemporaryRamDone
+};
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiTemporaryRamSupportPpiGuid,
+ &mTemporaryRamSupportPpi
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamDonePpiGuid,
+ &mTemporaryRamDonePpi
+ },
+};
+
+/** Temporary RAM migration function.
+
+ This function migrates the data from temporary RAM to permanent
+ memory.
+
+ @param[in] PeiServices PEI service
+ @param[in] TemporaryMemoryBase Temporary memory base address
+ @param[in] PermanentMemoryBase Permanent memory base address
+ @param[in] CopySize Size to copy
+
+**/
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ )
+{
+ VOID *OldHeap;
+ VOID *NewHeap;
+ VOID *OldStack;
+ VOID *NewStack;
+ EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Temp Mem Base:0x%Lx, Permanent Mem Base:0x%Lx, CopySize:0x%Lx\n",
+ __FUNCTION__,
+ TemporaryMemoryBase,
+ PermanentMemoryBase,
+ (UINT64)CopySize
+ ));
+
+ OldHeap = (VOID *)(UINTN)TemporaryMemoryBase;
+ NewHeap = (VOID *)((UINTN)PermanentMemoryBase + (CopySize >> 1));
+
+ OldStack = (VOID *)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
+ NewStack = (VOID *)(UINTN)PermanentMemoryBase;
+
+ CopyMem (NewHeap, OldHeap, CopySize >> 1); // Migrate Heap
+ CopyMem (NewStack, OldStack, CopySize >> 1); // Migrate Stack
+
+ //
+ // Reset firmware context pointer
+ //
+ GetFirmwareContextPointer (&FirmwareContext);
+ FirmwareContext = (VOID *)FirmwareContext + (unsigned long)((UINTN)NewStack - (UINTN)OldStack);
+ SetFirmwareContextPointer (FirmwareContext);
+
+ DEBUG ((DEBUG_INFO, "%a: Firmware Context is relocated to 0x%x\n", __FUNCTION__, FirmwareContext));
+
+ register UINTN a0 asm ("a0") = (UINTN)((UINTN)NewStack - (UINTN)OldStack);
+
+ asm volatile ("add sp, sp, a0"::"r"(a0):);
+ return EFI_SUCCESS;
+}
+
+/** Temprary RAM done function.
+
+**/
+EFI_STATUS EFIAPI
+TemporaryRamDone (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "%a: 2nd time PEI core, temporary ram done.\n", __FUNCTION__));
+ return EFI_SUCCESS;
+}
+
+/** Return platform SEC PPI before PEI Core
+
+ @param[in,out] ThisPpiList Pointer to retrieve EFI_PEI_PPI_DESCRIPTOR.
+
+**/
+STATIC EFI_STATUS
+GetPlatformPrePeiCorePpiDescriptor (
+ IN OUT EFI_PEI_PPI_DESCRIPTOR **ThisPpiList
+ )
+{
+ *ThisPpiList = mPrivateDispatchTable;
+ return EFI_SUCCESS;
+}
+
+/**
+ Locates the main boot firmware volume.
+
+ @param[in,out] BootFv On input, the base of the BootFv
+ On output, the decompressed main firmware volume
+
+ @retval EFI_SUCCESS The main firmware volume was located and decompressed
+ @retval EFI_NOT_FOUND The main firmware volume was not found
+
+**/
+EFI_STATUS
+FindMainFv (
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *Fv;
+ UINTN Distance;
+
+ ASSERT (((UINTN)*BootFv & EFI_PAGE_MASK) == 0);
+
+ Fv = *BootFv;
+ Distance = (UINTN)(*BootFv)->FvLength;
+ do {
+ Fv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)Fv + EFI_PAGE_SIZE);
+ Distance += EFI_PAGE_SIZE;
+ if (Distance > SIZE_32MB) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (Fv->Signature != EFI_FVH_SIGNATURE) {
+ continue;
+ }
+
+ if ((UINTN)Fv->FvLength < Distance) {
+ continue;
+ }
+
+ *BootFv = Fv;
+ return EFI_SUCCESS;
+ } while (TRUE);
+}
+
+/**
+ Locates the compressed main firmware volume and decompresses it.
+
+ @param[in,out] Fv On input, the firmware volume to search
+ On output, the decompressed BOOT/PEI FV
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+DecompressMemFvs (
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID_DEFINED_SECTION *Section;
+ UINT32 OutputBufferSize;
+ UINT32 ScratchBufferSize;
+ UINT16 SectionAttribute;
+ UINT32 AuthenticationStatus;
+ VOID *OutputBuffer;
+ VOID *ScratchBuffer;
+ EFI_COMMON_SECTION_HEADER *FvSection;
+ EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv;
+ EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv;
+ UINT32 FvHeaderSize;
+ UINT32 FvSectionSize;
+
+ FvSection = (EFI_COMMON_SECTION_HEADER *)NULL;
+
+ Status = FindFfsFileAndSection (
+ *Fv,
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
+ EFI_SECTION_GUID_DEFINED,
+ (EFI_COMMON_SECTION_HEADER **)&Section
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Unable to find GUID defined section\n"));
+ return Status;
+ }
+
+ Status = ExtractGuidedSectionGetInfo (
+ Section,
+ &OutputBufferSize,
+ &ScratchBufferSize,
+ &SectionAttribute
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Unable to GetInfo for GUIDed section\n"));
+ return Status;
+ }
+
+ OutputBuffer = (VOID *)((UINT8 *)(UINTN)PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);
+ ScratchBuffer = ALIGN_POINTER ((UINT8 *)OutputBuffer + OutputBufferSize, SIZE_1MB);
+
+ Status = ExtractGuidedSectionDecode (
+ Section,
+ &OutputBuffer,
+ ScratchBuffer,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Error during GUID section decode\n"));
+ return Status;
+ }
+
+ Status = FindFfsSectionInstance (
+ OutputBuffer,
+ OutputBufferSize,
+ EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+ 0,
+ &FvSection
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Unable to find PEI FV section\n"));
+ return Status;
+ }
+
+ ASSERT (
+ SECTION_SIZE (FvSection) ==
+ (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection))
+ );
+ ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+ PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfPeiMemFvBase);
+ CopyMem (PeiMemFv, (VOID *)(FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize));
+
+ if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));
+ CpuDeadLoop ();
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ Status = FindFfsSectionInstance (
+ OutputBuffer,
+ OutputBufferSize,
+ EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+ 1,
+ &FvSection
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Unable to find DXE FV section\n"));
+ return Status;
+ }
+
+ ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+ if (IS_SECTION2 (FvSection)) {
+ FvSectionSize = SECTION2_SIZE (FvSection);
+ FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
+ } else {
+ FvSectionSize = SECTION_SIZE (FvSection);
+ FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
+ }
+
+ ASSERT (FvSectionSize == (PcdGet32 (PcdOvmfDxeMemFvSize) + FvHeaderSize));
+
+ DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfDxeMemFvBase);
+ CopyMem (DxeMemFv, (VOID *)((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdOvmfDxeMemFvSize));
+
+ if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));
+ CpuDeadLoop ();
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ *Fv = PeiMemFv;
+ return EFI_SUCCESS;
+}
+
+/**
+ Locates the PEI Core entry point address
+
+ @param[in,out] Fv The firmware volume to search
+ @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+VOID
+FindPeiCoreImageBase (
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
+ OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
+ )
+{
+ *PeiCoreImageBase = 0;
+
+ FindMainFv (BootFv);
+
+ DecompressMemFvs (BootFv);
+
+ FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
+}
+
+/**
+ Find core image base.
+
+**/
+EFI_STATUS
+FindImageBase (
+ IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
+ OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase
+ )
+{
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
+ EFI_FFS_FILE_HEADER *File;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfFile;
+ EFI_COMMON_SECTION_HEADER *Section;
+ EFI_PHYSICAL_ADDRESS EndOfSection;
+
+ *SecCoreImageBase = 0;
+
+ CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BootFirmwareVolumePtr;
+ EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
+
+ //
+ // Loop through the FFS files in the Boot Firmware Volume
+ //
+ for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
+ CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
+ if (CurrentAddress > EndOfFirmwareVolume) {
+ return EFI_NOT_FOUND;
+ }
+
+ File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;
+ Size = FFS_FILE_SIZE (File);
+ if (Size < sizeof (*File)) {
+ return EFI_NOT_FOUND;
+ }
+
+ EndOfFile = CurrentAddress + Size;
+ if (EndOfFile > EndOfFirmwareVolume) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Look for SEC Core
+ //
+ if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
+ continue;
+ }
+
+ //
+ // Loop through the FFS file sections within the FFS file
+ //
+ EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)(File + 1);
+ for ( ; ;) {
+ CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
+ Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;
+
+ Size = SECTION_SIZE (Section);
+ if (Size < sizeof (*Section)) {
+ return EFI_NOT_FOUND;
+ }
+
+ EndOfSection = CurrentAddress + Size;
+ if (EndOfSection > EndOfFile) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Look for executable sections
+ //
+ if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {
+ if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
+ *SecCoreImageBase = (PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+ }
+
+ break;
+ }
+ }
+
+ //
+ // SEC Core image found
+ //
+ if (*SecCoreImageBase != 0) {
+ return EFI_SUCCESS;
+ }
+ }
+}
+
+/*
+ Find and return Pei Core entry point.
+
+ It also find SEC and PEI Core file debug information. It will report them if
+ remote debug is enabled.
+
+**/
+VOID
+FindAndReportEntryPoints (
+ IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
+ OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS SecCoreImageBase;
+ EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ //
+ // Find SEC Core and PEI Core image base
+ //
+ Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
+ ASSERT_EFI_ERROR (Status);
+
+ FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
+
+ ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+ //
+ // Report SEC Core debug information when remote debug is enabled
+ //
+ ImageContext.ImageAddress = SecCoreImageBase;
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+ //
+ // Report PEI Core debug information when remote debug is enabled
+ //
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+ //
+ // Find PEI Core entry point
+ //
+ Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, (VOID **)PeiCoreEntryPoint);
+ if (EFI_ERROR (Status)) {
+ *PeiCoreEntryPoint = 0;
+ }
+
+ return;
+}
+
+/**
+
+ Entry point to the C language phase of SEC. After the SEC assembly
+ code has initialized some temporary memory and set up the stack,
+ the control is transferred to this function.
+
+
+ @param[in] BootHartId Hardware thread ID of boot hart.
+ @param[in] DeviceTreeAddress Pointer to Device Tree (DTB)
+**/
+VOID
+NORETURN
+EFIAPI
+SecStartup (
+ IN UINTN BootHartId,
+ IN VOID *DeviceTreeAddress
+ )
+{
+ EFI_RISCV_FIRMWARE_CONTEXT FirmwareContext;
+ EFI_FIRMWARE_VOLUME_HEADER *BootFv;
+ EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
+ EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ EFI_SEC_PEI_HAND_OFF SecCoreData;
+ EFI_STATUS Status;
+
+ //
+ // Report Status Code to indicate entering SEC core
+ //
+ DEBUG ((
+ DEBUG_INFO,
+ "%a() BootHartId: 0x%x, DeviceTreeAddress=0x%x\n",
+ __FUNCTION__,
+ BootHartId,
+ DeviceTreeAddress
+ ));
+
+ //
+ // Process all libraries constructor function linked to SecCore.
+ //
+ ProcessLibraryConstructorList ();
+
+ BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)FixedPcdGet32 (PcdOvmfFdBaseAddress);
+
+ ASSERT (BootFv != NULL);
+ SecCoreData.DataSize = (UINT16)sizeof (EFI_SEC_PEI_HAND_OFF);
+ SecCoreData.BootFirmwareVolumeBase = BootFv;
+ SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
+ SecCoreData.TemporaryRamBase = (VOID *)(UINT64)FixedPcdGet32 (PcdOvmfSecPeiTempRamBase);
+ SecCoreData.TemporaryRamSize = (UINTN)FixedPcdGet32 (PcdOvmfSecPeiTempRamSize);
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+ SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
+ SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + (SecCoreData.TemporaryRamSize >> 1);
+ SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a() BFV Base: 0x%x, BFV Size: 0x%x, TempRAM Base: 0x%x, TempRAM Size: 0x%x, PeiTempRamBase: 0x%x, PeiTempRamSize: 0x%x, StackBase: 0x%x, StackSize: 0x%x\n",
+ __FUNCTION__,
+ SecCoreData.BootFirmwareVolumeBase,
+ SecCoreData.BootFirmwareVolumeSize,
+ SecCoreData.TemporaryRamBase,
+ SecCoreData.TemporaryRamSize,
+ SecCoreData.PeiTemporaryRamBase,
+ SecCoreData.PeiTemporaryRamSize,
+ SecCoreData.StackBase,
+ SecCoreData.StackSize
+ ));
+
+ FindAndReportEntryPoints (
+ &BootFv,
+ &PeiCoreEntryPoint
+ );
+ if (PeiCoreEntryPoint == NULL) {
+ CpuDeadLoop ();
+ }
+
+ SecCoreData.BootFirmwareVolumeBase = BootFv;
+ SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
+
+ Status = GetPlatformPrePeiCorePpiDescriptor (&PpiList);
+ if (EFI_ERROR (Status)) {
+ PpiList = NULL;
+ }
+
+ FirmwareContext.BootHartId = BootHartId;
+ FirmwareContext.FlattenedDeviceTree = (UINT64)DeviceTreeAddress;
+ SetFirmwareContextPointer (&FirmwareContext);
+
+ //
+ // Transfer the control to the PEI core
+ //
+ ASSERT (PeiCoreEntryPoint != NULL);
+ (*PeiCoreEntryPoint)(&SecCoreData, PpiList);
+
+ //
+ // Should not come here.
+ //
+ UNREACHABLE ();
+}
diff --git a/OvmfPkg/Sec/RiscV64/SecEntry.S b/OvmfPkg/Sec/RiscV64/SecEntry.S
new file mode 100644
index 000000000000..d201e9f8a608
--- /dev/null
+++ b/OvmfPkg/Sec/RiscV64/SecEntry.S
@@ -0,0 +1,23 @@
+/*
+ Copyright (c) 2021-2022 , Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ Copyright (c) 2022 Ventana Micro Systems Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ */
+
+#include "SecMain.h"
+
+.text
+.align 3
+
+ASM_FUNC (_ModuleEntryPoint)
+ /* Use Temp memory as the stack for calling to C code */
+ li a4, FixedPcdGet32 (PcdOvmfSecPeiTempRamBase)
+ li a5, FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)
+
+ /* Use Temp memory as the stack for calling to C code */
+ add sp, a4, a5
+
+ call SecStartup
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 11/29] OvmfPkg/PlatformPei: Refactor to allow other architectures
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (9 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 10/29] OvmfPkg/Sec: Add RISC-V support Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 12/29] OvmfPkg/PlatformPei: Add support for RISC-V Sunil V L
` (17 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Currently, PlatformPei supports only X86 architecture. So,
refactor it to allow other CPU architectures.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/PlatformPei/PlatformPei.inf | 34 +++++++++++--------
OvmfPkg/PlatformPei/{ => Ia32_X64}/Platform.h | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/AmdSev.c | 0
.../PlatformPei/{ => Ia32_X64}/ClearCache.c | 0
.../{ => Ia32_X64}/FeatureControl.c | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/Fv.c | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/IntelTdx.c | 0
.../PlatformPei/{ => Ia32_X64}/MemDetect.c | 0
.../PlatformPei/{ => Ia32_X64}/MemTypeInfo.c | 0
OvmfPkg/PlatformPei/{ => Ia32_X64}/Platform.c | 0
10 files changed, 19 insertions(+), 15 deletions(-)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/Platform.h (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/AmdSev.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/ClearCache.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/FeatureControl.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/Fv.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/IntelTdx.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/MemDetect.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/MemTypeInfo.c (100%)
rename OvmfPkg/PlatformPei/{ => Ia32_X64}/Platform.c (100%)
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 3cd83e6ec3e5..683ebf1a440a 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -22,16 +22,16 @@ [Defines]
# VALID_ARCHITECTURES = IA32 X64 EBC
#
-[Sources]
- AmdSev.c
- ClearCache.c
- FeatureControl.c
- Fv.c
- MemDetect.c
- MemTypeInfo.c
- Platform.c
- Platform.h
- IntelTdx.c
+[Sources.IA32, Sources.X64]
+ Ia32_X64/AmdSev.c
+ Ia32_X64/ClearCache.c
+ Ia32_X64/FeatureControl.c
+ Ia32_X64/Fv.c
+ Ia32_X64/MemDetect.c
+ Ia32_X64/MemTypeInfo.c
+ Ia32_X64/Platform.c
+ Ia32_X64/Platform.h
+ Ia32_X64/IntelTdx.c
[Packages]
EmbeddedPkg/EmbeddedPkg.dec
@@ -57,14 +57,16 @@ [LibraryClasses]
PeiServicesLib
PeiServicesTablePointerLib
PeimEntryPoint
+ PcdLib
+ PlatformInitLib
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ MtrrLib
+ VmgExitLib
QemuFwCfgLib
QemuFwCfgS3Lib
QemuFwCfgSimpleParserLib
- MtrrLib
MemEncryptSevLib
- PcdLib
- VmgExitLib
- PlatformInitLib
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
@@ -99,7 +101,6 @@ [Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
- gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable
@@ -116,6 +117,9 @@ [Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures
gEfiMdeModulePkgTokenSpaceGuid.PcdTdxSharedBitMask
+[Pcd.IA32, Pcd.X64]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+
[FixedPcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize
diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Ia32_X64/Platform.h
similarity index 100%
rename from OvmfPkg/PlatformPei/Platform.h
rename to OvmfPkg/PlatformPei/Ia32_X64/Platform.h
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/Ia32_X64/AmdSev.c
similarity index 100%
rename from OvmfPkg/PlatformPei/AmdSev.c
rename to OvmfPkg/PlatformPei/Ia32_X64/AmdSev.c
diff --git a/OvmfPkg/PlatformPei/ClearCache.c b/OvmfPkg/PlatformPei/Ia32_X64/ClearCache.c
similarity index 100%
rename from OvmfPkg/PlatformPei/ClearCache.c
rename to OvmfPkg/PlatformPei/Ia32_X64/ClearCache.c
diff --git a/OvmfPkg/PlatformPei/FeatureControl.c b/OvmfPkg/PlatformPei/Ia32_X64/FeatureControl.c
similarity index 100%
rename from OvmfPkg/PlatformPei/FeatureControl.c
rename to OvmfPkg/PlatformPei/Ia32_X64/FeatureControl.c
diff --git a/OvmfPkg/PlatformPei/Fv.c b/OvmfPkg/PlatformPei/Ia32_X64/Fv.c
similarity index 100%
rename from OvmfPkg/PlatformPei/Fv.c
rename to OvmfPkg/PlatformPei/Ia32_X64/Fv.c
diff --git a/OvmfPkg/PlatformPei/IntelTdx.c b/OvmfPkg/PlatformPei/Ia32_X64/IntelTdx.c
similarity index 100%
rename from OvmfPkg/PlatformPei/IntelTdx.c
rename to OvmfPkg/PlatformPei/Ia32_X64/IntelTdx.c
diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/Ia32_X64/MemDetect.c
similarity index 100%
rename from OvmfPkg/PlatformPei/MemDetect.c
rename to OvmfPkg/PlatformPei/Ia32_X64/MemDetect.c
diff --git a/OvmfPkg/PlatformPei/MemTypeInfo.c b/OvmfPkg/PlatformPei/Ia32_X64/MemTypeInfo.c
similarity index 100%
rename from OvmfPkg/PlatformPei/MemTypeInfo.c
rename to OvmfPkg/PlatformPei/Ia32_X64/MemTypeInfo.c
diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Ia32_X64/Platform.c
similarity index 100%
rename from OvmfPkg/PlatformPei/Platform.c
rename to OvmfPkg/PlatformPei/Ia32_X64/Platform.c
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 12/29] OvmfPkg/PlatformPei: Add support for RISC-V
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (10 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 11/29] OvmfPkg/PlatformPei: Refactor to allow other architectures Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 13/29] UefiCpuPkg/CpuTimerLib: Refactor to allow other architectures Sunil V L
` (16 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This is mostly copied from
edk2-platforms/Platform/RISC-V/PlatformPkg/Universal/Pei/PlatformPei
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/PlatformPei/PlatformPei.inf | 9 +
OvmfPkg/PlatformPei/RiscV64/Platform.h | 97 ++++++
OvmfPkg/PlatformPei/RiscV64/Fv.c | 81 ++++++
OvmfPkg/PlatformPei/RiscV64/MemDetect.c | 212 ++++++++++++++
OvmfPkg/PlatformPei/RiscV64/Platform.c | 372 ++++++++++++++++++++++++
5 files changed, 771 insertions(+)
create mode 100644 OvmfPkg/PlatformPei/RiscV64/Platform.h
create mode 100644 OvmfPkg/PlatformPei/RiscV64/Fv.c
create mode 100644 OvmfPkg/PlatformPei/RiscV64/MemDetect.c
create mode 100644 OvmfPkg/PlatformPei/RiscV64/Platform.c
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 683ebf1a440a..0bae88f6d01b 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -33,6 +33,12 @@ [Sources.IA32, Sources.X64]
Ia32_X64/Platform.h
Ia32_X64/IntelTdx.c
+[Sources.RISCV64]
+ RiscV64/Fv.c
+ RiscV64/MemDetect.c
+ RiscV64/Platform.c
+ RiscV64/Platform.h
+
[Packages]
EmbeddedPkg/EmbeddedPkg.dec
MdePkg/MdePkg.dec
@@ -68,6 +74,9 @@ [LibraryClasses.IA32, LibraryClasses.X64]
QemuFwCfgSimpleParserLib
MemEncryptSevLib
+[LibraryClasses.RISCV64]
+ RiscVSbiLib
+
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
diff --git a/OvmfPkg/PlatformPei/RiscV64/Platform.h b/OvmfPkg/PlatformPei/RiscV64/Platform.h
new file mode 100644
index 000000000000..6c23c722a360
--- /dev/null
+++ b/OvmfPkg/PlatformPei/RiscV64/Platform.h
@@ -0,0 +1,97 @@
+/** @file
+ Platform PEI module include file.
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PLATFORM_PEI_H_INCLUDED_
+#define PLATFORM_PEI_H_INCLUDED_
+
+VOID
+AddIoMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddIoMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ );
+
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ );
+
+VOID
+AddUntestedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddUntestedMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ );
+
+VOID
+AddressWidthInitialization (
+ VOID
+ );
+
+EFI_STATUS
+PublishPeiMemory (
+ VOID
+ );
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+ VOID
+ );
+
+VOID
+InitializeRamRegions (
+ VOID
+ );
+
+EFI_STATUS
+PeiFvInitialization (
+ VOID
+ );
+
+EFI_STATUS
+InitializeXen (
+ VOID
+ );
+
+/**
+ Build processor and platform information for the U5 platform
+
+ @return EFI_SUCCESS Status.
+
+**/
+EFI_STATUS
+BuildRiscVSmbiosHobs (
+ VOID
+ );
+
+#endif // _PLATFORM_PEI_H_INCLUDED_
diff --git a/OvmfPkg/PlatformPei/RiscV64/Fv.c b/OvmfPkg/PlatformPei/RiscV64/Fv.c
new file mode 100644
index 000000000000..ff99c1432935
--- /dev/null
+++ b/OvmfPkg/PlatformPei/RiscV64/Fv.c
@@ -0,0 +1,81 @@
+/** @file
+ Build FV related hobs for platform.
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+ Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PiPei.h"
+#include "Platform.h"
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+
+/**
+ Publish PEI & DXE (Decompressed) Memory based FVs to let PEI
+ and DXE know about them.
+
+ @retval EFI_SUCCESS Platform PEI FVs were initialized successfully.
+
+**/
+EFI_STATUS
+PeiFvInitialization (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "Platform PEI Firmware Volume Initialization\n"));
+
+ // Create a memory allocation HOB for the DXE FV.
+ //
+ // If "secure" S3 is needed, then SEC will decompress both PEI and DXE
+ // firmware volumes at S3 resume too, hence we need to keep away the OS from
+ // DXEFV as well. Otherwise we only need to keep away DXE itself from the
+ // DXEFV area.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdOvmfPeiMemFvBase),
+ PcdGet32 (PcdOvmfPeiMemFvSize),
+ EfiBootServicesData
+ );
+
+ //
+ // Let DXE know about the DXE FV
+ //
+ BuildFvHob (PcdGet32 (PcdOvmfDxeMemFvBase), PcdGet32 (PcdOvmfDxeMemFvSize));
+ DEBUG ((
+ DEBUG_INFO,
+ "Platform builds DXE FV at %x, size %x.\n",
+ PcdGet32 (PcdOvmfDxeMemFvBase),
+ PcdGet32 (PcdOvmfDxeMemFvSize)
+ ));
+
+ // Create a memory allocation HOB for the DXE FV.
+ //
+ // If "secure" S3 is needed, then SEC will decompress both PEI and DXE
+ // firmware volumes at S3 resume too, hence we need to keep away the OS from
+ // DXEFV as well. Otherwise we only need to keep away DXE itself from the
+ // DXEFV area.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdOvmfDxeMemFvBase),
+ PcdGet32 (PcdOvmfDxeMemFvSize),
+ EfiBootServicesData
+ );
+
+ //
+ // Let PEI know about the DXE FV so it can find the DXE Core
+ //
+ PeiServicesInstallFvInfoPpi (
+ NULL,
+ (VOID *)(UINTN)PcdGet32 (PcdOvmfDxeMemFvBase),
+ PcdGet32 (PcdOvmfDxeMemFvSize),
+ NULL,
+ NULL
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/PlatformPei/RiscV64/MemDetect.c b/OvmfPkg/PlatformPei/RiscV64/MemDetect.c
new file mode 100644
index 000000000000..eb9d24581f8d
--- /dev/null
+++ b/OvmfPkg/PlatformPei/RiscV64/MemDetect.c
@@ -0,0 +1,212 @@
+/** @file
+ Memory Detection for Virtual Machines.
+
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ MemDetect.c
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+
+#include <libfdt.h>
+
+#include <Guid/FdtHob.h>
+
+#include "Platform.h"
+
+STATIC EFI_PHYSICAL_ADDRESS SystemMemoryBase;
+STATIC UINT64 SystemMemorySize;
+STATIC EFI_PHYSICAL_ADDRESS MmodeResvBase;
+STATIC UINT64 MmodeResvSize;
+
+/**
+ Publish PEI core memory.
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+PublishPeiMemory (
+ VOID
+ )
+{
+ EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
+ EFI_PHYSICAL_ADDRESS MemoryBase;
+ CONST UINT64 *RegProp;
+ CONST CHAR8 *Type;
+ EFI_STATUS Status;
+ UINT64 CurBase, CurSize;
+ UINT64 NewBase = 0, NewSize = 0;
+ UINT64 MemorySize;
+ INT32 Node, Prev;
+ INT32 Len;
+ VOID *FdtPointer;
+
+ FirmwareContext = NULL;
+ GetFirmwareContextPointer (&FirmwareContext);
+
+ if (FirmwareContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Firmware Context is NULL\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ FdtPointer = (VOID *)FirmwareContext->FlattenedDeviceTree;
+ if (FdtPointer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid FDT pointer\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ // Look for the lowest memory node
+ for (Prev = 0; ; Prev = Node) {
+ Node = fdt_next_node (FdtPointer, Prev, NULL);
+ if (Node < 0) {
+ break;
+ }
+
+ // Check for memory node
+ Type = fdt_getprop (FdtPointer, Node, "device_type", &Len);
+ if (Type && (AsciiStrnCmp (Type, "memory", Len) == 0)) {
+ // Get the 'reg' property of this node. For now, we will assume
+ // two 8 byte quantities for base and size, respectively.
+ RegProp = fdt_getprop (FdtPointer, Node, "reg", &Len);
+ if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
+ CurBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+ CurSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: System RAM @ 0x%lx - 0x%lx\n",
+ __FUNCTION__,
+ CurBase,
+ CurBase + CurSize - 1
+ ));
+
+ if ((NewBase > CurBase) || (NewBase == 0)) {
+ NewBase = CurBase;
+ NewSize = CurSize;
+ }
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to parse FDT memory node\n",
+ __FUNCTION__
+ ));
+ }
+ }
+ }
+
+ SystemMemoryBase = NewBase;
+ SystemMemorySize = NewSize;
+
+ /* try to locate the reserved memory opensbi node */
+ Node = fdt_path_offset (FdtPointer, "/reserved-memory/mmode_resv0");
+ if (Node >= 0) {
+ RegProp = fdt_getprop (FdtPointer, Node, "reg", &Len);
+ if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
+ NewBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+ NewSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: M-mode Base = 0x%lx, M-mode Size = 0x%lx\n",
+ __FUNCTION__,
+ NewBase,
+ NewSize
+ ));
+ MmodeResvBase = NewBase;
+ MmodeResvSize = NewSize;
+ }
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: SystemMemoryBase:0x%x SystemMemorySize:%x\n",
+ __FUNCTION__,
+ SystemMemoryBase,
+ SystemMemorySize
+ ));
+
+ //
+ // Initial 16MB needs to be reserved
+ //
+ MemoryBase = SystemMemoryBase + SIZE_16MB;
+ MemorySize = SystemMemorySize - SIZE_16MB;
+
+ //
+ // Publish this memory to the PEI Core
+ //
+ Status = PublishSystemMemory (MemoryBase, MemorySize);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Publish system RAM and reserve memory regions.
+
+**/
+VOID
+InitializeRamRegions (
+ VOID
+ )
+{
+ /*
+ * M-mode FW can be loaded anywhere in memory but should not overlap
+ * with the EDK2. This can happen if some other boot code loads the
+ * M-mode firmware.
+ *
+ * The M-mode firmware memory should be marked as reserved memory
+ * so that OS doesn't use it.
+ */
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: M-mode FW Memory Start:0x%lx End:0x%lx\n",
+ __FUNCTION__,
+ MmodeResvBase,
+ MmodeResvBase + MmodeResvSize
+ ));
+ AddReservedMemoryBaseSizeHob (MmodeResvBase, MmodeResvSize);
+
+ if (MmodeResvBase > SystemMemoryBase) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Free Memory Start:0x%lx End:0x%lx\n",
+ __FUNCTION__,
+ SystemMemoryBase,
+ MmodeResvBase
+ ));
+ AddMemoryRangeHob (SystemMemoryBase, MmodeResvBase);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Free Memory Start:0x%lx End:0x%lx\n",
+ __FUNCTION__,
+ MmodeResvBase + MmodeResvSize,
+ SystemMemoryBase + SystemMemorySize
+ ));
+ AddMemoryRangeHob (
+ MmodeResvBase + MmodeResvSize,
+ SystemMemoryBase + SystemMemorySize
+ );
+}
diff --git a/OvmfPkg/PlatformPei/RiscV64/Platform.c b/OvmfPkg/PlatformPei/RiscV64/Platform.c
new file mode 100644
index 000000000000..45a2f44d9cca
--- /dev/null
+++ b/OvmfPkg/PlatformPei/RiscV64/Platform.c
@@ -0,0 +1,372 @@
+/** @file
+ Platform PEI driver
+
+ Copyright (c) 2019-2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/PlatformInitLib.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Ppi/MasterBootMode.h>
+#include <IndustryStandard/Pci22.h>
+
+#include "Platform.h"
+
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
+ { EfiACPIMemoryNVS, 0x004 },
+ { EfiACPIReclaimMemory, 0x008 },
+ { EfiReservedMemoryType, 0x004 },
+ { EfiRuntimeServicesData, 0x024 },
+ { EfiRuntimeServicesCode, 0x030 },
+ { EfiBootServicesCode, 0x180 },
+ { EfiBootServicesData, 0xF00 },
+ { EfiMaxMemoryType, 0x000 }
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPeiMasterBootModePpiGuid,
+ NULL
+ }
+};
+
+STATIC EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+/**
+ Build memory map I/O range resource HOB using the
+ base address and size.
+
+ @param MemoryBase Memory map I/O base.
+ @param MemorySize Memory map I/O size.
+
+**/
+VOID
+AddIoMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_MAPPED_IO,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Build reserved memory range resource HOB.
+
+ @param MemoryBase Reserved memory range base address.
+ @param MemorySize Reserved memory range size.
+
+**/
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_RESERVED,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Build memory map I/O resource using the base address
+ and the top address of memory range.
+
+ @param MemoryBase Memory map I/O range base address.
+ @param MemoryLimit The top address of memory map I/O range
+
+**/
+VOID
+AddIoMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+/**
+ Create memory range resource HOB using the memory base
+ address and size.
+
+ @param MemoryBase Memory range base address.
+ @param MemorySize Memory range size.
+
+**/
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Create memory range resource HOB using memory base
+ address and top address of the memory range.
+
+ @param MemoryBase Memory range base address.
+ @param MemoryLimit Memory range size.
+
+**/
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+/**
+ Create untested memory range resource HOB using memory base
+ address and top address of the memory range.
+
+ @param MemoryBase Memory range base address.
+ @param MemorySize Memory range size.
+
+**/
+VOID
+AddUntestedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Create untested memory range resource HOB using memory base
+ address and top address of the memory range.
+
+ @param MemoryBase Memory range base address.
+ @param MemoryLimit Memory range size.
+
+**/
+VOID
+AddUntestedMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddUntestedMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+/**
+ Add PCI resource.
+
+**/
+VOID
+AddPciResource (
+ VOID
+ )
+{
+ //
+ // Platform-specific
+ //
+}
+
+/**
+ Platform memory map initialization.
+
+**/
+VOID
+MemMapInitialization (
+ VOID
+ )
+{
+ //
+ // Create Memory Type Information HOB
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ mDefaultMemoryTypeInformation,
+ sizeof (mDefaultMemoryTypeInformation)
+ );
+
+ //
+ // Add PCI IO Port space available for PCI resource allocations.
+ //
+ AddPciResource ();
+}
+
+/**
+ Platform misc initialization.
+
+**/
+VOID
+MiscInitialization (
+ VOID
+ )
+{
+ //
+ // Build the CPU HOB with guest RAM size dependent address width and 16-bits
+ // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
+ // S3 resume as well, so we build it unconditionally.)
+ //
+ // TODO: Determine this dynamically from the platform
+ // setting or the HART configuration.
+ //
+ BuildCpuHob (56, 32);
+}
+
+/**
+ Check if system returns from S3.
+
+ @return BOOLEAN TRUE, system returned from S3
+ FALSE, system is not returned from S3
+
+**/
+BOOLEAN
+CheckResumeFromS3 (
+ VOID
+ )
+{
+ //
+ // Platform implementation-specific
+ //
+ return FALSE;
+}
+
+/**
+ Platform boot mode initialization.
+
+**/
+VOID
+BootModeInitialization (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (CheckResumeFromS3 ()) {
+ DEBUG ((DEBUG_INFO, "This is wake from S3\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "This is normal boot\n"));
+ }
+
+ Status = PeiServicesSetBootMode (mBootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesInstallPpi (mPpiBootMode);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Build processor information for U54 Coreplex processor.
+
+ @return EFI_SUCCESS Status.
+
+**/
+EFI_STATUS
+BuildCoreInformationHob (
+ VOID
+ )
+{
+ // return BuildRiscVSmbiosHobs ();
+ return EFI_SUCCESS;
+}
+
+/**
+ Perform Platform PEI initialization.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePlatform (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
+ Status = PlatformPeim ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "PlatformPeim failed\n"));
+ ASSERT (FALSE);
+ }
+
+ BootModeInitialization ();
+ DEBUG ((DEBUG_INFO, "Platform BOOT mode initiated.\n"));
+ PublishPeiMemory ();
+ DEBUG ((DEBUG_INFO, "PEI memory published.\n"));
+ InitializeRamRegions ();
+ DEBUG ((DEBUG_INFO, "Platform RAM regions initiated.\n"));
+
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ PeiFvInitialization ();
+ MemMapInitialization ();
+ }
+
+ MiscInitialization ();
+ Status = BuildCoreInformationHob ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to build processor information HOB.\n"));
+ ASSERT (FALSE);
+ }
+
+ return EFI_SUCCESS;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 13/29] UefiCpuPkg/CpuTimerLib: Refactor to allow other architectures
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (11 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 12/29] OvmfPkg/PlatformPei: Add support for RISC-V Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 14/29] UefiCpuPkg/CpuTimerLib: Add support for RISC-V Sunil V L
` (15 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Currently, CpuTimerLib library supports only X86 architecture.
Refactor to allow other CPU architectures.
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf | 6 +++---
.../Library/CpuTimerLib/{ => Ia32_X64}/BaseCpuTimerLib.c | 0
UefiCpuPkg/Library/CpuTimerLib/{ => Ia32_X64}/CpuTimerLib.c | 0
3 files changed, 3 insertions(+), 3 deletions(-)
rename UefiCpuPkg/Library/CpuTimerLib/{ => Ia32_X64}/BaseCpuTimerLib.c (100%)
rename UefiCpuPkg/Library/CpuTimerLib/{ => Ia32_X64}/CpuTimerLib.c (100%)
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
index de0648de91b5..a22457b44940 100644
--- a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
@@ -18,9 +18,9 @@ [Defines]
LIBRARY_CLASS = TimerLib
MODULE_UNI_FILE = BaseCpuTimerLib.uni
-[Sources]
- CpuTimerLib.c
- BaseCpuTimerLib.c
+[Sources.IA32, Sources.X64]
+ Ia32_X64/CpuTimerLib.c
+ Ia32_X64/BaseCpuTimerLib.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/Ia32_X64/BaseCpuTimerLib.c
similarity index 100%
rename from UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
rename to UefiCpuPkg/Library/CpuTimerLib/Ia32_X64/BaseCpuTimerLib.c
diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/Ia32_X64/CpuTimerLib.c
similarity index 100%
rename from UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
rename to UefiCpuPkg/Library/CpuTimerLib/Ia32_X64/CpuTimerLib.c
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 14/29] UefiCpuPkg/CpuTimerLib: Add support for RISC-V
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (12 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 13/29] UefiCpuPkg/CpuTimerLib: Refactor to allow other architectures Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 15/29] UefiCpuPkg/CpuExceptionHandlerLib: Refactor to allow other architectures Sunil V L
` (14 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar, Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This is mostly copied from
edk2-platforms/Silicon/RISC-V/ProcessorPkg/Library/RiscVTimerLib
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
.../Library/CpuTimerLib/BaseCpuTimerLib.inf | 3 +
.../Library/CpuTimerLib/RiscV64/CpuTimerLib.c | 199 ++++++++++++++++++
2 files changed, 202 insertions(+)
create mode 100644 UefiCpuPkg/Library/CpuTimerLib/RiscV64/CpuTimerLib.c
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
index a22457b44940..554ce9fe9db8 100644
--- a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
@@ -22,6 +22,9 @@ [Sources.IA32, Sources.X64]
Ia32_X64/CpuTimerLib.c
Ia32_X64/BaseCpuTimerLib.c
+[Sources.RISCV64]
+ RiscV64/CpuTimerLib.c
+
[Packages]
MdePkg/MdePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
diff --git a/UefiCpuPkg/Library/CpuTimerLib/RiscV64/CpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/RiscV64/CpuTimerLib.c
new file mode 100644
index 000000000000..9c8efc0f3530
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/RiscV64/CpuTimerLib.c
@@ -0,0 +1,199 @@
+/** @file
+ RISC-V instance of Timer Library.
+
+ Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Register/RiscV64/RiscVImpl.h>
+
+/**
+ Stalls the CPU for at least the given number of ticks.
+
+ Stalls the CPU for at least the given number of ticks. It's invoked by
+ MicroSecondDelay() and NanoSecondDelay().
+
+ @param Delay A period of time to delay in ticks.
+
+**/
+VOID
+InternalRiscVTimerDelay (
+ IN UINT32 Delay
+ )
+{
+ UINT32 Ticks;
+ UINT32 Times;
+
+ Times = Delay >> (RISCV_TIMER_COMPARE_BITS - 2);
+ Delay &= ((1 << (RISCV_TIMER_COMPARE_BITS - 2)) - 1);
+ do {
+ //
+ // The target timer count is calculated here
+ //
+ Ticks = RiscVReadTimer () + Delay;
+ Delay = 1 << (RISCV_TIMER_COMPARE_BITS - 2);
+ while (((Ticks - RiscVReadTimer ()) & (1 << (RISCV_TIMER_COMPARE_BITS - 1))) == 0) {
+ CpuPause ();
+ }
+ } while (Times-- > 0);
+}
+
+/**
+ Stalls the CPU for at least the given number of microseconds.
+
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param MicroSeconds The minimum number of microseconds to delay.
+
+ @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+ InternalRiscVTimerDelay (
+ (UINT32)DivU64x32 (
+ MultU64x32 (
+ MicroSeconds,
+ PcdGet64 (PcdCpuCoreCrystalClockFrequency)
+ ),
+ 1000000u
+ )
+ );
+ return MicroSeconds;
+}
+
+/**
+ Stalls the CPU for at least the given number of nanoseconds.
+
+ Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+ @param NanoSeconds The minimum number of nanoseconds to delay.
+
+ @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+ IN UINTN NanoSeconds
+ )
+{
+ InternalRiscVTimerDelay (
+ (UINT32)DivU64x32 (
+ MultU64x32 (
+ NanoSeconds,
+ PcdGet64 (PcdCpuCoreCrystalClockFrequency)
+ ),
+ 1000000000u
+ )
+ );
+ return NanoSeconds;
+}
+
+/**
+ Retrieves the current value of a 64-bit free running performance counter.
+
+ Retrieves the current value of a 64-bit free running performance counter. The
+ counter can either count up by 1 or count down by 1. If the physical
+ performance counter counts by a larger increment, then the counter values
+ must be translated. The properties of the counter can be retrieved from
+ GetPerformanceCounterProperties().
+
+ @return The current value of the free running performance counter.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounter (
+ VOID
+ )
+{
+ return (UINT64)RiscVReadTimer ();
+}
+
+/**return
+ Retrieves the 64-bit frequency in Hz and the range of performance counter
+ values.
+
+ If StartValue is not NULL, then the value that the performance counter starts
+ with immediately after is it rolls over is returned in StartValue. If
+ EndValue is not NULL, then the value that the performance counter end with
+ immediately before it rolls over is returned in EndValue. The 64-bit
+ frequency of the performance counter in Hz is always returned. If StartValue
+ is less than EndValue, then the performance counter counts up. If StartValue
+ is greater than EndValue, then the performance counter counts down. For
+ example, a 64-bit free running counter that counts up would have a StartValue
+ of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+ that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+ @param StartValue The value the performance counter starts with when it
+ rolls over.
+ @param EndValue The value that the performance counter ends with before
+ it rolls over.
+
+ @return The frequency in Hz.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+ OUT UINT64 *StartValue, OPTIONAL
+ OUT UINT64 *EndValue OPTIONAL
+ )
+{
+ if (StartValue != NULL) {
+ *StartValue = 0;
+ }
+
+ if (EndValue != NULL) {
+ *EndValue = 32 - 1;
+ }
+
+ return PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+}
+
+/**
+ Converts elapsed ticks of performance counter to time in nanoseconds.
+
+ This function converts the elapsed ticks of running performance counter to
+ time value in unit of nanoseconds.
+
+ @param Ticks The number of elapsed ticks of running performance counter.
+
+ @return The elapsed time in nanoseconds.
+
+**/
+UINT64
+EFIAPI
+GetTimeInNanoSecond (
+ IN UINT64 Ticks
+ )
+{
+ UINT64 NanoSeconds;
+ UINT32 Remainder;
+
+ //
+ // Ticks
+ // Time = --------- x 1,000,000,000
+ // Frequency
+ //
+ NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, PcdGet64 (PcdCpuCoreCrystalClockFrequency), &Remainder), 1000000000u);
+
+ //
+ // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)
+ // will not overflow 64-bit.
+ //
+ NanoSeconds += DivU64x32 (MultU64x32 ((UINT64)Remainder, 1000000000u), PcdGet64 (PcdCpuCoreCrystalClockFrequency));
+
+ return NanoSeconds;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 15/29] UefiCpuPkg/CpuExceptionHandlerLib: Refactor to allow other architectures
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (13 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 14/29] UefiCpuPkg/CpuTimerLib: Add support for RISC-V Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 16/29] UefiCpuPkg/CpuExceptionHandlerLib: Add support for RISC-V Sunil V L
` (13 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Currently, the CpuExceptionHandlerLib library supports only X86.
Refactor the library to allow adding other CPU architectures.
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
.../DxeCpuExceptionHandlerLib.inf | 14 ++++++++------
.../PeiCpuExceptionHandlerLib.inf | 8 ++++----
.../SecPeiCpuExceptionHandlerLib.inf | 12 +++++++-----
.../SmmCpuExceptionHandlerLib.inf | 8 ++++----
.../Xcode5SecPeiCpuExceptionHandlerLib.inf | 6 +++---
.../{ => Ia32_X64}/CpuExceptionCommon.h | 0
.../{ => Ia32_X64}/CpuExceptionCommon.c | 0
.../{ => Ia32_X64}/DxeException.c | 0
.../{ => Ia32_X64}/PeiCpuException.c | 0
.../{ => Ia32_X64}/PeiDxeSmmCpuException.c | 0
.../{ => Ia32_X64}/SecPeiCpuException.c | 0
.../{ => Ia32_X64}/SmmException.c | 0
12 files changed, 26 insertions(+), 22 deletions(-)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/CpuExceptionCommon.h (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/CpuExceptionCommon.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/DxeException.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/PeiCpuException.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/PeiDxeSmmCpuException.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/SecPeiCpuException.c (100%)
rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{ => Ia32_X64}/SmmException.c (100%)
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
index e7a81bebdb13..ef07b05c080a 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
@@ -32,11 +32,11 @@ [Sources.X64]
X64/ArchExceptionHandler.c
X64/ArchInterruptDefs.h
-[Sources.common]
- CpuExceptionCommon.h
- CpuExceptionCommon.c
- PeiDxeSmmCpuException.c
- DxeException.c
+[Sources.IA32, Sources.X64]
+ Ia32_X64/CpuExceptionCommon.h
+ Ia32_X64/CpuExceptionCommon.c
+ Ia32_X64/PeiDxeSmmCpuException.c
+ Ia32_X64/DxeException.c
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
@@ -56,8 +56,10 @@ [LibraryClasses]
SerialPortLib
PrintLib
SynchronizationLib
- LocalApicLib
PeCoffGetEntryPointLib
MemoryAllocationLib
DebugLib
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ LocalApicLib
VmgExitLib
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
index 7c2ec3b2db4c..7e7e1a4296de 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
@@ -33,10 +33,10 @@ [Sources.X64]
X64/ArchInterruptDefs.h
[Sources.common]
- CpuExceptionCommon.h
- CpuExceptionCommon.c
- PeiCpuException.c
- PeiDxeSmmCpuException.c
+ Ia32_X64/CpuExceptionCommon.h
+ Ia32_X64/CpuExceptionCommon.c
+ Ia32_X64/PeiCpuException.c
+ Ia32_X64/PeiDxeSmmCpuException.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
index 6a170286c8fc..28341abd4493 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
@@ -32,10 +32,10 @@ [Sources.X64]
X64/ArchExceptionHandler.c
X64/ArchInterruptDefs.h
-[Sources.common]
- CpuExceptionCommon.h
- CpuExceptionCommon.c
- SecPeiCpuException.c
+[Sources.IA32, Sources.X64]
+ Ia32_X64/CpuExceptionCommon.h
+ Ia32_X64/CpuExceptionCommon.c
+ Ia32_X64/SecPeiCpuException.c
[Packages]
MdePkg/MdePkg.dec
@@ -46,8 +46,10 @@ [LibraryClasses]
BaseLib
SerialPortLib
PrintLib
- LocalApicLib
PeCoffGetEntryPointLib
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ LocalApicLib
VmgExitLib
[Pcd]
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
index 9dde07612a04..b7f395f45ab4 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
@@ -33,10 +33,10 @@ [Sources.X64]
X64/ArchInterruptDefs.h
[Sources.common]
- CpuExceptionCommon.h
- CpuExceptionCommon.c
- PeiDxeSmmCpuException.c
- SmmException.c
+ Ia32_X64/CpuExceptionCommon.h
+ Ia32_X64/CpuExceptionCommon.c
+ Ia32_X64/PeiDxeSmmCpuException.c
+ Ia32_X64/SmmException.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
index 6d2f66504a5b..7830b3e6663f 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
@@ -38,9 +38,9 @@ [Sources.X64]
X64/ArchInterruptDefs.h
[Sources.common]
- CpuExceptionCommon.h
- CpuExceptionCommon.c
- SecPeiCpuException.c
+ Ia32_X64/CpuExceptionCommon.h
+ Ia32_X64/CpuExceptionCommon.c
+ Ia32_X64/SecPeiCpuException.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/CpuExceptionCommon.h
similarity index 100%
rename from UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
rename to UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/CpuExceptionCommon.h
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/CpuExceptionCommon.c
similarity index 100%
rename from UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
rename to UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/CpuExceptionCommon.c
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/DxeException.c
similarity index 100%
rename from UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
rename to UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/DxeException.c
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/PeiCpuException.c
similarity index 100%
rename from UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c
rename to UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/PeiCpuException.c
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/PeiDxeSmmCpuException.c
similarity index 100%
rename from UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c
rename to UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/PeiDxeSmmCpuException.c
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/SecPeiCpuException.c
similarity index 100%
rename from UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
rename to UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/SecPeiCpuException.c
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/SmmException.c
similarity index 100%
rename from UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c
rename to UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32_X64/SmmException.c
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 16/29] UefiCpuPkg/CpuExceptionHandlerLib: Add support for RISC-V
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (14 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 15/29] UefiCpuPkg/CpuExceptionHandlerLib: Refactor to allow other architectures Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 17/29] UefiCpuPkg/CpuDxe: Refactor to allow other architectures Sunil V L
` (12 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar, Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
.../DxeCpuExceptionHandlerLib.inf | 7 +-
.../SecPeiCpuExceptionHandlerLib.inf | 7 +-
.../RiscV64/CpuExceptionHandlerLib.h | 116 +++++++++++++++
.../RiscV64/CpuExceptionHandlerLib.c | 133 ++++++++++++++++++
.../RiscV64/SupervisorTrapHandler.S | 105 ++++++++++++++
5 files changed, 366 insertions(+), 2 deletions(-)
create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.h
create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.c
create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/SupervisorTrapHandler.S
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
index ef07b05c080a..b689e7af56e7 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
@@ -18,7 +18,7 @@ [Defines]
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 RISCV64
#
[Sources.Ia32]
@@ -38,6 +38,11 @@ [Sources.IA32, Sources.X64]
Ia32_X64/PeiDxeSmmCpuException.c
Ia32_X64/DxeException.c
+[Sources.RISCV64]
+ RiscV64/SupervisorTrapHandler.S
+ RiscV64/CpuExceptionHandlerLib.c
+ RiscV64/CpuExceptionHandlerLib.h
+
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
index 28341abd4493..b490ef5aff8a 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
@@ -18,7 +18,7 @@ [Defines]
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 RISCV64
#
[Sources.Ia32]
@@ -37,6 +37,11 @@ [Sources.IA32, Sources.X64]
Ia32_X64/CpuExceptionCommon.c
Ia32_X64/SecPeiCpuException.c
+[Sources.RISCV64]
+ RiscV64/SupervisorTrapHandler.S
+ RiscV64/CpuExceptionHandlerLib.c
+ RiscV64/CpuExceptionHandlerLib.h
+
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.h
new file mode 100644
index 000000000000..30f47e87552b
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.h
@@ -0,0 +1,116 @@
+/** @file
+
+ RISC-V Exception Handler library definition file.
+
+ Copyright (c) 2019-2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RISCV_CPU_EXECPTION_HANDLER_LIB_H_
+#define RISCV_CPU_EXECPTION_HANDLER_LIB_H_
+
+#include <Register/RiscV64/RiscVImpl.h>
+
+/**
+ Trap Handler for S-mode
+
+**/
+VOID
+SupervisorModeTrap (
+ VOID
+ );
+
+//
+// Index of SMode trap register
+//
+#define SMODE_TRAP_REGS_zero 0
+#define SMODE_TRAP_REGS_ra 1
+#define SMODE_TRAP_REGS_sp 2
+#define SMODE_TRAP_REGS_gp 3
+#define SMODE_TRAP_REGS_tp 4
+#define SMODE_TRAP_REGS_t0 5
+#define SMODE_TRAP_REGS_t1 6
+#define SMODE_TRAP_REGS_t2 7
+#define SMODE_TRAP_REGS_s0 8
+#define SMODE_TRAP_REGS_s1 9
+#define SMODE_TRAP_REGS_a0 10
+#define SMODE_TRAP_REGS_a1 11
+#define SMODE_TRAP_REGS_a2 12
+#define SMODE_TRAP_REGS_a3 13
+#define SMODE_TRAP_REGS_a4 14
+#define SMODE_TRAP_REGS_a5 15
+#define SMODE_TRAP_REGS_a6 16
+#define SMODE_TRAP_REGS_a7 17
+#define SMODE_TRAP_REGS_s2 18
+#define SMODE_TRAP_REGS_s3 19
+#define SMODE_TRAP_REGS_s4 20
+#define SMODE_TRAP_REGS_s5 21
+#define SMODE_TRAP_REGS_s6 22
+#define SMODE_TRAP_REGS_s7 23
+#define SMODE_TRAP_REGS_s8 24
+#define SMODE_TRAP_REGS_s9 25
+#define SMODE_TRAP_REGS_s10 26
+#define SMODE_TRAP_REGS_s11 27
+#define SMODE_TRAP_REGS_t3 28
+#define SMODE_TRAP_REGS_t4 29
+#define SMODE_TRAP_REGS_t5 30
+#define SMODE_TRAP_REGS_t6 31
+#define SMODE_TRAP_REGS_sepc 32
+#define SMODE_TRAP_REGS_sstatus 33
+#define SMODE_TRAP_REGS_sie 34
+#define SMODE_TRAP_REGS_last 35
+
+#define SMODE_TRAP_REGS_OFFSET(x) ((SMODE_TRAP_REGS_##x) * __SIZEOF_POINTER__)
+#define SMODE_TRAP_REGS_SIZE SMODE_TRAP_REGS_OFFSET(last)
+
+#pragma pack(1)
+typedef struct {
+ //
+ // Below are follow the format of EFI_SYSTEM_CONTEXT
+ //
+ UINT64 zero;
+ UINT64 ra;
+ UINT64 sp;
+ UINT64 gp;
+ UINT64 tp;
+ UINT64 t0;
+ UINT64 t1;
+ UINT64 t2;
+ UINT64 s0;
+ UINT64 s1;
+ UINT64 a0;
+ UINT64 a1;
+ UINT64 a2;
+ UINT64 a3;
+ UINT64 a4;
+ UINT64 a5;
+ UINT64 a6;
+ UINT64 a7;
+ UINT64 s2;
+ UINT64 s3;
+ UINT64 s4;
+ UINT64 s5;
+ UINT64 s6;
+ UINT64 s7;
+ UINT64 s8;
+ UINT64 s9;
+ UINT64 s10;
+ UINT64 s11;
+ UINT64 t3;
+ UINT64 t4;
+ UINT64 t5;
+ UINT64 t6;
+ //
+ // Below are the additional information to
+ // EFI_SYSTEM_CONTEXT, private to supervisor mode trap
+ // and not public to EFI environment.
+ //
+ UINT64 sepc;
+ UINT64 sstatus;
+ UINT64 sie;
+} SMODE_TRAP_REGISTERS;
+#pragma pack()
+
+#endif
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.c
new file mode 100644
index 000000000000..f1ee7d236aec
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.c
@@ -0,0 +1,133 @@
+/** @file
+ RISC-V Exception Handler library implementation.
+
+ Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/CpuExceptionHandlerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Register/RiscV64/RiscVEncoding.h>
+
+#include "CpuExceptionHandlerLib.h"
+
+STATIC EFI_CPU_INTERRUPT_HANDLER mInterruptHandlers[2];
+
+/**
+ Initializes all CPU exceptions entries and provides the default exception handlers.
+
+ Caller should try to get an array of interrupt and/or exception vectors that are in use and need to
+ persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.
+ If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.
+ If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.
+
+ @param[in] VectorInfo Pointer to reserved vector list.
+
+ @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized
+ with default exception handlers.
+ @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
+ @retval EFI_UNSUPPORTED This function is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuExceptionHandlers (
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
+ )
+{
+ RiscVSetSupervisorStvec ((UINT64)SupervisorModeTrap);
+ return EFI_SUCCESS;
+}
+
+/**
+ Registers a function to be called from the processor interrupt handler.
+
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+ NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or
+ InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned.
+
+ @param[in] InterruptType Defines which interrupt or exception to hook.
+ @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported,
+ or this function is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterCpuInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ DEBUG ((DEBUG_INFO, "%a: Type:%x Handler: %x\n", __FUNCTION__, InterruptType, InterruptHandler));
+ mInterruptHandlers[InterruptType] = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
+/**
+ Setup separate stacks for certain exception handlers.
+ If the input Buffer and BufferSize are both NULL, use global variable if possible.
+
+ @param[in] Buffer Point to buffer used to separate exception stack.
+ @param[in, out] BufferSize On input, it indicates the byte size of Buffer.
+ If the size is not enough, the return status will
+ be EFI_BUFFER_TOO_SMALL, and output BufferSize
+ will be the size it needs.
+
+ @retval EFI_SUCCESS The stacks are assigned successfully.
+ @retval EFI_UNSUPPORTED This function is not supported.
+ @retval EFI_BUFFER_TOO_SMALL This BufferSize is too small.
+**/
+EFI_STATUS
+EFIAPI
+InitializeSeparateExceptionStacks (
+ IN VOID *Buffer,
+ IN OUT UINTN *BufferSize
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Supervisor mode trap handler.
+
+ @param[in] SmodeTrapReg Registers before trap occurred.
+
+**/
+VOID
+RiscVSupervisorModeTrapHandler (
+ SMODE_TRAP_REGISTERS *SmodeTrapReg
+ )
+{
+ UINTN SCause;
+ EFI_SYSTEM_CONTEXT RiscVSystemContext;
+
+ RiscVSystemContext.SystemContextRiscV64 = (EFI_SYSTEM_CONTEXT_RISCV64 *)SmodeTrapReg;
+ //
+ // Check scasue register.
+ //
+ SCause = (UINTN)RiscVGetSupervisorTrapCause ();
+ if ((SCause & (1UL << (sizeof (UINTN) * 8- 1))) != 0) {
+ //
+ // This is interrupt event.
+ //
+ SCause &= ~(1UL << (sizeof (UINTN) * 8- 1));
+ if ((SCause == IRQ_S_TIMER) && (mInterruptHandlers[EXCEPT_RISCV_TIMER_INT] != NULL)) {
+ mInterruptHandlers[EXCEPT_RISCV_TIMER_INT](EXCEPT_RISCV_TIMER_INT, RiscVSystemContext);
+ }
+ }
+}
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/SupervisorTrapHandler.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/SupervisorTrapHandler.S
new file mode 100644
index 000000000000..649c4c5becf4
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/RiscV64/SupervisorTrapHandler.S
@@ -0,0 +1,105 @@
+/** @file
+ RISC-V Processor supervisor mode trap handler
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include "CpuExceptionHandlerLib.h"
+
+ .align 3
+ .section .entry, "ax", %progbits
+ .globl SupervisorModeTrap
+SupervisorModeTrap:
+ addi sp, sp, -SMODE_TRAP_REGS_SIZE
+
+ /* Save all general regisers except SP */
+ sd t0, SMODE_TRAP_REGS_OFFSET(t0)(sp)
+
+ csrr t0, CSR_SSTATUS
+ and t0, t0, (SSTATUS_SIE | SSTATUS_SPIE)
+ sd t0, SMODE_TRAP_REGS_OFFSET(sstatus)(sp)
+ csrr t0, CSR_SEPC
+ sd t0, SMODE_TRAP_REGS_OFFSET(sepc)(sp)
+ csrr t0, CSR_SIE
+ sd t0, SMODE_TRAP_REGS_OFFSET(sie)(sp)
+ ld t0, SMODE_TRAP_REGS_OFFSET(t0)(sp)
+
+ sd ra, SMODE_TRAP_REGS_OFFSET(ra)(sp)
+ sd gp, SMODE_TRAP_REGS_OFFSET(gp)(sp)
+ sd tp, SMODE_TRAP_REGS_OFFSET(tp)(sp)
+ sd t1, SMODE_TRAP_REGS_OFFSET(t1)(sp)
+ sd t2, SMODE_TRAP_REGS_OFFSET(t2)(sp)
+ sd s0, SMODE_TRAP_REGS_OFFSET(s0)(sp)
+ sd s1, SMODE_TRAP_REGS_OFFSET(s1)(sp)
+ sd a0, SMODE_TRAP_REGS_OFFSET(a0)(sp)
+ sd a1, SMODE_TRAP_REGS_OFFSET(a1)(sp)
+ sd a2, SMODE_TRAP_REGS_OFFSET(a2)(sp)
+ sd a3, SMODE_TRAP_REGS_OFFSET(a3)(sp)
+ sd a4, SMODE_TRAP_REGS_OFFSET(a4)(sp)
+ sd a5, SMODE_TRAP_REGS_OFFSET(a5)(sp)
+ sd a6, SMODE_TRAP_REGS_OFFSET(a6)(sp)
+ sd a7, SMODE_TRAP_REGS_OFFSET(a7)(sp)
+ sd s2, SMODE_TRAP_REGS_OFFSET(s2)(sp)
+ sd s3, SMODE_TRAP_REGS_OFFSET(s3)(sp)
+ sd s4, SMODE_TRAP_REGS_OFFSET(s4)(sp)
+ sd s5, SMODE_TRAP_REGS_OFFSET(s5)(sp)
+ sd s6, SMODE_TRAP_REGS_OFFSET(s6)(sp)
+ sd s7, SMODE_TRAP_REGS_OFFSET(s7)(sp)
+ sd s8, SMODE_TRAP_REGS_OFFSET(s8)(sp)
+ sd s9, SMODE_TRAP_REGS_OFFSET(s9)(sp)
+ sd s10, SMODE_TRAP_REGS_OFFSET(s10)(sp)
+ sd s11, SMODE_TRAP_REGS_OFFSET(s11)(sp)
+ sd t3, SMODE_TRAP_REGS_OFFSET(t3)(sp)
+ sd t4, SMODE_TRAP_REGS_OFFSET(t4)(sp)
+ sd t5, SMODE_TRAP_REGS_OFFSET(t5)(sp)
+ sd t6, SMODE_TRAP_REGS_OFFSET(t6)(sp)
+
+ /* Call to Supervisor mode trap handler in CpuExceptionHandlerLib.c */
+ call RiscVSupervisorModeTrapHandler
+
+ /* Restore all general regisers except SP */
+ ld ra, SMODE_TRAP_REGS_OFFSET(ra)(sp)
+ ld gp, SMODE_TRAP_REGS_OFFSET(gp)(sp)
+ ld tp, SMODE_TRAP_REGS_OFFSET(tp)(sp)
+ ld t2, SMODE_TRAP_REGS_OFFSET(t2)(sp)
+ ld s0, SMODE_TRAP_REGS_OFFSET(s0)(sp)
+ ld s1, SMODE_TRAP_REGS_OFFSET(s1)(sp)
+ ld a0, SMODE_TRAP_REGS_OFFSET(a0)(sp)
+ ld a1, SMODE_TRAP_REGS_OFFSET(a1)(sp)
+ ld a2, SMODE_TRAP_REGS_OFFSET(a2)(sp)
+ ld a3, SMODE_TRAP_REGS_OFFSET(a3)(sp)
+ ld a4, SMODE_TRAP_REGS_OFFSET(a4)(sp)
+ ld a5, SMODE_TRAP_REGS_OFFSET(a5)(sp)
+ ld a6, SMODE_TRAP_REGS_OFFSET(a6)(sp)
+ ld a7, SMODE_TRAP_REGS_OFFSET(a7)(sp)
+ ld s2, SMODE_TRAP_REGS_OFFSET(s2)(sp)
+ ld s3, SMODE_TRAP_REGS_OFFSET(s3)(sp)
+ ld s4, SMODE_TRAP_REGS_OFFSET(s4)(sp)
+ ld s5, SMODE_TRAP_REGS_OFFSET(s5)(sp)
+ ld s6, SMODE_TRAP_REGS_OFFSET(s6)(sp)
+ ld s7, SMODE_TRAP_REGS_OFFSET(s7)(sp)
+ ld s8, SMODE_TRAP_REGS_OFFSET(s8)(sp)
+ ld s9, SMODE_TRAP_REGS_OFFSET(s9)(sp)
+ ld s10, SMODE_TRAP_REGS_OFFSET(s10)(sp)
+ ld s11, SMODE_TRAP_REGS_OFFSET(s11)(sp)
+ ld t3, SMODE_TRAP_REGS_OFFSET(t3)(sp)
+ ld t4, SMODE_TRAP_REGS_OFFSET(t4)(sp)
+ ld t5, SMODE_TRAP_REGS_OFFSET(t5)(sp)
+ ld t6, SMODE_TRAP_REGS_OFFSET(t6)(sp)
+
+ ld t0, SMODE_TRAP_REGS_OFFSET(sepc)(sp)
+ csrw CSR_SEPC, t0
+ ld t0, SMODE_TRAP_REGS_OFFSET(sie)(sp)
+ csrw CSR_SIE, t0
+ csrr t0, CSR_SSTATUS
+ ld t1, SMODE_TRAP_REGS_OFFSET(sstatus)(sp)
+ or t0, t0, t1
+ csrw CSR_SSTATUS, t0
+ ld t1, SMODE_TRAP_REGS_OFFSET(t1)(sp)
+ ld t0, SMODE_TRAP_REGS_OFFSET(t0)(sp)
+ addi sp, sp, SMODE_TRAP_REGS_SIZE
+ sret
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 17/29] UefiCpuPkg/CpuDxe: Refactor to allow other architectures
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (15 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 16/29] UefiCpuPkg/CpuExceptionHandlerLib: Add support for RISC-V Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 18/29] UefiCpuPkg/CpuDxe: Add support for RISC-V Sunil V L
` (11 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Currently, CpuDxe supports only X86 architecture. To add
support for other architectures like RISC-V, this need to
be refactored.
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
UefiCpuPkg/CpuDxe/CpuDxe.inf | 28 ++++++++++---------
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuDxe.h | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuGdt.h | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuMp.h | 0
.../CpuDxe/{ => Ia32_X64}/CpuPageTable.h | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuDxe.c | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuGdt.c | 0
UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuMp.c | 0
.../CpuDxe/{ => Ia32_X64}/CpuPageTable.c | 0
9 files changed, 15 insertions(+), 13 deletions(-)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuDxe.h (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuGdt.h (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuMp.h (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuPageTable.h (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuDxe.c (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuGdt.c (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuMp.c (100%)
rename UefiCpuPkg/CpuDxe/{ => Ia32_X64}/CpuPageTable.c (100%)
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf
index 235241899222..069a7f2933bd 100644
--- a/UefiCpuPkg/CpuDxe/CpuDxe.inf
+++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf
@@ -29,28 +29,30 @@ [LibraryClasses]
DebugLib
DxeServicesTableLib
MemoryAllocationLib
- MtrrLib
UefiBootServicesTableLib
UefiDriverEntryPoint
- LocalApicLib
- UefiCpuLib
UefiLib
CpuExceptionHandlerLib
HobLib
ReportStatusCodeLib
- MpInitLib
TimerLib
PeCoffGetEntryPointLib
-[Sources]
- CpuDxe.c
- CpuDxe.h
- CpuGdt.c
- CpuGdt.h
- CpuMp.c
- CpuMp.h
- CpuPageTable.h
- CpuPageTable.c
+[LibraryClasses.IA32, LibraryClasses.X64]
+ LocalApicLib
+ MpInitLib
+ MtrrLib
+ UefiCpuLib
+
+[Sources.IA32, Sources.X64]
+ Ia32_X64/CpuDxe.c
+ Ia32_X64/CpuDxe.h
+ Ia32_X64/CpuGdt.c
+ Ia32_X64/CpuGdt.h
+ Ia32_X64/CpuMp.c
+ Ia32_X64/CpuMp.h
+ Ia32_X64/CpuPageTable.h
+ Ia32_X64/CpuPageTable.c
[Sources.IA32]
Ia32/CpuAsm.nasm
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.h b/UefiCpuPkg/CpuDxe/Ia32_X64/CpuDxe.h
similarity index 100%
rename from UefiCpuPkg/CpuDxe/CpuDxe.h
rename to UefiCpuPkg/CpuDxe/Ia32_X64/CpuDxe.h
diff --git a/UefiCpuPkg/CpuDxe/CpuGdt.h b/UefiCpuPkg/CpuDxe/Ia32_X64/CpuGdt.h
similarity index 100%
rename from UefiCpuPkg/CpuDxe/CpuGdt.h
rename to UefiCpuPkg/CpuDxe/Ia32_X64/CpuGdt.h
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.h b/UefiCpuPkg/CpuDxe/Ia32_X64/CpuMp.h
similarity index 100%
rename from UefiCpuPkg/CpuDxe/CpuMp.h
rename to UefiCpuPkg/CpuDxe/Ia32_X64/CpuMp.h
diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.h b/UefiCpuPkg/CpuDxe/Ia32_X64/CpuPageTable.h
similarity index 100%
rename from UefiCpuPkg/CpuDxe/CpuPageTable.h
rename to UefiCpuPkg/CpuDxe/Ia32_X64/CpuPageTable.h
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.c b/UefiCpuPkg/CpuDxe/Ia32_X64/CpuDxe.c
similarity index 100%
rename from UefiCpuPkg/CpuDxe/CpuDxe.c
rename to UefiCpuPkg/CpuDxe/Ia32_X64/CpuDxe.c
diff --git a/UefiCpuPkg/CpuDxe/CpuGdt.c b/UefiCpuPkg/CpuDxe/Ia32_X64/CpuGdt.c
similarity index 100%
rename from UefiCpuPkg/CpuDxe/CpuGdt.c
rename to UefiCpuPkg/CpuDxe/Ia32_X64/CpuGdt.c
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/Ia32_X64/CpuMp.c
similarity index 100%
rename from UefiCpuPkg/CpuDxe/CpuMp.c
rename to UefiCpuPkg/CpuDxe/Ia32_X64/CpuMp.c
diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c b/UefiCpuPkg/CpuDxe/Ia32_X64/CpuPageTable.c
similarity index 100%
rename from UefiCpuPkg/CpuDxe/CpuPageTable.c
rename to UefiCpuPkg/CpuDxe/Ia32_X64/CpuPageTable.c
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 18/29] UefiCpuPkg/CpuDxe: Add support for RISC-V
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (16 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 17/29] UefiCpuPkg/CpuDxe: Refactor to allow other architectures Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 19/29] UefiCpuPkg/CpuDxe: Add RISC-V Boot protocol support Sunil V L
` (10 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar, Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This is migrated from
edk2-platforms/Silicon/RISC-V/ProcessorPkg/Universal/CpuDxe
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
UefiCpuPkg/CpuDxe/CpuDxe.inf | 11 ++
UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h | 199 +++++++++++++++++++
UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c | 307 +++++++++++++++++++++++++++++
3 files changed, 517 insertions(+)
create mode 100644 UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h
create mode 100644 UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf
index 069a7f2933bd..5a6ead3bfbb6 100644
--- a/UefiCpuPkg/CpuDxe/CpuDxe.inf
+++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf
@@ -44,6 +44,9 @@ [LibraryClasses.IA32, LibraryClasses.X64]
MtrrLib
UefiCpuLib
+[LibraryClasses.RISCV64]
+ RiscVSbiLib
+
[Sources.IA32, Sources.X64]
Ia32_X64/CpuDxe.c
Ia32_X64/CpuDxe.h
@@ -62,11 +65,18 @@ [Sources.X64]
X64/CpuAsm.nasm
X64/PagingAttribute.c
+[Sources.RISCV64]
+ RiscV64/CpuDxe.c
+ RiscV64/CpuDxe.h
+
[Protocols]
gEfiCpuArchProtocolGuid ## PRODUCES
gEfiMpServiceProtocolGuid ## PRODUCES
gEfiSmmBase2ProtocolGuid ## SOMETIMES_CONSUMES
+[Protocols.RISCV64]
+ gRiscVEfiBootProtocolGuid ## PRODUCES
+
[Guids]
gIdleLoopEventGuid ## CONSUMES ## Event
gEfiVectorHandoffTableGuid ## SOMETIMES_CONSUMES ## SystemTable
@@ -83,6 +93,7 @@ [Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdTdxSharedBitMask ## CONSUMES
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES
[Depex]
TRUE
diff --git a/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h
new file mode 100644
index 000000000000..49f4e119665a
--- /dev/null
+++ b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h
@@ -0,0 +1,199 @@
+/** @file
+ RISC-V CPU DXE module header file.
+
+ Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CPU_DXE_H_
+#define CPU_DXE_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/RiscVBootProtocol.h>
+#include <Library/BaseRiscVSbiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/CpuExceptionHandlerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param This Protocol instance structure
+ @param Start Physical address to start flushing from.
+ @param Length Number of bytes to flush. Round up to chipset
+ granularity.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS If cache was flushed
+ @retval EFI_UNSUPPORTED If flush type is not supported.
+ @retval EFI_DEVICE_ERROR If requested range could not be flushed.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+/**
+ Enables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ Disables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ Return the state of interrupts.
+
+ @param This Protocol instance structure
+ @param State Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+/**
+ Generates an INIT to the CPU.
+
+ @param This Protocol instance structure
+ @param InitType Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
+ seen.
+ @retval EFI_DEVICE_ERROR If CPU INIT failed.
+ @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param This Protocol instance structure
+ @param InterruptType Defines which interrupt to hook. IA-32
+ valid range is 0x00 through 0xFF
+ @param InterruptHandler A pointer to a function of type
+ EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. A null
+ pointer is an error condition.
+
+ @retval EFI_SUCCESS If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
+ for InterruptType was previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
+ is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param This - Protocol instance structure.
+ @param TimerIndex - Specifies which CPU timer is requested.
+ @param TimerValue - Pointer to the returned timer value.
+ @param TimerPeriod - A pointer to the amount of time that passes
+ in femtoseconds (10-15) for each increment
+ of TimerValue. If TimerValue does not
+ increment at a predictable rate, then 0 is
+ returned. The amount of time that has
+ passed between two calls to GetTimerValue()
+ can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod.
+ This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+/**
+ Set memory cacheability attributes for given range of memeory.
+
+ @param This Protocol instance structure
+ @param BaseAddress Specifies the start address of the
+ memory range
+ @param Length Specifies the length of the memory range
+ @param Attributes The memory cacheability for the memory range
+
+ @retval EFI_SUCCESS If the cacheability of that memory range is
+ set successfully
+ @retval EFI_UNSUPPORTED If the desired operation cannot be done
+ @retval EFI_INVALID_PARAMETER The input parameter is not correct,
+ such as Length = 0
+
+**/
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+#endif
diff --git a/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c
new file mode 100644
index 000000000000..9f557b776a09
--- /dev/null
+++ b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c
@@ -0,0 +1,307 @@
+/** @file
+ RISC-V CPU DXE driver.
+
+ Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CpuDxe.h"
+
+//
+// Global Variables
+//
+STATIC BOOLEAN mInterruptState = FALSE;
+STATIC EFI_HANDLE mCpuHandle = NULL;
+
+EFI_CPU_ARCH_PROTOCOL gCpu = {
+ CpuFlushCpuDataCache,
+ CpuEnableInterrupt,
+ CpuDisableInterrupt,
+ CpuGetInterruptState,
+ CpuInit,
+ CpuRegisterInterruptHandler,
+ CpuGetTimerValue,
+ CpuSetMemoryAttributes,
+ 1, // NumberOfTimers
+ 4 // DmaBufferAlignment
+};
+
+//
+// CPU Arch Protocol Functions
+//
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param This Protocol instance structure
+ @param Start Physical address to start flushing from.
+ @param Length Number of bytes to flush. Round up to chipset
+ granularity.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS If cache was flushed
+ @retval EFI_UNSUPPORTED If flush type is not supported.
+ @retval EFI_DEVICE_ERROR If requested range could not be flushed.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ EnableInterrupts ();
+ mInterruptState = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Disables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ DisableInterrupts ();
+ mInterruptState = FALSE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the state of interrupts.
+
+ @param This Protocol instance structure
+ @param State Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = mInterruptState;
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates an INIT to the CPU.
+
+ @param This Protocol instance structure
+ @param InitType Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
+ seen.
+ @retval EFI_DEVICE_ERROR If CPU INIT failed.
+ @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param This Protocol instance structure
+ @param InterruptType Defines which interrupt to hook. IA-32
+ valid range is 0x00 through 0xFF
+ @param InterruptHandler A pointer to a function of type
+ EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. A null
+ pointer is an error condition.
+
+ @retval EFI_SUCCESS If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
+ for InterruptType was previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
+ is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);
+}
+
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param This - Protocol instance structure.
+ @param TimerIndex - Specifies which CPU timer is requested.
+ @param TimerValue - Pointer to the returned timer value.
+ @param TimerPeriod - A pointer to the amount of time that passes
+ in femtoseconds (10-15) for each increment
+ of TimerValue. If TimerValue does not
+ increment at a predictable rate, then 0 is
+ returned. The amount of time that has
+ passed between two calls to GetTimerValue()
+ can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod.
+ This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerValue = (UINT64)RiscVReadTimer ();
+ if (TimerPeriod != NULL) {
+ *TimerPeriod = DivU64x32 (
+ 1000000000000000u,
+ PcdGet64 (PcdCpuCoreCrystalClockFrequency)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
+
+ This function modifies the attributes for the memory region specified by BaseAddress and
+ Length from their current attributes to the attributes specified by Attributes.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval EFI_SUCCESS The attributes were set for the memory region.
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ Attributes specified an illegal combination of attributes that
+ cannot be set together.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ DEBUG ((DEBUG_INFO, "%a: Set memory attributes not supported yet\n", __FUNCTION__));
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the state information for the CPU Architectural Protocol.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS Thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Cannot create the thread
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ InitializeCpuExceptionHandlers(NULL);
+
+ //
+ // Make sure interrupts are disabled
+ //
+ DisableInterrupts ();
+
+ //
+ // Install CPU Architectural Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mCpuHandle,
+ &gEfiCpuArchProtocolGuid,
+ &gCpu,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 19/29] UefiCpuPkg/CpuDxe: Add RISC-V Boot protocol support
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (17 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 18/29] UefiCpuPkg/CpuDxe: Add support for RISC-V Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 20/29] UefiCpuPkg: Add CpuTimerDxe module Sunil V L
` (9 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar, Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
RISC-V UEFI platforms need to support RISCV_EFI_BOOT_PROTOCOL.
Add the support for this protocol which is defined in the spec:
https://github.com/riscv-non-isa/riscv-uefi/releases/download/1.0.0/RISCV_UEFI_PROTOCOL-spec.pdf
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
UefiCpuPkg/UefiCpuPkg.dsc | 12 +++---
UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c | 66 ++++++++++++++++++++++++++++--
2 files changed, 68 insertions(+), 10 deletions(-)
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index f694b3a77c2e..6ea90507e36f 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -122,9 +122,13 @@ [Components]
UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf
-
-[Components.IA32, Components.X64]
UefiCpuPkg/CpuDxe/CpuDxe.inf
+ UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+!if $(TOOL_CHAIN_TAG) != "XCODE5"
+ UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+!endif
+
+[Components.IA32, Components.X64]
UefiCpuPkg/CpuFeatures/CpuFeaturesPei.inf {
<LibraryClasses>
NULL|UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeaturesLib.inf
@@ -141,10 +145,6 @@ [Components.IA32, Components.X64]
UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeaturesLib.inf
- UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
-!if $(TOOL_CHAIN_TAG) != "XCODE5"
- UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
-!endif
UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
diff --git a/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c
index 9f557b776a09..7551e0653603 100644
--- a/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c
+++ b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c
@@ -2,6 +2,7 @@
RISC-V CPU DXE driver.
Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+ Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -12,8 +13,41 @@
//
// Global Variables
//
-STATIC BOOLEAN mInterruptState = FALSE;
-STATIC EFI_HANDLE mCpuHandle = NULL;
+STATIC BOOLEAN mInterruptState = FALSE;
+STATIC EFI_HANDLE mCpuHandle = NULL;
+STATIC UINTN mBootHartId;
+RISCV_EFI_BOOT_PROTOCOL gRiscvBootProtocol;
+
+/**
+ Get the boot hartid
+
+ @param This Protocol instance structure
+ @param BootHartId Pointer to the Boot Hart ID variable
+
+ @retval EFI_SUCCESS If BootHartId is returned
+ @retval EFI_INVALID_PARAMETER Either "BootHartId" is NULL or "This" is not
+ a valid RISCV_EFI_BOOT_PROTOCOL instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RiscvGetBootHartId (
+ IN RISCV_EFI_BOOT_PROTOCOL *This,
+ OUT UINTN *BootHartId
+ )
+{
+ if ((This != &gRiscvBootProtocol) || (BootHartId == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *BootHartId = mBootHartId;
+ return EFI_SUCCESS;
+}
+
+RISCV_EFI_BOOT_PROTOCOL gRiscvBootProtocol = {
+ RISCV_EFI_BOOT_PROTOCOL_LATEST_VERSION,
+ RiscvGetBootHartId
+};
EFI_CPU_ARCH_PROTOCOL gCpu = {
CpuFlushCpuDataCache,
@@ -284,15 +318,39 @@ InitializeCpu (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
- InitializeCpuExceptionHandlers(NULL);
+ GetFirmwareContextPointer (&FirmwareContext);
+ ASSERT (FirmwareContext != NULL);
+ if (FirmwareContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "Failed to get the pointer of EFI_RISCV_FIRMWARE_CONTEXT\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ DEBUG ((DEBUG_INFO, " %a: Firmware Context is at 0x%x.\n", __FUNCTION__, FirmwareContext));
+
+ mBootHartId = FirmwareContext->BootHartId;
+ DEBUG ((DEBUG_INFO, " %a: mBootHartId = 0x%x.\n", __FUNCTION__, mBootHartId));
+
+ InitializeCpuExceptionHandlers (NULL);
//
// Make sure interrupts are disabled
//
DisableInterrupts ();
+ //
+ // Install Boot protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gRiscVEfiBootProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gRiscvBootProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
//
// Install CPU Architectural Protocol
//
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 20/29] UefiCpuPkg: Add CpuTimerDxe module
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (18 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 19/29] UefiCpuPkg/CpuDxe: Add RISC-V Boot protocol support Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 21/29] ArmVirtPkg/PlatformHasAcpiDtDxe: Move to OvmfPkg Sunil V L
` (8 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar, Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This DXE module initializes the timer interrupt handler
and installs the Arch Timer protocol.
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
UefiCpuPkg/UefiCpuPkg.dsc | 3 +
UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf | 51 ++++
UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.h | 177 ++++++++++++++
UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.c | 294 +++++++++++++++++++++++
UefiCpuPkg/CpuTimerDxe/CpuTimer.uni | 15 ++
| 13 +
6 files changed, 553 insertions(+)
create mode 100644 UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf
create mode 100644 UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.h
create mode 100644 UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.c
create mode 100644 UefiCpuPkg/CpuTimerDxe/CpuTimer.uni
create mode 100644 UefiCpuPkg/CpuTimerDxe/CpuTimerExtra.uni
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 6ea90507e36f..54ef5edd6eae 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -178,5 +178,8 @@ [Components.IA32, Components.X64]
UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
+[Components.RISCV64]
+ UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf
+
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf b/UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf
new file mode 100644
index 000000000000..d7706328b591
--- /dev/null
+++ b/UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf
@@ -0,0 +1,51 @@
+## @file
+# Timer Arch protocol module
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = CpuTimerDxe
+ MODULE_UNI_FILE = CpuTimer.uni
+ FILE_GUID = 055DDAC6-9142-4013-BF20-FC2E5BC325C9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = TimerDriverInitialize
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ IoLib
+ CpuLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[LibraryClasses.RISCV64]
+ RiscVSbiLib
+
+[Sources.RISCV64]
+ RiscV64/Timer.h
+ RiscV64/Timer.c
+
+[Protocols]
+ gEfiCpuArchProtocolGuid ## CONSUMES
+ gEfiTimerArchProtocolGuid ## PRODUCES
+
+[Depex]
+ gEfiCpuArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ CpuTimerExtra.uni
diff --git a/UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.h b/UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.h
new file mode 100644
index 000000000000..586eb0cfadb4
--- /dev/null
+++ b/UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.h
@@ -0,0 +1,177 @@
+/** @file
+ RISC-V Timer Architectural Protocol definitions
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef TIMER_H_
+#define TIMER_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/Timer.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+
+//
+// RISC-V use 100us timer.
+// The default timer tick duration is set to 10 ms = 10 * 1000 * 10 100 ns units
+//
+#define DEFAULT_TIMER_TICK_DURATION 100000
+
+extern VOID
+RiscvSetTimerPeriod (
+ UINT32 TimerPeriod
+ );
+
+//
+// Function Prototypes
+//
+
+/**
+ Initialize the Timer Architectural Protocol driver
+
+ @param ImageHandle ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Timer Architectural Protocol created
+ @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
+ @retval EFI_DEVICE_ERROR A device error occured attempting to initialize the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+;
+
+/**
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param NotifyFunction The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+ @retval EFI_SUCCESS The timer period was changed.
+ @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+ )
+;
+
+/**
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+ @retval EFI_SUCCESS The timer period was changed.
+ @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ )
+;
+
+/**
+
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+ @retval EFI_SUCCESS The timer period was returned in TimerPeriod.
+ @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ )
+;
+
+/**
+
+ This function generates a soft timer interrupt. If the platform does not support soft
+ timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
+ If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
+ service, then a soft timer interrupt will be generated. If the timer interrupt is
+ enabled when this service is called, then the registered handler will be invoked. The
+ registered handler should not be able to distinguish a hardware-generated timer
+ interrupt from a software-generated timer interrupt.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The soft timer interrupt was generated.
+ @retval EFI_UNSUPPORTEDT The platform does not support the generation of soft timer interrupts.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ )
+;
+
+#endif
diff --git a/UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.c b/UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.c
new file mode 100644
index 000000000000..db153f715e60
--- /dev/null
+++ b/UefiCpuPkg/CpuTimerDxe/RiscV64/Timer.c
@@ -0,0 +1,294 @@
+/** @file
+ RISC-V Timer Architectural Protocol
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+#include "Timer.h"
+
+//
+// The handle onto which the Timer Architectural Protocol will be installed
+//
+STATIC EFI_HANDLE mTimerHandle = NULL;
+
+//
+// The Timer Architectural Protocol that this driver produces
+//
+EFI_TIMER_ARCH_PROTOCOL mTimer = {
+ TimerDriverRegisterHandler,
+ TimerDriverSetTimerPeriod,
+ TimerDriverGetTimerPeriod,
+ TimerDriverGenerateSoftInterrupt
+};
+
+//
+// Pointer to the CPU Architectural Protocol instance
+//
+EFI_CPU_ARCH_PROTOCOL *mCpu;
+
+//
+// The notification function to call on every timer interrupt.
+// A bug in the compiler prevents us from initializing this here.
+//
+STATIC EFI_TIMER_NOTIFY mTimerNotifyFunction;
+
+//
+// The current period of the timer interrupt
+//
+STATIC UINT64 mTimerPeriod = 0;
+
+/**
+ Timer Interrupt Handler.
+
+ @param InterruptType The type of interrupt that occured
+ @param SystemContext A pointer to the system context when the interrupt occured
+**/
+VOID
+EFIAPI
+TimerInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ EFI_TPL OriginalTPL;
+ UINT64 RiscvTimer;
+
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ if (mTimerNotifyFunction != NULL) {
+ mTimerNotifyFunction (mTimerPeriod);
+ }
+
+ RiscVDisableTimerInterrupt (); // Disable SMode timer int
+ RiscVClearPendingTimerInterrupt ();
+ if (mTimerPeriod == 0) {
+ gBS->RestoreTPL (OriginalTPL);
+ RiscVDisableTimerInterrupt (); // Disable SMode timer int
+ return;
+ }
+
+ RiscvTimer = RiscVReadTimer ();
+ SbiSetTimer (RiscvTimer += mTimerPeriod);
+ gBS->RestoreTPL (OriginalTPL);
+ RiscVEnableTimerInterrupt (); // enable SMode timer int
+}
+
+/**
+
+ This function registers the handler NotifyFunction so it is called every time
+ the timer interrupt fires. It also passes the amount of time since the last
+ handler call to the NotifyFunction. If NotifyFunction is NULL, then the
+ handler is unregistered. If the handler is registered, then EFI_SUCCESS is
+ returned. If the CPU does not support registering a timer interrupt handler,
+ then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
+ when a handler is already registered, then EFI_ALREADY_STARTED is returned.
+ If an attempt is made to unregister a handler when a handler is not registered,
+ then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
+ register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
+ is returned.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param NotifyFunction The function to call when a timer interrupt fires. This
+ function executes at TPL_HIGH_LEVEL. The DXE Core will
+ register a handler for the timer interrupt, so it can know
+ how much time has passed. This information is used to
+ signal timer based events. NULL will unregister the handler.
+
+ @retval EFI_SUCCESS The timer handler was registered.
+ @retval EFI_UNSUPPORTED The platform does not support timer interrupts.
+ @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
+ registered.
+ @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
+ previously registered.
+ @retval EFI_DEVICE_ERROR The timer handler could not be registered.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+ )
+{
+ DEBUG ((DEBUG_INFO, "TimerDriverRegisterHandler(0x%lx) called\n", NotifyFunction));
+ mTimerNotifyFunction = NotifyFunction;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+ @retval EFI_SUCCESS The timer period was changed.
+ @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ )
+{
+ UINT64 RiscvTimer;
+
+ DEBUG ((DEBUG_INFO, "TimerDriverSetTimerPeriod(0x%lx)\n", TimerPeriod));
+
+ if (TimerPeriod == 0) {
+ mTimerPeriod = 0;
+ RiscVDisableTimerInterrupt (); // Disable SMode timer int
+ return EFI_SUCCESS;
+ }
+
+ mTimerPeriod = TimerPeriod / 10; // convert unit from 100ns to 1us
+ RiscvTimer = RiscVReadTimer ();
+ SbiSetTimer (RiscvTimer + mTimerPeriod);
+
+ mCpu->EnableInterrupt (mCpu);
+ RiscVEnableTimerInterrupt (); // enable SMode timer int
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+ @retval EFI_SUCCESS The timer period was returned in TimerPeriod.
+ @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ )
+{
+ *TimerPeriod = mTimerPeriod;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function generates a soft timer interrupt. If the platform does not support soft
+ timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
+ If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
+ service, then a soft timer interrupt will be generated. If the timer interrupt is
+ enabled when this service is called, then the registered handler will be invoked. The
+ registered handler should not be able to distinguish a hardware-generated timer
+ interrupt from a software-generated timer interrupt.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The soft timer interrupt was generated.
+ @retval EFI_UNSUPPORTEDT The platform does not support the generation of soft timer interrupts.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the Timer Architectural Protocol driver
+
+ @param ImageHandle ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Timer Architectural Protocol created
+ @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
+ @retval EFI_DEVICE_ERROR A device error occured attempting to initialize the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Initialize the pointer to our notify function.
+ //
+ mTimerNotifyFunction = NULL;
+
+ //
+ // Make sure the Timer Architectural Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid);
+
+ //
+ // Find the CPU architectural protocol.
+ //
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Force the timer to be disabled
+ //
+ Status = TimerDriverSetTimerPeriod (&mTimer, 0);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install interrupt handler for RISC-V Timer.
+ //
+ Status = mCpu->RegisterInterruptHandler (mCpu, EXCEPT_RISCV_TIMER_INT, TimerInterruptHandler);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Force the timer to be enabled at its default period
+ //
+ Status = TimerDriverSetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATION);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the Timer Architectural Protocol onto a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mTimerHandle,
+ &gEfiTimerArchProtocolGuid,
+ &mTimer,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/UefiCpuPkg/CpuTimerDxe/CpuTimer.uni b/UefiCpuPkg/CpuTimerDxe/CpuTimer.uni
new file mode 100644
index 000000000000..07272a8a787b
--- /dev/null
+++ b/UefiCpuPkg/CpuTimerDxe/CpuTimer.uni
@@ -0,0 +1,15 @@
+// /** @file
+//
+// Timer Arch protocol strings.
+//
+// Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+// Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Timer driver that provides Timer Arch protocol"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Timer driver that provides Timer Arch protocol."
--git a/UefiCpuPkg/CpuTimerDxe/CpuTimerExtra.uni b/UefiCpuPkg/CpuTimerDxe/CpuTimerExtra.uni
new file mode 100644
index 000000000000..ad80afe2674c
--- /dev/null
+++ b/UefiCpuPkg/CpuTimerDxe/CpuTimerExtra.uni
@@ -0,0 +1,13 @@
+// /** @file
+// Timer Localized Strings and Content
+//
+// Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+// Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Timer DXE Driver"
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 21/29] ArmVirtPkg/PlatformHasAcpiDtDxe: Move to OvmfPkg
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (19 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 20/29] UefiCpuPkg: Add CpuTimerDxe module Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 22/29] ArmVirtPkg: Fix up the location of PlatformHasAcpiDtDxe Sunil V L
` (7 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This module is required by other architectures like RISC-V.
Hence, move this to OvmfPkg.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
ArmVirtPkg/ArmVirtPkg.dec | 9 ---------
OvmfPkg/OvmfPkg.dec | 7 +++++++
.../PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf | 3 +--
.../PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.c | 0
4 files changed, 8 insertions(+), 11 deletions(-)
rename {ArmVirtPkg => OvmfPkg}/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf (89%)
rename {ArmVirtPkg => OvmfPkg}/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.c (100%)
diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec
index 4e165f6cd845..d2d325d71ea7 100644
--- a/ArmVirtPkg/ArmVirtPkg.dec
+++ b/ArmVirtPkg/ArmVirtPkg.dec
@@ -33,8 +33,6 @@ [Guids.common]
gEarlyPL011BaseAddressGuid = { 0xB199DEA9, 0xFD5C, 0x4A84, { 0x80, 0x82, 0x2F, 0x41, 0x70, 0x78, 0x03, 0x05 } }
gEarly16550UartBaseAddressGuid = { 0xea67ca3e, 0x1f54, 0x436b, { 0x97, 0x88, 0xd4, 0xeb, 0x29, 0xc3, 0x42, 0x67 } }
- gArmVirtVariableGuid = { 0x50bea1e5, 0xa2c5, 0x46e9, { 0x9b, 0x3a, 0x59, 0x59, 0x65, 0x16, 0xb0, 0x0a } }
-
[PcdsFeatureFlag]
#
# Feature Flag PCD that defines whether TPM2 support is enabled
@@ -68,10 +66,3 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
# Cloud Hypervisor has no other way to pass Rsdp address to the guest except use a PCD.
#
gArmVirtTokenSpaceGuid.PcdCloudHvAcpiRsdpBaseAddress|0x0|UINT64|0x00000005
-
-[PcdsDynamic]
- #
- # Whether to force disable ACPI, regardless of the fw_cfg settings
- # exposed by QEMU
- #
- gArmVirtTokenSpaceGuid.PcdForceNoAcpi|0x0|BOOLEAN|0x00000003
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index f13dd4a61f01..716c98e084fd 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -147,6 +147,7 @@ [Guids]
gConfidentialComputingSevSnpBlobGuid = {0x067b1f5f, 0xcf26, 0x44c5, {0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42}}
gUefiOvmfPkgPlatformInfoGuid = {0xdec9b486, 0x1f16, 0x47c7, {0x8f, 0x68, 0xdf, 0x1a, 0x41, 0x88, 0x8b, 0xa5}}
gVMMBootOrderGuid = {0x668f4529, 0x63d0, 0x4bb5, {0xb6, 0x5d, 0x6f, 0xbb, 0x9d, 0x36, 0xa4, 0x4a}}
+ gOvmfVariableGuid = {0x50bea1e5, 0xa2c5, 0x46e9, {0x9b, 0x3a, 0x59, 0x59, 0x65, 0x16, 0xb0, 0x0a}}
[Ppis]
# PPI whose presence in the PPI database signals that the TPM base address
@@ -456,6 +457,12 @@ [PcdsDynamic, PcdsDynamicEx]
## This PCD records LASA field in CC EVENTLOG ACPI table.
gUefiOvmfPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLasa|0|UINT64|0x67
+ #
+ # Whether to force disable ACPI, regardless of the fw_cfg settings
+ # exposed by QEMU
+ #
+ gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi|0x0|BOOLEAN|0x69
+
[PcdsFeatureFlag]
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d
diff --git a/ArmVirtPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf b/OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
similarity index 89%
rename from ArmVirtPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
rename to OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
index e900aa992661..85873f73b2eb 100644
--- a/ArmVirtPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
+++ b/OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
@@ -19,7 +19,6 @@ [Sources]
PlatformHasAcpiDtDxe.c
[Packages]
- ArmVirtPkg/ArmVirtPkg.dec
EmbeddedPkg/EmbeddedPkg.dec
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
@@ -38,7 +37,7 @@ [Guids]
gEdkiiPlatformHasDeviceTreeGuid ## SOMETIMES_PRODUCES ## PROTOCOL
[Pcd]
- gArmVirtTokenSpaceGuid.PcdForceNoAcpi
+ gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi
[Depex]
gEfiVariableArchProtocolGuid
diff --git a/ArmVirtPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.c b/OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.c
similarity index 100%
rename from ArmVirtPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.c
rename to OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.c
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 22/29] ArmVirtPkg: Fix up the location of PlatformHasAcpiDtDxe
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (20 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 21/29] ArmVirtPkg/PlatformHasAcpiDtDxe: Move to OvmfPkg Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 23/29] ArmVirtPkg/PlatformBootManagerLib: Move to OvmfPkg Sunil V L
` (6 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Gerd Hoffmann
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
PlatformHasAcpiDtDxe is required by other architectures also.
Hence, it is moved to OvmfPkg. So, update the consumers of this
module with the new location.
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>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
ArmVirtPkg/ArmVirtCloudHv.dsc | 2 +-
ArmVirtPkg/ArmVirtQemu.dsc | 4 ++--
ArmVirtPkg/ArmVirtQemuKernel.dsc | 2 +-
.../CloudHvPlatformHasAcpiDtDxe/CloudHvHasAcpiDtDxe.inf | 2 +-
ArmVirtPkg/KvmtoolPlatformDxe/KvmtoolPlatformDxe.inf | 2 +-
ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc | 2 +-
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/ArmVirtPkg/ArmVirtCloudHv.dsc b/ArmVirtPkg/ArmVirtCloudHv.dsc
index 7ca7a391d9cf..c975e139a216 100644
--- a/ArmVirtPkg/ArmVirtCloudHv.dsc
+++ b/ArmVirtPkg/ArmVirtCloudHv.dsc
@@ -198,7 +198,7 @@ [PcdsDynamicDefault.common]
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0x0
[PcdsDynamicHii]
- gArmVirtTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gArmVirtVariableGuid|0x0|FALSE|NV,BS
+ gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gOvmfVariableGuid|0x0|FALSE|NV,BS
################################################################################
#
diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
index 9369a88858fd..9112cd6b07dc 100644
--- a/ArmVirtPkg/ArmVirtQemu.dsc
+++ b/ArmVirtPkg/ArmVirtQemu.dsc
@@ -286,7 +286,7 @@ [PcdsDynamicDefault.common]
!endif
[PcdsDynamicHii]
- gArmVirtTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gArmVirtVariableGuid|0x0|FALSE|NV,BS
+ gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gOvmfVariableGuid|0x0|FALSE|NV,BS
!if $(TPM2_CONFIG_ENABLE) == TRUE
gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x0|"1.3"|NV,BS
@@ -543,7 +543,7 @@ [Components.common]
#
# ACPI Support
#
- ArmVirtPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
+ OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
[Components.AARCH64]
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf {
diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
index 7f7d15d6eee3..21684f3666c8 100644
--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
+++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
@@ -457,7 +457,7 @@ [Components.common]
#
# ACPI Support
#
- ArmVirtPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
+ OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
[Components.AARCH64]
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf {
diff --git a/ArmVirtPkg/CloudHvPlatformHasAcpiDtDxe/CloudHvHasAcpiDtDxe.inf b/ArmVirtPkg/CloudHvPlatformHasAcpiDtDxe/CloudHvHasAcpiDtDxe.inf
index 4af06b2a6746..7cad40e11f33 100644
--- a/ArmVirtPkg/CloudHvPlatformHasAcpiDtDxe/CloudHvHasAcpiDtDxe.inf
+++ b/ArmVirtPkg/CloudHvPlatformHasAcpiDtDxe/CloudHvHasAcpiDtDxe.inf
@@ -36,7 +36,7 @@ [Guids]
gEdkiiPlatformHasDeviceTreeGuid ## SOMETIMES_PRODUCES ## PROTOCOL
[Pcd]
- gArmVirtTokenSpaceGuid.PcdForceNoAcpi
+ gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi
[Depex]
gEfiVariableArchProtocolGuid
diff --git a/ArmVirtPkg/KvmtoolPlatformDxe/KvmtoolPlatformDxe.inf b/ArmVirtPkg/KvmtoolPlatformDxe/KvmtoolPlatformDxe.inf
index 1cf25780f830..5888fcdc0b26 100644
--- a/ArmVirtPkg/KvmtoolPlatformDxe/KvmtoolPlatformDxe.inf
+++ b/ArmVirtPkg/KvmtoolPlatformDxe/KvmtoolPlatformDxe.inf
@@ -37,7 +37,7 @@ [Guids]
gEdkiiPlatformHasDeviceTreeGuid ## SOMETIMES_PRODUCES ## PROTOCOL
[Pcd]
- gArmVirtTokenSpaceGuid.PcdForceNoAcpi
+ gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi
[Depex]
TRUE
diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
index d4df6dede0fe..17799de845ba 100644
--- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
+++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
@@ -141,7 +141,7 @@ [FV.FvMain]
#
# ACPI Support
#
- INF ArmVirtPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
+ INF OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
!if $(ARCH) == AARCH64
INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 23/29] ArmVirtPkg/PlatformBootManagerLib: Move to OvmfPkg
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (21 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 22/29] ArmVirtPkg: Fix up the location of PlatformHasAcpiDtDxe Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 24/29] ArmVirtPkg: Fix up the paths to PlatformBootManagerLib Sunil V L
` (5 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Gerd Hoffmann,
Jiewen Yao, Jordan Justen
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
PlatformBootManagerLib in ArmVirtPkg is required for RISC-V
also. So, move it to OvmfPkg.
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>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/OvmfPkg.dec | 7 +++++++
.../PlatformBootManagerLibVirt}/PlatformBootManagerLib.inf | 3 +--
.../Library/PlatformBootManagerLibVirt}/PlatformBm.h | 0
.../Library/PlatformBootManagerLibVirt}/PlatformBm.c | 0
.../Library/PlatformBootManagerLibVirt}/QemuKernel.c | 0
OvmfPkg/OvmfPkg.ci.yaml | 1 +
6 files changed, 9 insertions(+), 2 deletions(-)
rename {ArmVirtPkg/Library/PlatformBootManagerLib => OvmfPkg/Library/PlatformBootManagerLibVirt}/PlatformBootManagerLib.inf (92%)
rename {ArmVirtPkg/Library/PlatformBootManagerLib => OvmfPkg/Library/PlatformBootManagerLibVirt}/PlatformBm.h (100%)
rename {ArmVirtPkg/Library/PlatformBootManagerLib => OvmfPkg/Library/PlatformBootManagerLibVirt}/PlatformBm.c (100%)
rename {ArmVirtPkg/Library/PlatformBootManagerLib => OvmfPkg/Library/PlatformBootManagerLibVirt}/QemuKernel.c (100%)
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 716c98e084fd..7d2acc5ea0e0 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -463,6 +463,13 @@ [PcdsDynamic, PcdsDynamicEx]
#
gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi|0x0|BOOLEAN|0x69
+ #
+ # Binary representation of the GUID that determines the terminal type. The
+ # size must be exactly 16 bytes. The default value corresponds to
+ # EFI_VT_100_GUID.
+ #
+ gUefiOvmfPkgTokenSpaceGuid.PcdTerminalTypeGuidBuffer|{0x65, 0x60, 0xA6, 0xDF, 0x19, 0xB4, 0xD3, 0x11, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}|VOID*|0x70
+
[PcdsFeatureFlag]
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBootManagerLib.inf
similarity index 92%
rename from ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
rename to OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBootManagerLib.inf
index 997eb1a4429f..a747ea3feac0 100644
--- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+++ b/OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBootManagerLib.inf
@@ -29,7 +29,6 @@ [Sources]
QemuKernel.c
[Packages]
- ArmVirtPkg/ArmVirtPkg.dec
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
OvmfPkg/OvmfPkg.dec
@@ -61,7 +60,7 @@ [FixedPcd]
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
[Pcd]
- gArmVirtTokenSpaceGuid.PcdTerminalTypeGuidBuffer
+ gUefiOvmfPkgTokenSpaceGuid.PcdTerminalTypeGuidBuffer
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
[Guids]
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.h b/OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBm.h
similarity index 100%
rename from ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.h
rename to OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBm.h
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c b/OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBm.c
similarity index 100%
rename from ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
rename to OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBm.c
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c b/OvmfPkg/Library/PlatformBootManagerLibVirt/QemuKernel.c
similarity index 100%
rename from ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c
rename to OvmfPkg/Library/PlatformBootManagerLibVirt/QemuKernel.c
diff --git a/OvmfPkg/OvmfPkg.ci.yaml b/OvmfPkg/OvmfPkg.ci.yaml
index ff022242b018..c6efb9a8e59e 100644
--- a/OvmfPkg/OvmfPkg.ci.yaml
+++ b/OvmfPkg/OvmfPkg.ci.yaml
@@ -22,6 +22,7 @@
],
## Both file path and directory path are accepted.
"IgnoreFiles": [
+ "Library/PlatformBootManagerLibVirt/PlatformBm.c"
],
"skip": True
},
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 24/29] ArmVirtPkg: Fix up the paths to PlatformBootManagerLib
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (22 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 23/29] ArmVirtPkg/PlatformBootManagerLib: Move to OvmfPkg Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library Sunil V L
` (4 subsequent siblings)
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Gerd Hoffmann
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
PlatformBootManagerLib has been moved to OvmfPkg so that other
CPU architectures can reuse. So, update existing paths with the
new location.
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>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
ArmVirtPkg/ArmVirtQemu.dsc | 4 ++--
ArmVirtPkg/ArmVirtQemuKernel.dsc | 4 ++--
ArmVirtPkg/ArmVirtPkg.ci.yaml | 1 -
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
index 9112cd6b07dc..0e460d21b2f5 100644
--- a/ArmVirtPkg/ArmVirtQemu.dsc
+++ b/ArmVirtPkg/ArmVirtQemu.dsc
@@ -71,7 +71,7 @@ [LibraryClasses.common]
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
- PlatformBootManagerLib|ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+ PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBootManagerLib.inf
PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
@@ -167,7 +167,7 @@ [PcdsFixedAtBuild.common]
!if $(TTY_TERMINAL) == TRUE
gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|4
# Set terminal type to TtyTerm, the value encoded is EFI_TTY_TERM_GUID
- gArmVirtTokenSpaceGuid.PcdTerminalTypeGuidBuffer|{0x80, 0x6d, 0x91, 0x7d, 0xb1, 0x5b, 0x8c, 0x45, 0xa4, 0x8f, 0xe2, 0x5f, 0xdd, 0x51, 0xef, 0x94}
+ gUefiOvmfPkgTokenSpaceGuid.PcdTerminalTypeGuidBuffer|{0x80, 0x6d, 0x91, 0x7d, 0xb1, 0x5b, 0x8c, 0x45, 0xa4, 0x8f, 0xe2, 0x5f, 0xdd, 0x51, 0xef, 0x94}
!else
gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|1
!endif
diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
index 21684f3666c8..e3967db53133 100644
--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
+++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
@@ -69,7 +69,7 @@ [LibraryClasses.common]
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
- PlatformBootManagerLib|ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+ PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBootManagerLib.inf
PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
@@ -146,7 +146,7 @@ [PcdsFixedAtBuild.common]
!if $(TTY_TERMINAL) == TRUE
gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|4
# Set terminal type to TtyTerm, the value encoded is EFI_TTY_TERM_GUID
- gArmVirtTokenSpaceGuid.PcdTerminalTypeGuidBuffer|{0x80, 0x6d, 0x91, 0x7d, 0xb1, 0x5b, 0x8c, 0x45, 0xa4, 0x8f, 0xe2, 0x5f, 0xdd, 0x51, 0xef, 0x94}
+ gUefiOvmfPkgTokenSpaceGuid.PcdTerminalTypeGuidBuffer|{0x80, 0x6d, 0x91, 0x7d, 0xb1, 0x5b, 0x8c, 0x45, 0xa4, 0x8f, 0xe2, 0x5f, 0xdd, 0x51, 0xef, 0x94}
!else
gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|1
!endif
diff --git a/ArmVirtPkg/ArmVirtPkg.ci.yaml b/ArmVirtPkg/ArmVirtPkg.ci.yaml
index 1e799dc4e194..552511c2694e 100644
--- a/ArmVirtPkg/ArmVirtPkg.ci.yaml
+++ b/ArmVirtPkg/ArmVirtPkg.ci.yaml
@@ -24,7 +24,6 @@
],
## Both file path and directory path are accepted.
"IgnoreFiles": [
- "Library/PlatformBootManagerLib/PlatformBm.c"
]
},
## options defined .pytool/Plugin/CompilerPlugin
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (23 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 24/29] ArmVirtPkg: Fix up the paths to PlatformBootManagerLib Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-19 12:19 ` Ard Biesheuvel
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver Sunil V L
` (3 subsequent siblings)
28 siblings, 1 reply; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Daniel Schaefer
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
This is copied from ArmVirtPkg since it is required for
other architectures also.
It also adds the instance for single flash drive which has
both code and variables. This is copied from SbsaQemu.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Daniel Schaefer <git@danielschaefer.me>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/OvmfPkg.dec | 8 ++
.../NorFlashQemuLib/NorFlashQemuLib.inf | 40 ++++++
.../NorFlashQemuUnifiedLib.inf | 30 ++++
OvmfPkg/Include/Library/NorFlashPlatformLib.h | 30 ++++
.../Library/NorFlashQemuLib/NorFlashQemuLib.c | 136 ++++++++++++++++++
.../NorFlashQemuLib/NorFlashQemuUnifiedLib.c | 40 ++++++
6 files changed, 284 insertions(+)
create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
create mode 100644 OvmfPkg/Include/Library/NorFlashPlatformLib.h
create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 7d2acc5ea0e0..0697c91c6836 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -129,6 +129,10 @@ [LibraryClasses]
#
HardwareInfoLib|Include/Library/HardwareInfoLib.h
+ ## @libraryclass NorFlashQemuLib
+ #
+ NorFlashPlatformLib|Include/Library/NorFlashPlatformLib.h
+
[Guids]
gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
@@ -405,6 +409,10 @@ [PcdsFixedAtBuild]
# check to decide whether to abort dispatch of the driver it is linked into.
gUefiOvmfPkgTokenSpaceGuid.PcdEntryPointOverrideFwCfgVarName|""|VOID*|0x68
+ ## The base address and size of the FVMAIN
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvBaseAddress|0|UINT64|0x71
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvSize|0|UINT32|0x72
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
new file mode 100644
index 000000000000..ecd8059b3508
--- /dev/null
+++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
@@ -0,0 +1,40 @@
+#/** @file
+#
+# Component description file for NorFlashQemuLib module
+#
+# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = NorFlashQemuLib
+ FILE_GUID = 42C30D8E-BFAD-4E77-9041-E7DAAE88DF7A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NorFlashPlatformLib
+
+[Sources.common]
+ NorFlashQemuLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gFdtClientProtocolGuid ## CONSUMES
+
+[Depex]
+ gFdtClientProtocolGuid
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvBaseAddress
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvSize
diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
new file mode 100644
index 000000000000..91d1406fc3e7
--- /dev/null
+++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
@@ -0,0 +1,30 @@
+#/** @file
+#
+# Component description file for NorFlashQemuLib module
+#
+# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = NorFlashQemuUnifiedLib
+ FILE_GUID = 064742F1-E531-4D7D-A154-22315889CC23
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NorFlashPlatformLib
+
+[Sources.common]
+ NorFlashQemuUnifiedLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
diff --git a/OvmfPkg/Include/Library/NorFlashPlatformLib.h b/OvmfPkg/Include/Library/NorFlashPlatformLib.h
new file mode 100644
index 000000000000..6ef5b70e9948
--- /dev/null
+++ b/OvmfPkg/Include/Library/NorFlashPlatformLib.h
@@ -0,0 +1,30 @@
+/** @file
+
+ Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#ifndef _NORFLASHPLATFORMLIB_H_
+#define _NORFLASHPLATFORMLIB_H_
+
+typedef struct {
+ UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA)
+ UINTN RegionBaseAddress; // Start address of one single region
+ UINTN Size;
+ UINTN BlockSize;
+} NOR_FLASH_DESCRIPTION;
+
+EFI_STATUS
+NorFlashPlatformInitialization (
+ VOID
+ );
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+ OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
+ OUT UINT32 *Count
+ );
+
+#endif /* _NORFLASHPLATFORMLIB_H_ */
diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
new file mode 100644
index 000000000000..3632fa9e7a98
--- /dev/null
+++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
@@ -0,0 +1,136 @@
+/** @file
+
+ Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/NorFlashPlatformLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/FdtClient.h>
+
+#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
+
+#define MAX_FLASH_BANKS 4
+
+EFI_STATUS
+NorFlashPlatformInitialization (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+ OUT 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;
+
+ Status = gBS->LocateProtocol (
+ &gFdtClientProtocolGuid,
+ NULL,
+ (VOID **)&FdtClient
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Num = 0;
+ 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",
+ __FUNCTION__,
+ 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 ((PcdGet64 (PcdOvmfFvBaseAddress) + PcdGet32 (PcdOvmfFvSize) > Base) &&
+ ((Base + Size) > PcdGet64 (PcdOvmfFvBaseAddress)))
+ {
+ continue;
+ }
+
+ mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base;
+ mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base;
+ mNorFlashDevices[Num].Size = (UINTN)Size;
+ mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE;
+ Num++;
+ }
+
+ //
+ // 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/NorFlashQemuLib/NorFlashQemuUnifiedLib.c b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
new file mode 100644
index 000000000000..1420fb5b596c
--- /dev/null
+++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
@@ -0,0 +1,40 @@
+/** @file
+
+ Copyright (c) 2019, Linaro Ltd. All rights reserved
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#include <Base.h>
+#include <PiDxe.h>
+#include <Library/NorFlashPlatformLib.h>
+
+#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
+
+EFI_STATUS
+NorFlashPlatformInitialization (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+NOR_FLASH_DESCRIPTION mNorFlashDevice =
+{
+ FixedPcdGet32 (PcdOvmfFdBaseAddress),
+ FixedPcdGet64 (PcdFlashNvStorageVariableBase),
+ FixedPcdGet32 (PcdOvmfFirmwareFdSize),
+ QEMU_NOR_BLOCK_SIZE
+};
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+ OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
+ OUT UINT32 *Count
+ )
+{
+ *NorFlashDescriptions = &mNorFlashDevice;
+ *Count = 1;
+ return EFI_SUCCESS;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (24 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library Sunil V L
@ 2022-10-10 10:11 ` Sunil V L
2022-10-10 10:39 ` Ard Biesheuvel
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 27/29] OvmfPkg: RiscVVirt: Add Qemu Virt platform support Sunil V L
` (2 subsequent siblings)
28 siblings, 1 reply; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:11 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
RISC-V needs NorFlashDxe driver for qemu virt machine. The
ArmPlatformPkg has this driver but migrating it to generic
package like MdeModulePkg introduces circular dependencies.
So, add a simplified version of the NorFlashDxe driver in
OvmfPkg.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf | 69 ++
OvmfPkg/Drivers/NorFlashDxe/NorFlash.h | 422 ++++++++
OvmfPkg/Drivers/NorFlashDxe/NorFlash.c | 972 ++++++++++++++++++
.../Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | 123 +++
OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c | 506 +++++++++
OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c | 777 ++++++++++++++
6 files changed, 2869 insertions(+)
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
new file mode 100644
index 000000000000..e327b2ac7405
--- /dev/null
+++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
@@ -0,0 +1,69 @@
+#/** @file
+#
+# Component description file for NorFlashDxe module
+#
+# Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QemuNorFlashDxe
+ FILE_GUID = D4F3B3FC-3AEF-4774-AC94-304438ABDA53
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = NorFlashInitialise
+
+[Sources.common]
+ NorFlash.c
+ NorFlash.h
+ NorFlashDxe.c
+ NorFlashFvb.c
+ NorFlashBlockIoDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ IoLib
+ BaseLib
+ DebugLib
+ HobLib
+ NorFlashPlatformLib
+ UefiLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeLib
+ DxeServicesTableLib
+
+[Guids]
+ gEfiSystemNvDataFvGuid
+ gEfiVariableGuid
+ gEfiAuthenticatedVariableGuid
+ gEfiEventVirtualAddressChangeGuid
+ gEdkiiNvVarStoreFormattedGuid ## PRODUCES ## PROTOCOL
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid
+ gEfiDiskIoProtocolGuid
+
+[Pcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Depex]
+ gEfiCpuArchProtocolGuid
diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
new file mode 100644
index 000000000000..c83032e87d9c
--- /dev/null
+++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
@@ -0,0 +1,422 @@
+/** @file NorFlash.h
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __NOR_FLASH_H__
+#define __NOR_FLASH_H__
+
+#include <Base.h>
+#include <PiDxe.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/NorFlashPlatformLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#define NOR_FLASH_ERASE_RETRY 10
+
+// Device access macros
+// These are necessary because we use 2 x 16bit parts to make up 32bit data
+
+#define HIGH_16_BITS 0xFFFF0000
+#define LOW_16_BITS 0x0000FFFF
+#define LOW_8_BITS 0x000000FF
+
+#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
+
+#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )
+#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )
+
+// Each command must be sent simultaneously to both chips,
+// i.e. at the lower 16 bits AND at the higher 16 bits
+#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + ((OffsetAddr) << 2))
+#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
+#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))
+#define GET_NOR_BLOCK_ADDRESS(BaseAddr, Lba, LbaSize) ( BaseAddr + (UINTN)((Lba) * LbaSize) )
+
+// Status Register Bits
+#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)
+#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)
+#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)
+#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)
+#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)
+#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)
+#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)
+#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)
+
+// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
+
+// On chip buffer size for buffered programming operations
+// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
+// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
+#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)
+#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
+#define MAX_BUFFERED_PROG_ITERATIONS 10000000
+#define BOUNDARY_OF_32_WORDS 0x7F
+
+// CFI Addresses
+#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10
+#define P30_CFI_ADDR_VENDOR_ID 0x13
+
+// CFI Data
+#define CFI_QRY 0x00595251
+
+// READ Commands
+#define P30_CMD_READ_DEVICE_ID 0x0090
+#define P30_CMD_READ_STATUS_REGISTER 0x0070
+#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050
+#define P30_CMD_READ_ARRAY 0x00FF
+#define P30_CMD_READ_CFI_QUERY 0x0098
+
+// WRITE Commands
+#define P30_CMD_WORD_PROGRAM_SETUP 0x0040
+#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010
+#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8
+#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0
+#define P30_CMD_BEFP_SETUP 0x0080
+#define P30_CMD_BEFP_CONFIRM 0x00D0
+
+// ERASE Commands
+#define P30_CMD_BLOCK_ERASE_SETUP 0x0020
+#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0
+
+// SUSPEND Commands
+#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0
+#define P30_CMD_SUSPEND_RESUME 0x00D0
+
+// BLOCK LOCKING / UNLOCKING Commands
+#define P30_CMD_LOCK_BLOCK_SETUP 0x0060
+#define P30_CMD_LOCK_BLOCK 0x0001
+#define P30_CMD_UNLOCK_BLOCK 0x00D0
+#define P30_CMD_LOCK_DOWN_BLOCK 0x002F
+
+// PROTECTION Commands
+#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
+
+// CONFIGURATION Commands
+#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
+#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003
+
+#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
+#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
+#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
+#define INSTANCE_FROM_DISKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, DiskIoProtocol, NOR_FLASH_SIGNATURE)
+
+typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
+
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ UINT8 Index;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} NOR_FLASH_DEVICE_PATH;
+#pragma pack ()
+
+struct _NOR_FLASH_INSTANCE {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+
+ UINTN DeviceBaseAddress;
+ UINTN RegionBaseAddress;
+ UINTN Size;
+ EFI_LBA StartLba;
+
+ EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
+ EFI_BLOCK_IO_MEDIA Media;
+ EFI_DISK_IO_PROTOCOL DiskIoProtocol;
+
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+ VOID *ShadowBuffer;
+
+ NOR_FLASH_DEVICE_PATH DevicePath;
+};
+
+EFI_STATUS
+NorFlashReadCfiData (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN CFI_Offset,
+ IN UINT32 NumberOfBytes,
+ OUT UINT32 *Data
+ );
+
+EFI_STATUS
+NorFlashWriteBuffer (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN TargetAddress,
+ IN UINTN BufferSizeInBytes,
+ IN UINT32 *Buffer
+ );
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ );
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ );
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+//
+// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.ReadDisk
+//
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoReadDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+//
+// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.WriteDisk
+//
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoWriteDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+//
+// NorFlashFvbDxe.c
+//
+
+EFI_STATUS
+EFIAPI
+FvbGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ );
+
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ );
+
+EFI_STATUS
+ValidateFvHeader (
+ IN NOR_FLASH_INSTANCE *Instance
+ );
+
+EFI_STATUS
+InitializeFvAndVariableStoreHeaders (
+ IN NOR_FLASH_INSTANCE *Instance
+ );
+
+VOID
+EFIAPI
+FvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+//
+// NorFlashDxe.c
+//
+
+EFI_STATUS
+NorFlashWriteFullBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINT32 *DataBuffer,
+ IN UINT32 BlockSizeInWords
+ );
+
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ );
+
+EFI_STATUS
+NorFlashCreateInstance (
+ IN UINTN NorFlashDeviceBase,
+ IN UINTN NorFlashRegionBase,
+ IN UINTN NorFlashSize,
+ IN UINT32 Index,
+ IN UINT32 BlockSize,
+ IN BOOLEAN SupportFvb,
+ OUT NOR_FLASH_INSTANCE **NorFlashInstance
+ );
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE *Instance
+ );
+
+//
+// NorFlash.c
+//
+EFI_STATUS
+NorFlashWriteSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+NorFlashWriteBlocks (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashReadBlocks (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashRead (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashWrite (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+NorFlashReset (
+ IN NOR_FLASH_INSTANCE *Instance
+ );
+
+EFI_STATUS
+NorFlashEraseSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ );
+
+EFI_STATUS
+NorFlashUnlockSingleBlockIfNecessary (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ );
+
+EFI_STATUS
+NorFlashWriteSingleWord (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN WordAddress,
+ IN UINT32 WriteData
+ );
+
+VOID
+EFIAPI
+NorFlashVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif /* __NOR_FLASH_H__ */
diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
new file mode 100644
index 000000000000..c2a6aa281578
--- /dev/null
+++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
@@ -0,0 +1,972 @@
+/** @file NorFlash.c
+
+ Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.<BR>
+ Copyright (c) 2020, Linaro, Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+
+#include "NorFlash.h"
+
+//
+// Global variable declarations
+//
+extern NOR_FLASH_INSTANCE **mNorFlashInstances;
+extern UINT32 mNorFlashDeviceCount;
+
+UINT32
+NorFlashReadStatusRegister (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN SR_Address
+ )
+{
+ // Prepare to read the status register
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);
+ return MmioRead32 (Instance->DeviceBaseAddress);
+}
+
+STATIC
+BOOLEAN
+NorFlashBlockIsLocked (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ UINT32 LockStatus;
+
+ // Send command for reading device id
+ SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
+
+ // Read block lock status
+ LockStatus = MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2));
+
+ // Decode block lock status
+ LockStatus = FOLD_32BIT_INTO_16BIT (LockStatus);
+
+ if ((LockStatus & 0x2) != 0) {
+ DEBUG ((DEBUG_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN\n"));
+ }
+
+ return ((LockStatus & 0x1) != 0);
+}
+
+STATIC
+EFI_STATUS
+NorFlashUnlockSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ UINT32 LockStatus;
+
+ // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
+ // and to protect shared data structures.
+
+ // Request a lock setup
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
+
+ // Request an unlock
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
+
+ // Wait until the status register gives us the all clear
+ do {
+ LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
+ } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY);
+
+ DEBUG ((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x\n", BlockAddress));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashUnlockSingleBlockIfNecessary (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (NorFlashBlockIsLocked (Instance, BlockAddress)) {
+ Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
+ }
+
+ return Status;
+}
+
+/**
+ * The following function presumes that the block has already been unlocked.
+ **/
+EFI_STATUS
+NorFlashEraseSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT32 StatusRegister;
+
+ Status = EFI_SUCCESS;
+
+ // Request a block erase and then confirm it
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP);
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM);
+
+ // Wait until the status register gives us the all clear
+ do {
+ StatusRegister = NorFlashReadStatusRegister (Instance, BlockAddress);
+ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+ if (StatusRegister & P30_SR_BIT_VPP) {
+ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: VPP Range Error\n", BlockAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) == (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) {
+ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Command Sequence Error\n", BlockAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_ERASE) {
+ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Erase Error StatusRegister:0x%X\n", BlockAddress, StatusRegister));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+ // The debug level message has been reduced because a device lock might happen. In this case we just retry it ...
+ DEBUG ((DEBUG_INFO, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error\n", BlockAddress));
+ Status = EFI_WRITE_PROTECTED;
+ }
+
+ if (EFI_ERROR (Status)) {
+ // Clear the Status Register
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ }
+
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ return Status;
+}
+
+EFI_STATUS
+NorFlashWriteSingleWord (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN WordAddress,
+ IN UINT32 WriteData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 StatusRegister;
+
+ Status = EFI_SUCCESS;
+
+ // Request a write single word command
+ SEND_NOR_COMMAND (WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP);
+
+ // Store the word into NOR Flash;
+ MmioWrite32 (WordAddress, WriteData);
+
+ // Wait for the write to complete and then check for any errors; i.e. check the Status Register
+ do {
+ // Prepare to read the status register
+ StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress);
+ // The chip is busy while the WRITE bit is not asserted
+ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+ // Perform a full status check:
+ // Mask the relevant bits of Status Register.
+ // Everything should be zero, if not, we have a problem
+
+ if (StatusRegister & P30_SR_BIT_VPP) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): VPP Range Error\n", WordAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_PROGRAM) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Program Error\n", WordAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Device Protect Error\n", WordAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ // Clear the Status Register
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ }
+
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ return Status;
+}
+
+/*
+ * Writes data to the NOR Flash using the Buffered Programming method.
+ *
+ * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions.
+ * Therefore this function will only handle buffers up to 32 words or 128 bytes.
+ * To deal with larger buffers, call this function again.
+ *
+ * This function presumes that both the TargetAddress and the TargetAddress+BufferSize
+ * exist entirely within the NOR Flash. Therefore these conditions will not be checked here.
+ *
+ * In buffered programming, if the target address not at the beginning of a 32-bit word boundary,
+ * then programming time is doubled and power consumption is increased.
+ * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries.
+ * i.e. the last 4 bits of the target start address must be zero: 0x......00
+ */
+EFI_STATUS
+NorFlashWriteBuffer (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN TargetAddress,
+ IN UINTN BufferSizeInBytes,
+ IN UINT32 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSizeInWords;
+ UINTN Count;
+ volatile UINT32 *Data;
+ UINTN WaitForBuffer;
+ BOOLEAN BufferAvailable;
+ UINT32 StatusRegister;
+
+ WaitForBuffer = MAX_BUFFERED_PROG_ITERATIONS;
+ BufferAvailable = FALSE;
+
+ // Check that the target address does not cross a 32-word boundary.
+ if ((TargetAddress & BOUNDARY_OF_32_WORDS) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check there are some data to program
+ if (BufferSizeInBytes == 0) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Check that the buffer size does not exceed the maximum hardware buffer size on chip.
+ if (BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Check that the buffer size is a multiple of 32-bit words
+ if ((BufferSizeInBytes % 4) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Pre-programming conditions checked, now start the algorithm.
+
+ // Prepare the data destination address
+ Data = (UINT32 *)TargetAddress;
+
+ // Check the availability of the buffer
+ do {
+ // Issue the Buffered Program Setup command
+ SEND_NOR_COMMAND (TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP);
+
+ // Read back the status register bit#7 from the same address
+ if (((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE) {
+ BufferAvailable = TRUE;
+ }
+
+ // Update the loop counter
+ WaitForBuffer--;
+ } while ((WaitForBuffer > 0) && (BufferAvailable == FALSE));
+
+ // The buffer was not available for writing
+ if (WaitForBuffer == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // From now on we work in 32-bit words
+ BufferSizeInWords = BufferSizeInBytes / (UINTN)4;
+
+ // Write the word count, which is (buffer_size_in_words - 1),
+ // because word count 0 means one word.
+ SEND_NOR_COMMAND (TargetAddress, 0, (BufferSizeInWords - 1));
+
+ // Write the data to the NOR Flash, advancing each address by 4 bytes
+ for (Count = 0; Count < BufferSizeInWords; Count++, Data++, Buffer++) {
+ MmioWrite32 ((UINTN)Data, *Buffer);
+ }
+
+ // Issue the Buffered Program Confirm command, to start the programming operation
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM);
+
+ // Wait for the write to complete and then check for any errors; i.e. check the Status Register
+ do {
+ StatusRegister = NorFlashReadStatusRegister (Instance, TargetAddress);
+ // The chip is busy while the WRITE bit is not asserted
+ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+ // Perform a full status check:
+ // Mask the relevant bits of Status Register.
+ // Everything should be zero, if not, we have a problem
+
+ Status = EFI_SUCCESS;
+
+ if (StatusRegister & P30_SR_BIT_VPP) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): VPP Range Error\n", TargetAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_PROGRAM) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Program Error\n", TargetAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Device Protect Error\n", TargetAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ // Clear the Status Register
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ }
+
+EXIT:
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ return Status;
+}
+
+EFI_STATUS
+NorFlashWriteBlocks (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ )
+{
+ UINT32 *pWriteBuffer;
+ EFI_STATUS Status;
+ EFI_LBA CurrentBlock;
+ UINT32 BlockSizeInWords;
+ UINT32 NumBlocks;
+ UINT32 BlockCount;
+
+ Status = EFI_SUCCESS;
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Instance->Media.ReadOnly == TRUE) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ // We must have some bytes to read
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes));
+ if (BufferSizeInBytes == 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // The size of the buffer must be a multiple of the block size
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize));
+ if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // All blocks must be within the device
+ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba));
+
+ if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockSizeInWords = Instance->Media.BlockSize / 4;
+
+ // Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer
+ // to a proper data type, so use *ReadBuffer
+ pWriteBuffer = (UINT32 *)Buffer;
+
+ CurrentBlock = Lba;
+ for (BlockCount = 0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++, pWriteBuffer = pWriteBuffer + BlockSizeInWords) {
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock));
+
+ Status = NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffer, BlockSizeInWords);
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status));
+ return Status;
+}
+
+#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0)
+
+/**
+ Copy Length bytes from Source to Destination, using aligned accesses only.
+ Note that this implementation uses memcpy() semantics rather then memmove()
+ semantics, i.e., SourceBuffer and DestinationBuffer should not overlap.
+
+ @param DestinationBuffer The target of the copy request.
+ @param SourceBuffer The place to copy from.
+ @param Length The number of bytes to copy.
+
+ @return Destination
+
+**/
+STATIC
+VOID *
+AlignedCopyMem (
+ OUT VOID *DestinationBuffer,
+ IN CONST VOID *SourceBuffer,
+ IN UINTN Length
+ )
+{
+ UINT8 *Destination8;
+ CONST UINT8 *Source8;
+ UINT32 *Destination32;
+ CONST UINT32 *Source32;
+ UINT64 *Destination64;
+ CONST UINT64 *Source64;
+
+ if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 8) && (Length >= 8)) {
+ Destination64 = DestinationBuffer;
+ Source64 = SourceBuffer;
+ while (Length >= 8) {
+ *Destination64++ = *Source64++;
+ Length -= 8;
+ }
+
+ Destination8 = (UINT8 *)Destination64;
+ Source8 = (CONST UINT8 *)Source64;
+ } else if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 4) && (Length >= 4)) {
+ Destination32 = DestinationBuffer;
+ Source32 = SourceBuffer;
+ while (Length >= 4) {
+ *Destination32++ = *Source32++;
+ Length -= 4;
+ }
+
+ Destination8 = (UINT8 *)Destination32;
+ Source8 = (CONST UINT8 *)Source32;
+ } else {
+ Destination8 = DestinationBuffer;
+ Source8 = SourceBuffer;
+ }
+
+ while (Length-- != 0) {
+ *Destination8++ = *Source8++;
+ }
+
+ return DestinationBuffer;
+}
+
+EFI_STATUS
+NorFlashReadBlocks (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ UINT32 NumBlocks;
+ UINTN StartAddress;
+
+ DEBUG ((
+ DEBUG_BLKIO,
+ "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
+ BufferSizeInBytes,
+ Instance->Media.BlockSize,
+ Instance->Media.LastBlock,
+ Lba
+ ));
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Return if we have not any byte to read
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+
+ // The size of the buffer must be a multiple of the block size
+ if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // All blocks must be within the device
+ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
+
+ if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
+ DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the address to start reading from
+ StartAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Lba,
+ Instance->Media.BlockSize
+ );
+
+ // Put the device into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ // Readout the data
+ AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashRead (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ UINTN StartAddress;
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Return if we have not any byte to read
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
+ DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the address to start reading from
+ StartAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Lba,
+ Instance->Media.BlockSize
+ );
+
+ // Put the device into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ // Readout the data
+ AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
+
+ return EFI_SUCCESS;
+}
+
+/*
+ Write a full or portion of a block. It must not span block boundaries; that is,
+ Offset + *NumBytes <= Instance->Media.BlockSize.
+*/
+EFI_STATUS
+NorFlashWriteSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS TempStatus;
+ UINT32 Tmp;
+ UINT32 TmpBuf;
+ UINT32 WordToWrite;
+ UINT32 Mask;
+ BOOLEAN DoErase;
+ UINTN BytesToWrite;
+ UINTN CurOffset;
+ UINTN WordAddr;
+ UINTN BlockSize;
+ UINTN BlockAddress;
+ UINTN PrevBlockAddress;
+
+ PrevBlockAddress = 0;
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not write: Device is in WriteDisabled state.\n"));
+ // It is in WriteDisabled state, return an error right away
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ // The write must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ((Offset >= BlockSize) ||
+ (*NumBytes > BlockSize) ||
+ ((Offset + *NumBytes) > BlockSize))
+ {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to write
+ if (*NumBytes == 0) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Pick 128bytes as a good start for word operations as opposed to erasing the
+ // block and writing the data regardless if an erase is really needed.
+ // It looks like most individual NV variable writes are smaller than 128bytes.
+ if (*NumBytes <= 128) {
+ // Check to see if we need to erase before programming the data into NOR.
+ // If the destination bits are only changing from 1s to 0s we can just write.
+ // After a block is erased all bits in the block is set to 1.
+ // If any byte requires us to erase we just give up and rewrite all of it.
+ DoErase = FALSE;
+ BytesToWrite = *NumBytes;
+ CurOffset = Offset;
+
+ while (BytesToWrite > 0) {
+ // Read full word from NOR, splice as required. A word is the smallest
+ // unit we can write.
+ TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof (Tmp), &Tmp);
+ if (EFI_ERROR (TempStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Physical address of word in NOR to write.
+ WordAddr = (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Lba,
+ BlockSize
+ );
+ // The word of data that is to be written.
+ TmpBuf = *((UINT32 *)(Buffer + (*NumBytes - BytesToWrite)));
+
+ // First do word aligned chunks.
+ if ((CurOffset & 0x3) == 0) {
+ if (BytesToWrite >= 4) {
+ // Is the destination still in 'erased' state?
+ if (~Tmp != 0) {
+ // Check to see if we are only changing bits to zero.
+ if ((Tmp ^ TmpBuf) & TmpBuf) {
+ DoErase = TRUE;
+ break;
+ }
+ }
+
+ // Write this word to NOR
+ WordToWrite = TmpBuf;
+ CurOffset += sizeof (TmpBuf);
+ BytesToWrite -= sizeof (TmpBuf);
+ } else {
+ // BytesToWrite < 4. Do small writes and left-overs
+ Mask = ~((~0) << (BytesToWrite * 8));
+ // Mask out the bytes we want.
+ TmpBuf &= Mask;
+ // Is the destination still in 'erased' state?
+ if ((Tmp & Mask) != Mask) {
+ // Check to see if we are only changing bits to zero.
+ if ((Tmp ^ TmpBuf) & TmpBuf) {
+ DoErase = TRUE;
+ break;
+ }
+ }
+
+ // Merge old and new data. Write merged word to NOR
+ WordToWrite = (Tmp & ~Mask) | TmpBuf;
+ CurOffset += BytesToWrite;
+ BytesToWrite = 0;
+ }
+ } else {
+ // Do multiple words, but starting unaligned.
+ if (BytesToWrite > (4 - (CurOffset & 0x3))) {
+ Mask = ((~0) << ((CurOffset & 0x3) * 8));
+ // Mask out the bytes we want.
+ TmpBuf &= Mask;
+ // Is the destination still in 'erased' state?
+ if ((Tmp & Mask) != Mask) {
+ // Check to see if we are only changing bits to zero.
+ if ((Tmp ^ TmpBuf) & TmpBuf) {
+ DoErase = TRUE;
+ break;
+ }
+ }
+
+ // Merge old and new data. Write merged word to NOR
+ WordToWrite = (Tmp & ~Mask) | TmpBuf;
+ BytesToWrite -= (4 - (CurOffset & 0x3));
+ CurOffset += (4 - (CurOffset & 0x3));
+ } else {
+ // Unaligned and fits in one word.
+ Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8);
+ // Mask out the bytes we want.
+ TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;
+ // Is the destination still in 'erased' state?
+ if ((Tmp & Mask) != Mask) {
+ // Check to see if we are only changing bits to zero.
+ if ((Tmp ^ TmpBuf) & TmpBuf) {
+ DoErase = TRUE;
+ break;
+ }
+ }
+
+ // Merge old and new data. Write merged word to NOR
+ WordToWrite = (Tmp & ~Mask) | TmpBuf;
+ CurOffset += BytesToWrite;
+ BytesToWrite = 0;
+ }
+ }
+
+ //
+ // Write the word to NOR.
+ //
+
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
+ if (BlockAddress != PrevBlockAddress) {
+ TempStatus = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
+ if (EFI_ERROR (TempStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ PrevBlockAddress = BlockAddress;
+ }
+
+ TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
+ if (EFI_ERROR (TempStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ // Exit if we got here and could write all the data. Otherwise do the
+ // Erase-Write cycle.
+ if (!DoErase) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ // Check we did get some memory. Buffer is BlockSize.
+ if (Instance->ShadowBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Read NOR Flash data into shadow buffer
+ TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
+ if (EFI_ERROR (TempStatus)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Put the data at the appropriate location inside the buffer area
+ CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
+
+ // Write the modified buffer back to the NorFlash
+ TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
+ if (EFI_ERROR (TempStatus)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/*
+ Although DiskIoDxe will automatically install the DiskIO protocol whenever
+ we install the BlockIO protocol, its implementation is sub-optimal as it reads
+ and writes entire blocks using the BlockIO protocol. In fact we can access
+ NOR flash with a finer granularity than that, so we can improve performance
+ by directly producing the DiskIO protocol.
+*/
+
+/**
+ Read BufferSize bytes from Offset into Buffer.
+
+ @param This Protocol instance pointer.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Offset The starting byte offset to read from
+ @param BufferSize Size of Buffer
+ @param Buffer Buffer containing read data
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
+ @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
+ valid for the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoReadDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 DiskOffset,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ UINT32 BlockSize;
+ UINT32 BlockOffset;
+ EFI_LBA Lba;
+
+ Instance = INSTANCE_FROM_DISKIO_THIS (This);
+
+ if (MediaId != Instance->Media.MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ BlockSize = Instance->Media.BlockSize;
+ Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
+
+ return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer);
+}
+
+/**
+ Writes a specified number of bytes to a device.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId ID of the medium to be written.
+ @param Offset The starting byte offset on the logical block I/O device to write.
+ @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
+ @param Buffer A pointer to the buffer containing the data to be written.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
+ @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
+ valid for the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoWriteDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 DiskOffset,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ UINT32 BlockSize;
+ UINT32 BlockOffset;
+ EFI_LBA Lba;
+ UINTN RemainingBytes;
+ UINTN WriteSize;
+ EFI_STATUS Status;
+
+ Instance = INSTANCE_FROM_DISKIO_THIS (This);
+
+ if (MediaId != Instance->Media.MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ BlockSize = Instance->Media.BlockSize;
+ Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
+
+ RemainingBytes = BufferSize;
+
+ // Write either all the remaining bytes, or the number of bytes that bring
+ // us up to a block boundary, whichever is less.
+ // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next
+ // block boundary (even if it is already on one).
+ WriteSize = MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) - DiskOffset);
+
+ do {
+ if (WriteSize == BlockSize) {
+ // Write a full block
+ Status = NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize / sizeof (UINT32));
+ } else {
+ // Write a partial block
+ Status = NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &WriteSize, Buffer);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Now continue writing either all the remaining bytes or single blocks.
+ RemainingBytes -= WriteSize;
+ Buffer = (UINT8 *)Buffer + WriteSize;
+ Lba++;
+ BlockOffset = 0;
+ WriteSize = MIN (RemainingBytes, BlockSize);
+ } while (RemainingBytes);
+
+ return Status;
+}
+
+EFI_STATUS
+NorFlashReset (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+ return EFI_SUCCESS;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+NorFlashVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress);
+
+ // Convert BlockIo protocol
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
+
+ // Convert Fvb
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Read);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Write);
+
+ if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowBuffer);
+ }
+ }
+
+ return;
+}
diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
new file mode 100644
index 000000000000..9d4732c6905a
--- /dev/null
+++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
@@ -0,0 +1,123 @@
+/** @file NorFlashBlockIoDxe.c
+
+ Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "NorFlash.h"
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_BLKIO_THIS (This);
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
+
+ return NorFlashReset (Instance);
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = INSTANCE_FROM_BLKIO_THIS (This);
+ Media = This->Media;
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, BufferSizeInBytes, Buffer));
+
+ if (!Media) {
+ Status = EFI_INVALID_PARAMETER;
+ } else if (!Media->MediaPresent) {
+ Status = EFI_NO_MEDIA;
+ } else if (Media->MediaId != MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ } else if ((Media->IoAlign > 2) && (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ Status = NorFlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
+ }
+
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ EFI_STATUS Status;
+
+ Instance = INSTANCE_FROM_BLKIO_THIS (This);
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes, BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
+
+ if ( !This->Media->MediaPresent ) {
+ Status = EFI_NO_MEDIA;
+ } else if ( This->Media->MediaId != MediaId ) {
+ Status = EFI_MEDIA_CHANGED;
+ } else if ( This->Media->ReadOnly ) {
+ Status = EFI_WRITE_PROTECTED;
+ } else {
+ Status = NorFlashWriteBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
+ }
+
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ // No Flush required for the NOR Flash driver
+ // because cache operations are not permitted.
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
+
+ // Nothing to do so just return without error
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
new file mode 100644
index 000000000000..f7b92de21a57
--- /dev/null
+++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
@@ -0,0 +1,506 @@
+/** @file NorFlashDxe.c
+
+ Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesTableLib.h>
+
+#include "NorFlash.h"
+
+STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
+
+//
+// Global variable declarations
+//
+NOR_FLASH_INSTANCE **mNorFlashInstances;
+UINT32 mNorFlashDeviceCount;
+UINTN mFlashNvStorageVariableBase;
+EFI_EVENT mFvbVirtualAddrChangeEvent;
+
+NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
+ NOR_FLASH_SIGNATURE, // Signature
+ NULL, // Handle ... NEED TO BE FILLED
+
+ 0, // DeviceBaseAddress ... NEED TO BE FILLED
+ 0, // RegionBaseAddress ... NEED TO BE FILLED
+ 0, // Size ... NEED TO BE FILLED
+ 0, // StartLba
+
+ {
+ EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision
+ NULL, // Media ... NEED TO BE FILLED
+ NorFlashBlockIoReset, // Reset;
+ NorFlashBlockIoReadBlocks, // ReadBlocks
+ NorFlashBlockIoWriteBlocks, // WriteBlocks
+ NorFlashBlockIoFlushBlocks // FlushBlocks
+ }, // BlockIoProtocol
+
+ {
+ 0, // MediaId ... NEED TO BE FILLED
+ FALSE, // RemovableMedia
+ TRUE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching;
+ 0, // BlockSize ... NEED TO BE FILLED
+ 4, // IoAlign
+ 0, // LastBlock ... NEED TO BE FILLED
+ 0, // LowestAlignedLba
+ 1, // LogicalBlocksPerPhysicalBlock
+ }, // Media;
+
+ {
+ EFI_DISK_IO_PROTOCOL_REVISION, // Revision
+ NorFlashDiskIoReadDisk, // ReadDisk
+ NorFlashDiskIoWriteDisk // WriteDisk
+ },
+
+ {
+ FvbGetAttributes, // GetAttributes
+ FvbSetAttributes, // SetAttributes
+ FvbGetPhysicalAddress, // GetPhysicalAddress
+ FvbGetBlockSize, // GetBlockSize
+ FvbRead, // Read
+ FvbWrite, // Write
+ FvbEraseBlocks, // EraseBlocks
+ NULL, // ParentHandle
+ }, // FvbProtoccol;
+ NULL, // ShadowBuffer
+ {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),
+ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)
+ }
+ },
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
+ }, // GUID ... NEED TO BE FILLED
+ },
+ 0, // Index
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ }
+ } // DevicePath
+};
+
+EFI_STATUS
+NorFlashCreateInstance (
+ IN UINTN NorFlashDeviceBase,
+ IN UINTN NorFlashRegionBase,
+ IN UINTN NorFlashSize,
+ IN UINT32 Index,
+ IN UINT32 BlockSize,
+ IN BOOLEAN SupportFvb,
+ OUT NOR_FLASH_INSTANCE **NorFlashInstance
+ )
+{
+ EFI_STATUS Status;
+ NOR_FLASH_INSTANCE *Instance;
+
+ ASSERT (NorFlashInstance != NULL);
+
+ Instance = AllocateRuntimeCopyPool (sizeof (NOR_FLASH_INSTANCE), &mNorFlashInstanceTemplate);
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Instance->DeviceBaseAddress = NorFlashDeviceBase;
+ Instance->RegionBaseAddress = NorFlashRegionBase;
+ Instance->Size = NorFlashSize;
+
+ Instance->BlockIoProtocol.Media = &Instance->Media;
+ Instance->Media.MediaId = Index;
+ Instance->Media.BlockSize = BlockSize;
+ Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
+
+ CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
+ Instance->DevicePath.Index = (UINT8)Index;
+
+ Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);
+ if (Instance->ShadowBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (SupportFvb) {
+ NorFlashFvbInitialize (Instance);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid,
+ &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &Instance->BlockIoProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ &Instance->FvbProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Instance);
+ return Status;
+ }
+ } else {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid,
+ &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &Instance->BlockIoProtocol,
+ &gEfiDiskIoProtocolGuid,
+ &Instance->DiskIoProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Instance);
+ return Status;
+ }
+ }
+
+ *NorFlashInstance = Instance;
+ return Status;
+}
+
+/**
+ * This function unlock and erase an entire NOR Flash block.
+ **/
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_TPL OriginalTPL;
+
+ if (!EfiAtRuntime ()) {
+ // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ } else {
+ // This initialization is only to prevent the compiler to complain about the
+ // use of uninitialized variables
+ OriginalTPL = TPL_HIGH_LEVEL;
+ }
+
+ Index = 0;
+ // The block erase might fail a first time (SW bug ?). Retry it ...
+ do {
+ // Unlock the block if we have to
+ Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
+ Index++;
+ } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
+
+ if (Index == NOR_FLASH_ERASE_RETRY) {
+ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));
+ }
+
+ if (!EfiAtRuntime ()) {
+ // Interruptions can resume.
+ gBS->RestoreTPL (OriginalTPL);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+NorFlashWriteFullBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINT32 *DataBuffer,
+ IN UINT32 BlockSizeInWords
+ )
+{
+ EFI_STATUS Status;
+ UINTN WordAddress;
+ UINT32 WordIndex;
+ UINTN BufferIndex;
+ UINTN BlockAddress;
+ UINTN BuffersInBlock;
+ UINTN RemainingWords;
+ EFI_TPL OriginalTPL;
+ UINTN Cnt;
+
+ Status = EFI_SUCCESS;
+
+ // Get the physical address of the block
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4);
+
+ // Start writing from the first address at the start of the block
+ WordAddress = BlockAddress;
+
+ if (!EfiAtRuntime ()) {
+ // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ } else {
+ // This initialization is only to prevent the compiler to complain about the
+ // use of uninitialized variables
+ OriginalTPL = TPL_HIGH_LEVEL;
+ }
+
+ Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
+ goto EXIT;
+ }
+
+ // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
+
+ // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero
+ if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) {
+ // First, break the entire block into buffer-sized chunks.
+ BuffersInBlock = (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;
+
+ // Then feed each buffer chunk to the NOR Flash
+ // If a buffer does not contain any data, don't write it.
+ for (BufferIndex = 0;
+ BufferIndex < BuffersInBlock;
+ BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
+ )
+ {
+ // Check the buffer to see if it contains any data (not set all 1s).
+ for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {
+ if (~DataBuffer[Cnt] != 0 ) {
+ // Some data found, write the buffer.
+ Status = NorFlashWriteBuffer (
+ Instance,
+ WordAddress,
+ P30_MAX_BUFFER_SIZE_IN_BYTES,
+ DataBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Finally, finish off any remaining words that are less than the maximum size of the buffer
+ RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
+
+ if (RemainingWords != 0) {
+ Status = NorFlashWriteBuffer (Instance, WordAddress, (RemainingWords * 4), DataBuffer);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ }
+ } else {
+ // For now, use the single word programming algorithm
+ // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,
+ // i.e. which ends in the range 0x......01 - 0x......7F.
+ for (WordIndex = 0; WordIndex < BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4) {
+ Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ }
+ }
+
+EXIT:
+ if (!EfiAtRuntime ()) {
+ // Interruptions can resume.
+ gBS->RestoreTPL (OriginalTPL);
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashInitialise (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ NOR_FLASH_DESCRIPTION *NorFlashDevices;
+ BOOLEAN ContainVariableStorage;
+
+ Status = NorFlashPlatformInitialization ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to initialize Nor Flash devices\n"));
+ return Status;
+ }
+
+ Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to get Nor Flash devices\n"));
+ return Status;
+ }
+
+ mNorFlashInstances = AllocateRuntimePool (sizeof (NOR_FLASH_INSTANCE *) * mNorFlashDeviceCount);
+
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ // Check if this NOR Flash device contain the variable storage region
+
+ if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
+ ContainVariableStorage =
+ (NorFlashDevices[Index].RegionBaseAddress <= PcdGet64 (PcdFlashNvStorageVariableBase64)) &&
+ (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvStorageVariableSize) <=
+ NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
+ } else {
+ ContainVariableStorage =
+ (NorFlashDevices[Index].RegionBaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) &&
+ (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize) <=
+ NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
+ }
+
+ Status = NorFlashCreateInstance (
+ NorFlashDevices[Index].DeviceBaseAddress,
+ NorFlashDevices[Index].RegionBaseAddress,
+ NorFlashDevices[Index].Size,
+ Index,
+ NorFlashDevices[Index].BlockSize,
+ ContainVariableStorage,
+ &mNorFlashInstances[Index]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n", Index));
+ }
+ }
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ NorFlashVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mNorFlashVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FvbNumLba;
+ EFI_BOOT_MODE BootMode;
+ UINTN RuntimeMmioRegionSize;
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashFvbInitialize\n"));
+ ASSERT ((Instance != NULL));
+
+ //
+ // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
+ //
+
+ // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;
+ // even if we only use the small block region at the top of the NOR Flash.
+ // The reason is when the NOR Flash memory is set into program mode, the command
+ // is written as the base of the flash region (ie: Instance->DeviceBaseAddress)
+ RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
+
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ Instance->DeviceBaseAddress,
+ RuntimeMmioRegionSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ Instance->DeviceBaseAddress,
+ RuntimeMmioRegionSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mFlashNvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
+ PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);
+
+ // Set the index of the first LBA for the FVB
+ Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->Media.BlockSize;
+
+ BootMode = GetBootModeHob ();
+ if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // Determine if there is a valid header at the beginning of the NorFlash
+ Status = ValidateFvHeader (Instance);
+ }
+
+ // Install the Default FVB header if required
+ if (EFI_ERROR (Status)) {
+ // There is no valid header, so time to install one.
+ DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Installing a correct one for this volume.\n",
+ __FUNCTION__
+ ));
+
+ // Erase all the NorFlash that is reserved for variable storage
+ FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
+
+ Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Install all appropriate headers
+ Status = InitializeFvAndVariableStoreHeaders (Instance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // The driver implementing the variable read service can now be dispatched;
+ // the varstore headers are in place.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gImageHandle,
+ &gEdkiiNvVarStoreFormattedGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FvbVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mFvbVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
new file mode 100644
index 000000000000..0767581308d2
--- /dev/null
+++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
@@ -0,0 +1,777 @@
+/*++ @file NorFlashFvbDxe.c
+
+ Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ --*/
+
+#include <PiDxe.h>
+
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/VariableFormat.h>
+#include <Guid/SystemNvDataGuid.h>
+#include <Guid/NvVarStoreFormatted.h>
+
+#include "NorFlash.h"
+
+extern UINTN mFlashNvStorageVariableBase;
+///
+/// The Firmware Volume Block Protocol is the low-level interface
+/// to a firmware volume. File-level access to a firmware volume
+/// should not be done using the Firmware Volume Block Protocol.
+/// Normal access to a firmware volume must use the Firmware
+/// Volume Protocol. Typically, only the file system driver that
+/// produces the Firmware Volume Protocol will bind to the
+/// Firmware Volume Block Protocol.
+///
+
+/**
+ Initialises the FV Header and Variable Store Header
+ to support variable operations.
+
+ @param[in] Ptr - Location to initialise the headers
+
+**/
+EFI_STATUS
+InitializeFvAndVariableStoreHeaders (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ EFI_STATUS Status;
+ VOID *Headers;
+ UINTN HeadersLength;
+ EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINT32 NvStorageFtwSpareSize;
+ UINT32 NvStorageFtwWorkingSize;
+ UINT32 NvStorageVariableSize;
+ UINT64 NvStorageFtwSpareBase;
+ UINT64 NvStorageFtwWorkingBase;
+ UINT64 NvStorageVariableBase;
+
+ HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + sizeof (VARIABLE_STORE_HEADER);
+ Headers = AllocateZeroPool (HeadersLength);
+
+ NvStorageFtwWorkingSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+ NvStorageFtwSpareSize = PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+ NvStorageVariableSize = PcdGet32 (PcdFlashNvStorageVariableSize);
+
+ NvStorageFtwSpareBase = (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) != 0) ?
+ PcdGet64 (PcdFlashNvStorageFtwSpareBase64) : PcdGet32 (PcdFlashNvStorageFtwSpareBase);
+ NvStorageFtwWorkingBase = (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) != 0) ?
+ PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) : PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
+ NvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
+ PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);
+
+ // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
+ if ((NvStorageVariableBase + NvStorageVariableSize) != NvStorageFtwWorkingBase) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: NvStorageFtwWorkingBase is not contiguous with NvStorageVariableBase region\n",
+ __FUNCTION__
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((NvStorageFtwWorkingBase + NvStorageFtwWorkingSize) != NvStorageFtwSpareBase) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: NvStorageFtwSpareBase is not contiguous with NvStorageFtwWorkingBase region\n",
+ __FUNCTION__
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the size of the area is at least one block size
+ if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->Media.BlockSize <= 0)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n",
+ __FUNCTION__,
+ NvStorageVariableSize
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->Media.BlockSize <= 0)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n",
+ __FUNCTION__,
+ NvStorageFtwWorkingSize
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->Media.BlockSize <= 0)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n",
+ __FUNCTION__,
+ NvStorageFtwSpareSize
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Ensure the Variable area Base Addresses are aligned on a block size boundaries
+ if ((NvStorageVariableBase % Instance->Media.BlockSize != 0) ||
+ (NvStorageFtwWorkingBase % Instance->Media.BlockSize != 0) ||
+ (NvStorageFtwSpareBase % Instance->Media.BlockSize != 0))
+ {
+ DEBUG ((DEBUG_ERROR, "%a: NvStorage Base addresses must be aligned to block size boundaries", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // EFI_FIRMWARE_VOLUME_HEADER
+ //
+ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers;
+ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
+ FirmwareVolumeHeader->FvLength =
+ PcdGet32 (PcdFlashNvStorageVariableSize) +
+ PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
+ FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2)(
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
+ );
+ FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
+ FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize;
+ FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
+ FirmwareVolumeHeader->BlockMap[1].Length = 0;
+ FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength);
+
+ //
+ // VARIABLE_STORE_HEADER
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
+ VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+
+ // Install the combined super-header in the NorFlash
+ Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
+
+ FreePool (Headers);
+ return Status;
+}
+
+/**
+ Check the integrity of firmware volume header.
+
+ @param[in] FwVolHeader - A pointer to a firmware volume header
+
+ @retval EFI_SUCCESS - The firmware volume is consistent
+ @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ UINT16 Checksum;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress;
+
+ FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
+ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
+ || (FwVolHeader->FvLength != FvLength)
+ )
+ {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: No Firmware Volume header present\n",
+ __FUNCTION__
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Firmware Volume Guid non-compatible\n",
+ __FUNCTION__
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ // Verify the header checksum
+ Checksum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength);
+ if (Checksum != 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: FV checksum is invalid (Checksum:0x%X)\n",
+ __FUNCTION__,
+ Checksum
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)FwVolHeader + FwVolHeader->HeaderLength);
+
+ // Check the Variable Store Guid
+ if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
+ !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid))
+ {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Variable Store Guid non-compatible\n",
+ __FUNCTION__
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Variable Store Length does not match\n",
+ __FUNCTION__
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetAttributes() function retrieves the attributes and
+ current settings of the block.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
+ current settings are returned.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2)(
+
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
+
+ );
+
+ // Check if it is write protected
+ if (Instance->Media.ReadOnly != TRUE) {
+ FlashFvbAttributes = FlashFvbAttributes |
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
+ }
+
+ *Attributes = FlashFvbAttributes;
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The SetAttributes() function sets configurable firmware volume attributes
+ and returns the new settings of the firmware volume.
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2
+ that contains the desired firmware volume settings.
+ On successful return, it contains the new settings of
+ the firmware volume.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities
+ as declared in the firmware volume header.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n", *Attributes));
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The GetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Address Pointer to a caller-allocated
+ EFI_PHYSICAL_ADDRESS that, on successful
+ return from GetPhysicalAddress(), contains the
+ base address of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->RegionBaseAddress));
+
+ ASSERT (Address != NULL);
+
+ *Address = mFlashNvStorageVariableBase;
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The GetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block for which to return the size.
+
+ @param BlockSize Pointer to a caller-allocated UINTN in which
+ the size of the block is returned.
+
+ @param NumberOfBlocks Pointer to a caller-allocated UINTN in
+ which the number of consecutive blocks,
+ starting with Lba, is returned. All
+ blocks in this range have a size of
+ BlockSize.
+
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+{
+ EFI_STATUS Status;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->Media.BlockSize, Instance->Media.LastBlock));
+
+ if (Lba > Instance->Media.LastBlock) {
+ DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // This is easy because in this platform each NorFlash device has equal sized blocks.
+ *BlockSize = (UINTN)Instance->Media.BlockSize;
+ *NumberOfBlocks = (UINTN)(Instance->Media.LastBlock - Lba + 1);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks));
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The Read() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+ Implementations should be mindful that the firmware volume
+ might be in the ReadDisabled state. If it is in this state,
+ the Read() function must return the status code
+ EFI_ACCESS_DENIED without modifying the contents of the
+ buffer. The Read() function must also prevent spanning block
+ boundaries. If a read is requested that would span a block
+ boundary, the read must read up to the boundary but not
+ beyond. The output parameter NumBytes must be set to correctly
+ indicate the number of bytes actually read. The caller must be
+ aware that a read may be partially completed.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index from which to read.
+
+ @param Offset Offset into the block at which to begin reading.
+
+ @param NumBytes Pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes read.
+
+ @param Buffer Pointer to a caller-allocated buffer that will be used
+ to hold the data that is read.
+
+ @retval EFI_SUCCESS The firmware volume was read successfully, and contents are
+ in Buffer.
+
+ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ returned in Buffer.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS TempStatus;
+ UINTN BlockSize;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
+
+ TempStatus = EFI_SUCCESS;
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
+
+ // The read must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ((Offset >= BlockSize) ||
+ (*NumBytes > BlockSize) ||
+ ((Offset + *NumBytes) > BlockSize))
+ {
+ DEBUG ((DEBUG_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to read
+ if (*NumBytes == 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Decide if we are doing full block reads or not.
+ if (*NumBytes % BlockSize != 0) {
+ TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer);
+ if (EFI_ERROR (TempStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+ } else {
+ // Read NOR Flash data into shadow buffer
+ TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer);
+ if (EFI_ERROR (TempStatus)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The Write() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset. If the
+ firmware volume is sticky write, the caller must ensure that
+ all the bits of the specified range to write are in the
+ EFI_FVB_ERASE_POLARITY state before calling the Write()
+ function, or else the result will be unpredictable. This
+ unpredictability arises because, for a sticky-write firmware
+ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
+ state but cannot flip it back again. Before calling the
+ Write() function, it is recommended for the caller to first call
+ the EraseBlocks() function to erase the specified block to
+ write. A block erase cycle will transition bits from the
+ (NOT)EFI_FVB_ERASE_POLARITY state back to the
+ EFI_FVB_ERASE_POLARITY state. Implementations should be
+ mindful that the firmware volume might be in the WriteDisabled
+ state. If it is in this state, the Write() function must
+ return the status code EFI_ACCESS_DENIED without modifying the
+ contents of the firmware volume. The Write() function must
+ also prevent spanning block boundaries. If a write is
+ requested that spans a block boundary, the write must store up
+ to the boundary but not beyond. The output parameter NumBytes
+ must be set to correctly indicate the number of bytes actually
+ written. The caller must be aware that a write may be
+ partially completed. All writes, partial or otherwise, must be
+ fully flushed to the hardware before the Write() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index to write to.
+
+ @param Offset Offset into the block at which to begin writing.
+
+ @param NumBytes The pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes actually written.
+
+ @param Buffer The pointer to a caller-allocated buffer that contains the source for the write.
+
+ @retval EFI_SUCCESS The firmware volume was written successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ actually written.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written.
+
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset, NumBytes, Buffer);
+}
+
+/**
+ Erases and initialises a firmware volume block.
+
+ The EraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list. The entire parameter list of
+ blocks must be verified before erasing any blocks. If a block is
+ requested that does not exist within the associated firmware
+ volume (it has a larger index than the last block of the
+ firmware volume), the EraseBlocks() function must return the
+ status code EFI_INVALID_PARAMETER without modifying the contents
+ of the firmware volume. Implementations should be mindful that
+ the firmware volume might be in the WriteDisabled state. If it
+ is in this state, the EraseBlocks() function must return the
+ status code EFI_ACCESS_DENIED without modifying the contents of
+ the firmware volume. All calls to EraseBlocks() must be fully
+ flushed to the hardware before the EraseBlocks() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+
+ @param ... The variable argument list is a list of tuples.
+ Each tuple describes a range of LBAs to erase
+ and consists of the following:
+ - An EFI_LBA that indicates the starting LBA
+ - A UINTN that indicates the number of blocks to erase.
+
+ The list is terminated with an EFI_LBA_LIST_TERMINATOR.
+ For example, the following indicates that two ranges of blocks
+ (5-7 and 10-11) are to be erased:
+ EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
+
+ @retval EFI_SUCCESS The erase request successfully completed.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written.
+ The firmware device may have been partially erased.
+
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do
+ not exist in the firmware volume.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Args;
+ UINTN BlockAddress; // Physical address of Lba to erase
+ EFI_LBA StartingLba; // Lba from which we start erasing
+ UINTN NumOfLba; // Number of Lba blocks to erase
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n"));
+
+ Status = EFI_SUCCESS;
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ // Firmware volume is in WriteDisabled state
+ DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
+
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ // Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINTN);
+
+ // All blocks must be within range
+ DEBUG ((
+ DEBUG_BLKIO,
+ "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n",
+ Instance->StartLba + StartingLba,
+ (UINT64)NumOfLba,
+ Instance->Media.LastBlock
+ ));
+ if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) {
+ VA_END (Args);
+ DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ } while (TRUE);
+
+ VA_END (Args);
+
+ //
+ // To get here, all must be ok, so start erasing
+ //
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ // Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINTN);
+
+ // Go through each one and erase it
+ while (NumOfLba > 0) {
+ // Get the physical address of Lba to erase
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Instance->StartLba + StartingLba,
+ Instance->Media.BlockSize
+ );
+
+ // Erase it
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress));
+ Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
+ if (EFI_ERROR (Status)) {
+ VA_END (Args);
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // Move to the next Lba
+ StartingLba++;
+ NumOfLba--;
+ }
+ } while (TRUE);
+
+ VA_END (Args);
+
+EXIT:
+ return Status;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+FvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase);
+ return;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 27/29] OvmfPkg: RiscVVirt: Add Qemu Virt platform support
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (25 preceding siblings ...)
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver Sunil V L
@ 2022-10-10 10:12 ` Sunil V L
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 28/29] Maintainers.txt: Add entry for OvmfPkg/RiscVVirt Sunil V L
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 29/29] UefiCpuPkg/UefiCpuPkg.ci.yaml: Ignore RISC-V file Sunil V L
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:12 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
Add infrastructure files to build edk2 for RISC-V qemu virt machine.
- EDK2 will boot as S-mode payload of opensbi.
- It supports building
either code and variables in unified flash or in two separate drives
via build time option UNIFIED_NVVARS.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
OvmfPkg/Platforms/RiscVVirt/RiscVVirt.dsc | 726 ++++++++++++++++++
OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf | 406 ++++++++++
OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf.inc | 66 ++
OvmfPkg/Platforms/RiscVVirt/VarStore.fdf.inc | 79 ++
4 files changed, 1277 insertions(+)
create mode 100644 OvmfPkg/Platforms/RiscVVirt/RiscVVirt.dsc
create mode 100644 OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf
create mode 100644 OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf.inc
create mode 100644 OvmfPkg/Platforms/RiscVVirt/VarStore.fdf.inc
diff --git a/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.dsc b/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.dsc
new file mode 100644
index 000000000000..63d95e91abe2
--- /dev/null
+++ b/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.dsc
@@ -0,0 +1,726 @@
+## @file
+# RISC-V EFI on RiscVVirt RISC-V platform
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+# Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = RiscVVirt
+ PLATFORM_GUID = 39DADB39-1B21-4867-838E-830B6149B9E0
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x0001001c
+ OUTPUT_DIRECTORY = Build/$(PLATFORM_NAME)
+ SUPPORTED_ARCHITECTURES = RISCV64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+ FLASH_DEFINITION = OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf
+
+ #
+ # Enable below options may cause build error or may not work on
+ # the initial version of RISC-V package
+ # Defines for default states. These can be changed on the command line.
+ # -D FLAG=VALUE
+ #
+ DEFINE SECURE_BOOT_ENABLE = FALSE
+ DEFINE DEBUG_ON_SERIAL_PORT = TRUE
+
+ #
+ # Network definition
+ #
+ DEFINE NETWORK_SNP_ENABLE = FALSE
+ DEFINE NETWORK_IP6_ENABLE = FALSE
+ DEFINE NETWORK_TLS_ENABLE = TRUE
+ DEFINE NETWORK_HTTP_BOOT_ENABLE = TRUE
+ DEFINE NETWORK_ISCSI_ENABLE = FALSE
+ DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+
+[BuildOptions]
+ GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ GCC:*_*_RISCV64_GENFW_FLAGS = --keepexceptiontable
+!endif
+
+[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
+ GCC: *_*_*_DLINK_FLAGS = -z common-page-size=0x1000
+ MSFT: *_*_*_DLINK_FLAGS = /ALIGN:4096
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this Platform.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
+ PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
+ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+ SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
+ VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+ FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+ TimerLib|UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
+ TimeBaseLib|EmbeddedPkg//Library/TimeBaseLib/TimeBaseLib.inf
+ RealTimeClockLib|EmbeddedPkg//Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
+!ifdef $(UNIFIED_VARSTORE)
+ NorFlashPlatformLib|OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
+!else
+ NorFlashPlatformLib|OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
+!endif
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
+
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+ DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
+!else
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+!endif
+
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+ TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+ AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+!else
+ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+ AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+!endif
+ VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+
+!if $(HTTP_BOOT_ENABLE) == TRUE
+ HttpLib|MdeModulePkg/Library/DxeHttpLib/DxeHttpLib.inf
+!endif
+
+ SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
+ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
+
+[LibraryClasses.common]
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+!endif
+
+ RiscVSbiLib|MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf
+
+ # PCI Libraries
+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ PciCapLib|OvmfPkg/Library/BasePciCapLib/BasePciCapLib.inf
+ PciCapPciSegmentLib|OvmfPkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf
+ PciCapPciIoLib|OvmfPkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf
+ DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+
+ # Virtio Support
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
+ QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
+ QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
+ QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
+
+ # PCI support
+ PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+ PciHostBridgeLib|MdeModulePkg/Library/PciHostBridgeLibNull/PciHostBridgeLibNull.inf
+
+ # Boot Manager
+!if $(TPM2_ENABLE) == TRUE
+ Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
+ Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
+ TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.inf
+!else
+ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf
+!endif
+
+ BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
+ PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf
+
+ PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibVirt/PlatformBootManagerLib.inf
+
+ FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+ QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
+ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+
+[LibraryClasses.common.SEC]
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf
+
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+
+[LibraryClasses.common.PEI_CORE]
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+
+[LibraryClasses.common.PEIM]
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeiResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+ ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+
+[LibraryClasses.common.DXE_CORE]
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+!endif
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ PciExpressLib|OvmfPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExpressLib.inf
+ PciPcdProducerLib|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
+ PciHostBridgeLib|OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
+ PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ PlatformUpdateProgressLib|MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+
+[LibraryClasses.common.UEFI_APPLICATION]
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform.
+#
+################################################################################
+[PcdsFeatureFlag]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
+ gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x02
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+!endif
+
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
+!endif
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x04
+ gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04
+ gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04
+!endif
+
+ #
+ # F2 for UI APP
+ #
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString|L"2.7"
+
+ # Serial Port
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x10000000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate|9600
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|3686400
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1
+
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|800
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|600
+
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|10
+
+ # Set video resolution for text setup.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0208
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform.
+#
+################################################################################
+[Components]
+
+ #
+ # SEC Phase modules
+ #
+ OvmfPkg/Sec/SecMain.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ }
+
+ #
+ # PEI Phase modules
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ }
+
+ OvmfPkg/PlatformPei/PlatformPei.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ PlatformInitLib|OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
+ }
+
+ #
+ # DXE Phase modules
+ #
+ MdeModulePkg/Core/Dxe/DxeMain.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg//Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ }
+
+ MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+ MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+
+ MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
+ <LibraryClasses>
+ NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+ }
+!else
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+!endif
+
+ MdeModulePkg/Universal/Metronome/Metronome.inf
+ EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+
+ #
+ # RISC-V Platform module
+ #
+ UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf
+
+ OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
+
+ #
+ # RISC-V Core module
+ #
+ UefiCpuPkg/CpuDxe/CpuDxe.inf
+ MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+
+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ }
+ MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+ MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+ MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+
+# Graphic console
+ MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+
+ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+ MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+ MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+ MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+ MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+ MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+ MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+
+ #
+ # Network Support
+ #
+ !include NetworkPkg/Network.dsc.inc
+
+ #
+ # Usb Support
+ #
+ MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+ MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+ MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+ MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+ #
+ # PCI support
+ #
+ UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf {
+ <LibraryClasses>
+ NULL|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
+ }
+ MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+ MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
+ <LibraryClasses>
+ NULL|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
+ }
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+ OvmfPkg/Virtio10Dxe/Virtio10.inf
+
+ #
+ # Video support
+ #
+ OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
+ OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
+ OvmfPkg/PlatformDxe/Platform.inf
+
+ #
+ # Platform Driver
+ #
+ OvmfPkg/Fdt/VirtioFdtDxe/VirtioFdtDxe.inf
+ EmbeddedPkg/Drivers/FdtClientDxe/FdtClientDxe.inf
+ OvmfPkg/Fdt/HighMemDxe/HighMemDxe.inf
+ OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+ OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+ OvmfPkg/VirtioNetDxe/VirtioNet.inf
+ OvmfPkg/VirtioRngDxe/VirtioRng.inf
+
+ MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+ OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
+
+ #
+ # FAT filesystem + GPT/MBR partitioning + UDF filesystem
+ #
+ FatPkg/EnhancedFatDxe/Fat.inf
+ MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
+ OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ <LibraryClasses>
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ }
+
+ ShellPkg/Application/Shell/Shell.inf {
+ <LibraryClasses>
+ ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
+ NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
+ HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+
+ <PcdsFixedAtBuild>
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
+ }
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!endif
+
+ #
+ # Bds
+ #
+ MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf {
+ <LibraryClasses>
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+ MdeModulePkg/Logo/LogoDxe.inf
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+ NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
+ NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
+ }
+ OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf {
+ <LibraryClasses>
+ NULL|OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierLibNull.inf
+ }
+
+# HTTPS(secure) support in GUI for updating ssl keys for PXE boot
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+ NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
+ NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
+ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ }
+
+# TFTP support for PXE boot
+ ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ <LibraryClasses>
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ }
+ ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ <LibraryClasses>
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ }
+
+ # HTTP support for PXE boot
+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ <LibraryClasses>
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
+ }
+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ <LibraryClasses>
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
+ }
+
+# HTTPS (secure) support for PXE boot
+ NetworkPkg/TlsDxe/TlsDxe.inf {
+ <LibraryClasses>
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+ TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
+ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+ RngLib|MdePkg/Library/DxeRngLib/DxeRngLib.inf
+ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ }
+ NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {
+ <LibraryClasses>
+ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf
+ }
+
+[PcdsDynamicDefault.common]
+ # set PcdPciExpressBaseAddress to MAX_UINT64, which signifies that this
+ # PCD and PcdPciDisableBusEnumeration above have not been assigned yet
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xFFFFFFFFFFFFFFFF
+
+ gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation|0x0
+
+[PcdsFeatureFlag.common]
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|TRUE
+
+ ## If TRUE, Graphics Output Protocol will be installed on virtual handle created by ConsplitterDxe.
+ # It could be set FALSE to save size.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
diff --git a/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf b/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf
new file mode 100644
index 000000000000..3e0e0eb9ae77
--- /dev/null
+++ b/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf
@@ -0,0 +1,406 @@
+# @file
+# Flash definition file on RiscVVirt RISC-V platform
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+# Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# Platform definitions
+#
+
+!include RiscVVirt.fdf.inc
+
+################################################################################
+!ifdef UNIFIED_VARSTORE
+[FD.RISCV_VIRT]
+BaseAddress = $(FW_BASE_ADDRESS)|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+Size = $(FW_SIZE)|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize
+ErasePolarity = 1
+BlockSize = $(BLOCK_SIZE)
+NumBlocks = $(FW_BLOCKS)
+
+$(SECFV_OFFSET)|$(SECFV_SIZE)
+FV = SECFV
+
+$(FVMAIN_OFFSET)|$(FVMAIN_SIZE)
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvBaseAddress|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvSize
+FV = FVMAIN_COMPACT
+
+!include VarStore.fdf.inc
+
+!else
+[FD.RISCV_CODE]
+BaseAddress = $(FW_BASE_ADDRESS)|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+Size = $(CODE_SIZE)
+ErasePolarity = 1
+BlockSize = $(BLOCK_SIZE)
+NumBlocks = $(CODE_BLOCKS)
+
+$(SECFV_OFFSET)|$(SECFV_SIZE)
+FV = SECFV
+
+$(FVMAIN_OFFSET)|$(FVMAIN_SIZE)
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvBaseAddress|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvSize
+FV = FVMAIN_COMPACT
+
+################################################################################
+[FD.RISCV_NVVARS]
+BaseAddress = $(VARS_BASE_ADDRESS)
+Size = $(VARS_SIZE)
+ErasePolarity = 1
+BlockSize = $(VARS_BLOCK_SIZE)
+NumBlocks = $(VARS_BLOCKS)
+
+!include VarStore.fdf.inc
+!endif
+################################################################################
+
+[FD.RISCV_MEMFD]
+BaseAddress = $(MEMFD_BASE_ADDRESS)
+Size = 0x00a00000
+ErasePolarity = 1
+BlockSize = $(BLOCK_SIZE)
+NumBlocks = 0xa00
+
+0x00000000|0x00010000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+
+0x00010000|0x001000
+gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+
+0x00040000|0x00080000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
+FV = PEIFV
+
+0x00100000|0x00900000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+FV = DXEFV
+
+##########################################################################################
+
+[FV.SECFV]
+BlockSize = 0x1000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+#
+# SEC Phase modules
+#
+# The code in this FV handles the initial firmware startup, and
+# decompresses the PEI and DXE FVs which handles the rest of the boot sequence.
+#
+INF OvmfPkg/Sec/SecMain.inf
+
+################################################################################
+[FV.PEIFV]
+BlockSize = 0x10000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+APRIORI PEI {
+ INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+}
+
+#
+# PEI Phase modules
+#
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+# RISC-V Platform PEI Driver
+INF OvmfPkg/PlatformPei/PlatformPei.inf
+
+################################################################################
+
+[FV.DXEFV]
+BlockSize = 0x10000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+APRIORI DXE {
+ INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+ INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+}
+
+#
+# DXE Phase modules
+#
+INF MdeModulePkg/Core/Dxe/DxeMain.inf
+
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+#
+# PCI support
+#
+INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+INF OvmfPkg/Virtio10Dxe/Virtio10.inf
+
+#
+# Video support
+#
+INF OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
+INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
+INF OvmfPkg/PlatformDxe/Platform.inf
+
+#
+# Platform Driver
+#
+INF OvmfPkg/Fdt/VirtioFdtDxe/VirtioFdtDxe.inf
+INF EmbeddedPkg/Drivers/FdtClientDxe/FdtClientDxe.inf
+INF OvmfPkg/Fdt/HighMemDxe/HighMemDxe.inf
+INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+INF OvmfPkg/VirtioNetDxe/VirtioNet.inf
+INF OvmfPkg/VirtioRngDxe/VirtioRng.inf
+INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+
+INF MdeModulePkg/Universal/Metronome/Metronome.inf
+INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+
+INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+INF OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+INF OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
+
+# RISC-V Platform Drivers
+INF OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
+
+# RISC-V Core Drivers
+INF UefiCpuPkg/CpuTimerDxe/CpuTimerDxe.inf
+INF UefiCpuPkg/CpuDxe/CpuDxe.inf
+
+INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+
+INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!endif
+
+INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+INF MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+INF FatPkg/EnhancedFatDxe/Fat.inf
+INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
+!ifndef $(SOURCE_DEBUG_ENABLE)
+INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+!endif
+
+INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
+INF ShellPkg/Application/Shell/Shell.inf
+
+# TFTP support for PXE boot
+INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf
+
+# HTTP support for PXE boot
+INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
+INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
+
+#
+# Network modules
+#
+!if $(E1000_ENABLE)
+ FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 {
+ SECTION PE32 = Intel3.5/EFIX64/E3507X2.EFI
+ }
+!endif
+
+!include NetworkPkg/Network.fdf.inc
+
+#
+# Usb Support
+#
+INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+INF MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+INF MdeModulePkg/Application/UiApp/UiApp.inf
+INF OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
+
+################################################################################
+
+[FV.FVMAIN_COMPACT]
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 27A72E80-3118-4c0c-8673-AA5B4EFA9613
+
+FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+ SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+ #
+ # These firmware volumes will have files placed in them uncompressed,
+ # and then both firmware volumes will be compressed in a single
+ # compression operation in order to achieve better overall compression.
+ #
+ SECTION FV_IMAGE = PEIFV
+ SECTION FV_IMAGE = DXEFV
+ }
+ }
+
+[Rule.Common.SEC]
+ FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEI_CORE]
+ FILE PEI_CORE = $(NAMED_GUID) {
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEIM]
+ FILE PEIM = $(NAMED_GUID) {
+ PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_CORE]
+ FILE DXE_CORE = $(NAMED_GUID) {
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align = 4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ PE32 PE32 Align=4K |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 Align=4K |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+ FILE FREEFORM = $(NAMED_GUID) {
+ RAW ACPI |.acpi
+ RAW ASL |.aml
+ }
diff --git a/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf.inc b/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf.inc
new file mode 100644
index 000000000000..5a2d96d53c8e
--- /dev/null
+++ b/OvmfPkg/Platforms/RiscVVirt/RiscVVirt.fdf.inc
@@ -0,0 +1,66 @@
+## @file
+# Definitions of Flash definition file on RiscVVirt RISC-V platform
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+# Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+DEFINE BLOCK_SIZE = 0x1000
+
+DEFINE PFLASH1_BASE = 0x22000000
+DEFINE PFLASH2_BASE = 0x23000000
+
+DEFINE FW_BASE_ADDRESS = $(PFLASH1_BASE)
+DEFINE FW_SIZE = 0x00300000
+DEFINE FW_BLOCKS = 0x300
+
+DEFINE CODE_BASE_ADDRESS = $(FW_BASE_ADDRESS)
+DEFINE CODE_SIZE = 0x00240000
+DEFINE CODE_BLOCKS = 0x240
+
+#
+# Separate varstore will start at 3rd pflash address
+#
+DEFINE VARS_BASE_ADDRESS = $(PFLASH2_BASE)
+
+DEFINE VARS_SIZE = 0x000C0000
+DEFINE VARS_BLOCK_SIZE = 0x40000
+DEFINE VARS_BLOCKS = 0x3
+
+#
+# The size of memory region must be power of 2.
+# The base address must be aligned with the size.
+#
+# FW memory region
+#
+DEFINE SECFV_OFFSET = 0x00000000
+DEFINE SECFV_SIZE = 0x00040000
+DEFINE FVMAIN_OFFSET = 0x00040000
+DEFINE FVMAIN_SIZE = 0x00200000
+
+#
+# EFI Variable memory region.
+# The total size of EFI Variable FD must include
+# all of sub regions of EFI Variable
+#
+!ifdef $(UNIFIED_VARSTORE)
+DEFINE VARS_OFFSET = $(CODE_SIZE)
+!else
+DEFINE VARS_OFFSET = 0x00000000
+!endif
+DEFINE VARS_LIVE_SIZE = 0x00040000
+DEFINE VARS_FTW_WORKING_OFFSET = $(VARS_OFFSET) + $(VARS_LIVE_SIZE)
+DEFINE VARS_FTW_WORKING_SIZE = 0x00040000
+DEFINE VARS_FTW_SPARE_OFFSET = $(VARS_FTW_WORKING_OFFSET) + $(VARS_FTW_WORKING_SIZE)
+DEFINE VARS_FTW_SPARE_SIZE = 0x00040000
+
+#
+# Base Address where SEC phase will decompress and load
+# the PEI and DXE FVs
+#
+DEFINE MEMFD_BASE_ADDRESS = 0x80200000
+
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency = 10000000
diff --git a/OvmfPkg/Platforms/RiscVVirt/VarStore.fdf.inc b/OvmfPkg/Platforms/RiscVVirt/VarStore.fdf.inc
new file mode 100644
index 000000000000..30b170d77997
--- /dev/null
+++ b/OvmfPkg/Platforms/RiscVVirt/VarStore.fdf.inc
@@ -0,0 +1,79 @@
+## @file
+# FDF include file with Layout Regions that define an empty variable store.
+#
+# Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+$(VARS_OFFSET)|$(VARS_LIVE_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+#
+# NV_VARIABLE_STORE
+#
+DATA = {
+ ## This is the EFI_FIRMWARE_VOLUME_HEADER
+ # ZeroVector []
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # FileSystemGuid: gEfiSystemNvDataFvGuid =
+ # { 0xFFF12B8D, 0x7696, 0x4C8B,
+ # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+ 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+ 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+ # FvLength: 0x20000
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # Signature "_FVH" # Attributes
+ 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
+ # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision
+ 0x48, 0x00, 0x39, 0xF1, 0x00, 0x00, 0x00, 0x02,
+ # Blockmap[0]: 0x20 Blocks * 0x1000 Bytes / Block
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ # Blockmap[1]: End
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is the VARIABLE_STORE_HEADER
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ # Signature: gEfiAuthenticatedVariableGuid =
+ # { 0xaaf32c78, 0x947b, 0x439a,
+ # { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
+ 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
+ 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
+!else
+ # Signature: gEfiVariableGuid =
+ # { 0xddcf3616, 0x3275, 0x4164,
+ # { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
+ 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41,
+ 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d,
+!endif
+ # Size: 0x40000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
+ # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x3FFB8
+ # This can speed up the Variable Dispatch a bit.
+ 0xB8, 0xFF, 0x03, 0x00,
+ # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+ 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+$(VARS_FTW_WORKING_OFFSET)|$(VARS_FTW_WORKING_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+#
+#NV_FTW_WROK
+#
+DATA = {
+ # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid =
+ # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+ 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
+ 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95,
+ # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
+ 0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF,
+ # WriteQueueSize: UINT64
+ 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+$(VARS_FTW_SPARE_OFFSET)|$(VARS_FTW_SPARE_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+#
+#NV_FTW_SPARE
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 28/29] Maintainers.txt: Add entry for OvmfPkg/RiscVVirt
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (26 preceding siblings ...)
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 27/29] OvmfPkg: RiscVVirt: Add Qemu Virt platform support Sunil V L
@ 2022-10-10 10:12 ` Sunil V L
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 29/29] UefiCpuPkg/UefiCpuPkg.ci.yaml: Ignore RISC-V file Sunil V L
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:12 UTC (permalink / raw)
To: devel; +Cc: Andrew Fish, Leif Lindholm, Michael D Kinney
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
RiscVVirt is created to support EDK2 for RISC-V qemu
virt machine platform. Add maintainer entries.
Cc: Andrew Fish <afish@apple.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
Maintainers.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Maintainers.txt b/Maintainers.txt
index c641414109ad..ed8891b34606 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -527,6 +527,10 @@ F: OvmfPkg/XenResetVector/
R: Anthony Perard <anthony.perard@citrix.com> [sheep]
R: Julien Grall <julien@xen.org> [jgrall]
+OvmfPkg: RISC-V Qemu Virt Platform
+F: OvmfPkg/Platforms/RiscVVirt
+R: Sunil V L <sunilvl@ventanamicro.com> [vlsunil]
+
PcAtChipsetPkg
F: PcAtChipsetPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/PcAtChipsetPkg
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [edk2-staging/RiscV64QemuVirt PATCH 29/29] UefiCpuPkg/UefiCpuPkg.ci.yaml: Ignore RISC-V file
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
` (27 preceding siblings ...)
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 28/29] Maintainers.txt: Add entry for OvmfPkg/RiscVVirt Sunil V L
@ 2022-10-10 10:12 ` Sunil V L
28 siblings, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-10 10:12 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
RISC-V register names do not follow the EDK2 formatting.
So, add it to ignore list for now.
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
UefiCpuPkg/UefiCpuPkg.ci.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/UefiCpuPkg/UefiCpuPkg.ci.yaml b/UefiCpuPkg/UefiCpuPkg.ci.yaml
index bbdc44a45b34..ae963e94c8e6 100644
--- a/UefiCpuPkg/UefiCpuPkg.ci.yaml
+++ b/UefiCpuPkg/UefiCpuPkg.ci.yaml
@@ -19,6 +19,7 @@
],
## Both file path and directory path are accepted.
"IgnoreFiles": [
+ "Library/CpuExceptionHandlerLib/RiscV64/CpuExceptionHandlerLib.h"
]
},
"CompilerPlugin": {
--
2.25.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver Sunil V L
@ 2022-10-10 10:39 ` Ard Biesheuvel
2022-10-10 15:19 ` Sunil V L
0 siblings, 1 reply; 43+ messages in thread
From: Ard Biesheuvel @ 2022-10-10 10:39 UTC (permalink / raw)
To: Sunil V L; +Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
>
> RISC-V needs NorFlashDxe driver for qemu virt machine. The
> ArmPlatformPkg has this driver but migrating it to generic
> package like MdeModulePkg introduces circular dependencies.
> So, add a simplified version of the NorFlashDxe driver in
> OvmfPkg.
>
So what is the difference between this simplified version and the old
version? And it is backed in QEMU by the same NOR flash emulation,
shouldn't we use this driver for ArmVirtQemu as well?
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> ---
> OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf | 69 ++
> OvmfPkg/Drivers/NorFlashDxe/NorFlash.h | 422 ++++++++
> OvmfPkg/Drivers/NorFlashDxe/NorFlash.c | 972 ++++++++++++++++++
> .../Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | 123 +++
> OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c | 506 +++++++++
> OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c | 777 ++++++++++++++
> 6 files changed, 2869 insertions(+)
> create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
> create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
> create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
> create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
> create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
> create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
>
> diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
> new file mode 100644
> index 000000000000..e327b2ac7405
> --- /dev/null
> +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
> @@ -0,0 +1,69 @@
> +#/** @file
> +#
> +# Component description file for NorFlashDxe module
> +#
> +# Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#**/
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = QemuNorFlashDxe
> + FILE_GUID = D4F3B3FC-3AEF-4774-AC94-304438ABDA53
> + MODULE_TYPE = DXE_RUNTIME_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = NorFlashInitialise
> +
> +[Sources.common]
> + NorFlash.c
> + NorFlash.h
> + NorFlashDxe.c
> + NorFlashFvb.c
> + NorFlashBlockIoDxe.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + OvmfPkg/OvmfPkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> + IoLib
> + BaseLib
> + DebugLib
> + HobLib
> + NorFlashPlatformLib
> + UefiLib
> + UefiDriverEntryPoint
> + UefiBootServicesTableLib
> + UefiRuntimeLib
> + DxeServicesTableLib
> +
> +[Guids]
> + gEfiSystemNvDataFvGuid
> + gEfiVariableGuid
> + gEfiAuthenticatedVariableGuid
> + gEfiEventVirtualAddressChangeGuid
> + gEdkiiNvVarStoreFormattedGuid ## PRODUCES ## PROTOCOL
> +
> +[Protocols]
> + gEfiBlockIoProtocolGuid
> + gEfiDevicePathProtocolGuid
> + gEfiFirmwareVolumeBlockProtocolGuid
> + gEfiDiskIoProtocolGuid
> +
> +[Pcd.common]
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
> +
> +[Depex]
> + gEfiCpuArchProtocolGuid
> diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
> new file mode 100644
> index 000000000000..c83032e87d9c
> --- /dev/null
> +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
> @@ -0,0 +1,422 @@
> +/** @file NorFlash.h
> +
> + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef __NOR_FLASH_H__
> +#define __NOR_FLASH_H__
> +
> +#include <Base.h>
> +#include <PiDxe.h>
> +
> +#include <Guid/EventGroup.h>
> +
> +#include <Protocol/BlockIo.h>
> +#include <Protocol/DiskIo.h>
> +#include <Protocol/FirmwareVolumeBlock.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/NorFlashPlatformLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiRuntimeLib.h>
> +
> +#define NOR_FLASH_ERASE_RETRY 10
> +
> +// Device access macros
> +// These are necessary because we use 2 x 16bit parts to make up 32bit data
> +
> +#define HIGH_16_BITS 0xFFFF0000
> +#define LOW_16_BITS 0x0000FFFF
> +#define LOW_8_BITS 0x000000FF
> +
> +#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
> +
> +#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )
> +#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )
> +
> +// Each command must be sent simultaneously to both chips,
> +// i.e. at the lower 16 bits AND at the higher 16 bits
> +#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + ((OffsetAddr) << 2))
> +#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
> +#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))
> +#define GET_NOR_BLOCK_ADDRESS(BaseAddr, Lba, LbaSize) ( BaseAddr + (UINTN)((Lba) * LbaSize) )
> +
> +// Status Register Bits
> +#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)
> +#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)
> +#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)
> +#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)
> +#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)
> +#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)
> +#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)
> +#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)
> +
> +// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
> +
> +// On chip buffer size for buffered programming operations
> +// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
> +// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
> +#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)
> +#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
> +#define MAX_BUFFERED_PROG_ITERATIONS 10000000
> +#define BOUNDARY_OF_32_WORDS 0x7F
> +
> +// CFI Addresses
> +#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10
> +#define P30_CFI_ADDR_VENDOR_ID 0x13
> +
> +// CFI Data
> +#define CFI_QRY 0x00595251
> +
> +// READ Commands
> +#define P30_CMD_READ_DEVICE_ID 0x0090
> +#define P30_CMD_READ_STATUS_REGISTER 0x0070
> +#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050
> +#define P30_CMD_READ_ARRAY 0x00FF
> +#define P30_CMD_READ_CFI_QUERY 0x0098
> +
> +// WRITE Commands
> +#define P30_CMD_WORD_PROGRAM_SETUP 0x0040
> +#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010
> +#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8
> +#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0
> +#define P30_CMD_BEFP_SETUP 0x0080
> +#define P30_CMD_BEFP_CONFIRM 0x00D0
> +
> +// ERASE Commands
> +#define P30_CMD_BLOCK_ERASE_SETUP 0x0020
> +#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0
> +
> +// SUSPEND Commands
> +#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0
> +#define P30_CMD_SUSPEND_RESUME 0x00D0
> +
> +// BLOCK LOCKING / UNLOCKING Commands
> +#define P30_CMD_LOCK_BLOCK_SETUP 0x0060
> +#define P30_CMD_LOCK_BLOCK 0x0001
> +#define P30_CMD_UNLOCK_BLOCK 0x00D0
> +#define P30_CMD_LOCK_DOWN_BLOCK 0x002F
> +
> +// PROTECTION Commands
> +#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
> +
> +// CONFIGURATION Commands
> +#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
> +#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003
> +
> +#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
> +#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
> +#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
> +#define INSTANCE_FROM_DISKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, DiskIoProtocol, NOR_FLASH_SIGNATURE)
> +
> +typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
> +
> +#pragma pack (1)
> +typedef struct {
> + VENDOR_DEVICE_PATH Vendor;
> + UINT8 Index;
> + EFI_DEVICE_PATH_PROTOCOL End;
> +} NOR_FLASH_DEVICE_PATH;
> +#pragma pack ()
> +
> +struct _NOR_FLASH_INSTANCE {
> + UINT32 Signature;
> + EFI_HANDLE Handle;
> +
> + UINTN DeviceBaseAddress;
> + UINTN RegionBaseAddress;
> + UINTN Size;
> + EFI_LBA StartLba;
> +
> + EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
> + EFI_BLOCK_IO_MEDIA Media;
> + EFI_DISK_IO_PROTOCOL DiskIoProtocol;
> +
> + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
> + VOID *ShadowBuffer;
> +
> + NOR_FLASH_DEVICE_PATH DevicePath;
> +};
> +
> +EFI_STATUS
> +NorFlashReadCfiData (
> + IN UINTN DeviceBaseAddress,
> + IN UINTN CFI_Offset,
> + IN UINT32 NumberOfBytes,
> + OUT UINT32 *Data
> + );
> +
> +EFI_STATUS
> +NorFlashWriteBuffer (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN TargetAddress,
> + IN UINTN BufferSizeInBytes,
> + IN UINT32 *Buffer
> + );
> +
> +//
> +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashBlockIoReset (
> + IN EFI_BLOCK_IO_PROTOCOL *This,
> + IN BOOLEAN ExtendedVerification
> + );
> +
> +//
> +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashBlockIoReadBlocks (
> + IN EFI_BLOCK_IO_PROTOCOL *This,
> + IN UINT32 MediaId,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSizeInBytes,
> + OUT VOID *Buffer
> + );
> +
> +//
> +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashBlockIoWriteBlocks (
> + IN EFI_BLOCK_IO_PROTOCOL *This,
> + IN UINT32 MediaId,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSizeInBytes,
> + IN VOID *Buffer
> + );
> +
> +//
> +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashBlockIoFlushBlocks (
> + IN EFI_BLOCK_IO_PROTOCOL *This
> + );
> +
> +//
> +// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.ReadDisk
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashDiskIoReadDisk (
> + IN EFI_DISK_IO_PROTOCOL *This,
> + IN UINT32 MediaId,
> + IN UINT64 Offset,
> + IN UINTN BufferSize,
> + OUT VOID *Buffer
> + );
> +
> +//
> +// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.WriteDisk
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashDiskIoWriteDisk (
> + IN EFI_DISK_IO_PROTOCOL *This,
> + IN UINT32 MediaId,
> + IN UINT64 Offset,
> + IN UINTN BufferSize,
> + IN VOID *Buffer
> + );
> +
> +//
> +// NorFlashFvbDxe.c
> +//
> +
> +EFI_STATUS
> +EFIAPI
> +FvbGetAttributes (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + OUT EFI_FVB_ATTRIBUTES_2 *Attributes
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +FvbSetAttributes (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +FvbGetPhysicalAddress (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + OUT EFI_PHYSICAL_ADDRESS *Address
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +FvbGetBlockSize (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + IN EFI_LBA Lba,
> + OUT UINTN *BlockSize,
> + OUT UINTN *NumberOfBlocks
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +FvbRead (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN OUT UINTN *NumBytes,
> + IN OUT UINT8 *Buffer
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +FvbWrite (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN OUT UINTN *NumBytes,
> + IN UINT8 *Buffer
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +FvbEraseBlocks (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + ...
> + );
> +
> +EFI_STATUS
> +ValidateFvHeader (
> + IN NOR_FLASH_INSTANCE *Instance
> + );
> +
> +EFI_STATUS
> +InitializeFvAndVariableStoreHeaders (
> + IN NOR_FLASH_INSTANCE *Instance
> + );
> +
> +VOID
> +EFIAPI
> +FvbVirtualNotifyEvent (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + );
> +
> +//
> +// NorFlashDxe.c
> +//
> +
> +EFI_STATUS
> +NorFlashWriteFullBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINT32 *DataBuffer,
> + IN UINT32 BlockSizeInWords
> + );
> +
> +EFI_STATUS
> +NorFlashUnlockAndEraseSingleBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN BlockAddress
> + );
> +
> +EFI_STATUS
> +NorFlashCreateInstance (
> + IN UINTN NorFlashDeviceBase,
> + IN UINTN NorFlashRegionBase,
> + IN UINTN NorFlashSize,
> + IN UINT32 Index,
> + IN UINT32 BlockSize,
> + IN BOOLEAN SupportFvb,
> + OUT NOR_FLASH_INSTANCE **NorFlashInstance
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +NorFlashFvbInitialize (
> + IN NOR_FLASH_INSTANCE *Instance
> + );
> +
> +//
> +// NorFlash.c
> +//
> +EFI_STATUS
> +NorFlashWriteSingleBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN OUT UINTN *NumBytes,
> + IN UINT8 *Buffer
> + );
> +
> +EFI_STATUS
> +NorFlashWriteBlocks (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSizeInBytes,
> + IN VOID *Buffer
> + );
> +
> +EFI_STATUS
> +NorFlashReadBlocks (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSizeInBytes,
> + OUT VOID *Buffer
> + );
> +
> +EFI_STATUS
> +NorFlashRead (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN UINTN BufferSizeInBytes,
> + OUT VOID *Buffer
> + );
> +
> +EFI_STATUS
> +NorFlashWrite (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN OUT UINTN *NumBytes,
> + IN UINT8 *Buffer
> + );
> +
> +EFI_STATUS
> +NorFlashReset (
> + IN NOR_FLASH_INSTANCE *Instance
> + );
> +
> +EFI_STATUS
> +NorFlashEraseSingleBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN BlockAddress
> + );
> +
> +EFI_STATUS
> +NorFlashUnlockSingleBlockIfNecessary (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN BlockAddress
> + );
> +
> +EFI_STATUS
> +NorFlashWriteSingleWord (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN WordAddress,
> + IN UINT32 WriteData
> + );
> +
> +VOID
> +EFIAPI
> +NorFlashVirtualNotifyEvent (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + );
> +
> +#endif /* __NOR_FLASH_H__ */
> diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
> new file mode 100644
> index 000000000000..c2a6aa281578
> --- /dev/null
> +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
> @@ -0,0 +1,972 @@
> +/** @file NorFlash.c
> +
> + Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.<BR>
> + Copyright (c) 2020, Linaro, Ltd. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/BaseMemoryLib.h>
> +
> +#include "NorFlash.h"
> +
> +//
> +// Global variable declarations
> +//
> +extern NOR_FLASH_INSTANCE **mNorFlashInstances;
> +extern UINT32 mNorFlashDeviceCount;
> +
> +UINT32
> +NorFlashReadStatusRegister (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN SR_Address
> + )
> +{
> + // Prepare to read the status register
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);
> + return MmioRead32 (Instance->DeviceBaseAddress);
> +}
> +
> +STATIC
> +BOOLEAN
> +NorFlashBlockIsLocked (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN BlockAddress
> + )
> +{
> + UINT32 LockStatus;
> +
> + // Send command for reading device id
> + SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
> +
> + // Read block lock status
> + LockStatus = MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2));
> +
> + // Decode block lock status
> + LockStatus = FOLD_32BIT_INTO_16BIT (LockStatus);
> +
> + if ((LockStatus & 0x2) != 0) {
> + DEBUG ((DEBUG_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN\n"));
> + }
> +
> + return ((LockStatus & 0x1) != 0);
> +}
> +
> +STATIC
> +EFI_STATUS
> +NorFlashUnlockSingleBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN BlockAddress
> + )
> +{
> + UINT32 LockStatus;
> +
> + // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
> + // and to protect shared data structures.
> +
> + // Request a lock setup
> + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
> +
> + // Request an unlock
> + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
> +
> + // Wait until the status register gives us the all clear
> + do {
> + LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
> + } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
> +
> + // Put device back into Read Array mode
> + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY);
> +
> + DEBUG ((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x\n", BlockAddress));
> +
> + return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +NorFlashUnlockSingleBlockIfNecessary (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN BlockAddress
> + )
> +{
> + EFI_STATUS Status;
> +
> + Status = EFI_SUCCESS;
> +
> + if (NorFlashBlockIsLocked (Instance, BlockAddress)) {
> + Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + * The following function presumes that the block has already been unlocked.
> + **/
> +EFI_STATUS
> +NorFlashEraseSingleBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN BlockAddress
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 StatusRegister;
> +
> + Status = EFI_SUCCESS;
> +
> + // Request a block erase and then confirm it
> + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP);
> + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM);
> +
> + // Wait until the status register gives us the all clear
> + do {
> + StatusRegister = NorFlashReadStatusRegister (Instance, BlockAddress);
> + } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
> +
> + if (StatusRegister & P30_SR_BIT_VPP) {
> + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: VPP Range Error\n", BlockAddress));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) == (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) {
> + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Command Sequence Error\n", BlockAddress));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if (StatusRegister & P30_SR_BIT_ERASE) {
> + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Erase Error StatusRegister:0x%X\n", BlockAddress, StatusRegister));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
> + // The debug level message has been reduced because a device lock might happen. In this case we just retry it ...
> + DEBUG ((DEBUG_INFO, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error\n", BlockAddress));
> + Status = EFI_WRITE_PROTECTED;
> + }
> +
> + if (EFI_ERROR (Status)) {
> + // Clear the Status Register
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
> + }
> +
> + // Put device back into Read Array mode
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> +
> + return Status;
> +}
> +
> +EFI_STATUS
> +NorFlashWriteSingleWord (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN WordAddress,
> + IN UINT32 WriteData
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 StatusRegister;
> +
> + Status = EFI_SUCCESS;
> +
> + // Request a write single word command
> + SEND_NOR_COMMAND (WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP);
> +
> + // Store the word into NOR Flash;
> + MmioWrite32 (WordAddress, WriteData);
> +
> + // Wait for the write to complete and then check for any errors; i.e. check the Status Register
> + do {
> + // Prepare to read the status register
> + StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress);
> + // The chip is busy while the WRITE bit is not asserted
> + } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
> +
> + // Perform a full status check:
> + // Mask the relevant bits of Status Register.
> + // Everything should be zero, if not, we have a problem
> +
> + if (StatusRegister & P30_SR_BIT_VPP) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): VPP Range Error\n", WordAddress));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if (StatusRegister & P30_SR_BIT_PROGRAM) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Program Error\n", WordAddress));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Device Protect Error\n", WordAddress));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if (!EFI_ERROR (Status)) {
> + // Clear the Status Register
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
> + }
> +
> + // Put device back into Read Array mode
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> +
> + return Status;
> +}
> +
> +/*
> + * Writes data to the NOR Flash using the Buffered Programming method.
> + *
> + * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions.
> + * Therefore this function will only handle buffers up to 32 words or 128 bytes.
> + * To deal with larger buffers, call this function again.
> + *
> + * This function presumes that both the TargetAddress and the TargetAddress+BufferSize
> + * exist entirely within the NOR Flash. Therefore these conditions will not be checked here.
> + *
> + * In buffered programming, if the target address not at the beginning of a 32-bit word boundary,
> + * then programming time is doubled and power consumption is increased.
> + * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries.
> + * i.e. the last 4 bits of the target start address must be zero: 0x......00
> + */
> +EFI_STATUS
> +NorFlashWriteBuffer (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN TargetAddress,
> + IN UINTN BufferSizeInBytes,
> + IN UINT32 *Buffer
> + )
> +{
> + EFI_STATUS Status;
> + UINTN BufferSizeInWords;
> + UINTN Count;
> + volatile UINT32 *Data;
> + UINTN WaitForBuffer;
> + BOOLEAN BufferAvailable;
> + UINT32 StatusRegister;
> +
> + WaitForBuffer = MAX_BUFFERED_PROG_ITERATIONS;
> + BufferAvailable = FALSE;
> +
> + // Check that the target address does not cross a 32-word boundary.
> + if ((TargetAddress & BOUNDARY_OF_32_WORDS) != 0) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + // Check there are some data to program
> + if (BufferSizeInBytes == 0) {
> + return EFI_BUFFER_TOO_SMALL;
> + }
> +
> + // Check that the buffer size does not exceed the maximum hardware buffer size on chip.
> + if (BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES) {
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // Check that the buffer size is a multiple of 32-bit words
> + if ((BufferSizeInBytes % 4) != 0) {
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // Pre-programming conditions checked, now start the algorithm.
> +
> + // Prepare the data destination address
> + Data = (UINT32 *)TargetAddress;
> +
> + // Check the availability of the buffer
> + do {
> + // Issue the Buffered Program Setup command
> + SEND_NOR_COMMAND (TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP);
> +
> + // Read back the status register bit#7 from the same address
> + if (((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE) {
> + BufferAvailable = TRUE;
> + }
> +
> + // Update the loop counter
> + WaitForBuffer--;
> + } while ((WaitForBuffer > 0) && (BufferAvailable == FALSE));
> +
> + // The buffer was not available for writing
> + if (WaitForBuffer == 0) {
> + Status = EFI_DEVICE_ERROR;
> + goto EXIT;
> + }
> +
> + // From now on we work in 32-bit words
> + BufferSizeInWords = BufferSizeInBytes / (UINTN)4;
> +
> + // Write the word count, which is (buffer_size_in_words - 1),
> + // because word count 0 means one word.
> + SEND_NOR_COMMAND (TargetAddress, 0, (BufferSizeInWords - 1));
> +
> + // Write the data to the NOR Flash, advancing each address by 4 bytes
> + for (Count = 0; Count < BufferSizeInWords; Count++, Data++, Buffer++) {
> + MmioWrite32 ((UINTN)Data, *Buffer);
> + }
> +
> + // Issue the Buffered Program Confirm command, to start the programming operation
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM);
> +
> + // Wait for the write to complete and then check for any errors; i.e. check the Status Register
> + do {
> + StatusRegister = NorFlashReadStatusRegister (Instance, TargetAddress);
> + // The chip is busy while the WRITE bit is not asserted
> + } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
> +
> + // Perform a full status check:
> + // Mask the relevant bits of Status Register.
> + // Everything should be zero, if not, we have a problem
> +
> + Status = EFI_SUCCESS;
> +
> + if (StatusRegister & P30_SR_BIT_VPP) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): VPP Range Error\n", TargetAddress));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if (StatusRegister & P30_SR_BIT_PROGRAM) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Program Error\n", TargetAddress));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Device Protect Error\n", TargetAddress));
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> + if (!EFI_ERROR (Status)) {
> + // Clear the Status Register
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
> + }
> +
> +EXIT:
> + // Put device back into Read Array mode
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> +
> + return Status;
> +}
> +
> +EFI_STATUS
> +NorFlashWriteBlocks (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSizeInBytes,
> + IN VOID *Buffer
> + )
> +{
> + UINT32 *pWriteBuffer;
> + EFI_STATUS Status;
> + EFI_LBA CurrentBlock;
> + UINT32 BlockSizeInWords;
> + UINT32 NumBlocks;
> + UINT32 BlockCount;
> +
> + Status = EFI_SUCCESS;
> +
> + // The buffer must be valid
> + if (Buffer == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (Instance->Media.ReadOnly == TRUE) {
> + return EFI_WRITE_PROTECTED;
> + }
> +
> + // We must have some bytes to read
> + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes));
> + if (BufferSizeInBytes == 0) {
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // The size of the buffer must be a multiple of the block size
> + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize));
> + if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // All blocks must be within the device
> + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
> +
> + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba));
> +
> + if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + BlockSizeInWords = Instance->Media.BlockSize / 4;
> +
> + // Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer
> + // to a proper data type, so use *ReadBuffer
> + pWriteBuffer = (UINT32 *)Buffer;
> +
> + CurrentBlock = Lba;
> + for (BlockCount = 0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++, pWriteBuffer = pWriteBuffer + BlockSizeInWords) {
> + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock));
> +
> + Status = NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffer, BlockSizeInWords);
> +
> + if (EFI_ERROR (Status)) {
> + break;
> + }
> + }
> +
> + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status));
> + return Status;
> +}
> +
> +#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0)
> +
> +/**
> + Copy Length bytes from Source to Destination, using aligned accesses only.
> + Note that this implementation uses memcpy() semantics rather then memmove()
> + semantics, i.e., SourceBuffer and DestinationBuffer should not overlap.
> +
> + @param DestinationBuffer The target of the copy request.
> + @param SourceBuffer The place to copy from.
> + @param Length The number of bytes to copy.
> +
> + @return Destination
> +
> +**/
> +STATIC
> +VOID *
> +AlignedCopyMem (
> + OUT VOID *DestinationBuffer,
> + IN CONST VOID *SourceBuffer,
> + IN UINTN Length
> + )
> +{
> + UINT8 *Destination8;
> + CONST UINT8 *Source8;
> + UINT32 *Destination32;
> + CONST UINT32 *Source32;
> + UINT64 *Destination64;
> + CONST UINT64 *Source64;
> +
> + if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 8) && (Length >= 8)) {
> + Destination64 = DestinationBuffer;
> + Source64 = SourceBuffer;
> + while (Length >= 8) {
> + *Destination64++ = *Source64++;
> + Length -= 8;
> + }
> +
> + Destination8 = (UINT8 *)Destination64;
> + Source8 = (CONST UINT8 *)Source64;
> + } else if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 4) && (Length >= 4)) {
> + Destination32 = DestinationBuffer;
> + Source32 = SourceBuffer;
> + while (Length >= 4) {
> + *Destination32++ = *Source32++;
> + Length -= 4;
> + }
> +
> + Destination8 = (UINT8 *)Destination32;
> + Source8 = (CONST UINT8 *)Source32;
> + } else {
> + Destination8 = DestinationBuffer;
> + Source8 = SourceBuffer;
> + }
> +
> + while (Length-- != 0) {
> + *Destination8++ = *Source8++;
> + }
> +
> + return DestinationBuffer;
> +}
> +
> +EFI_STATUS
> +NorFlashReadBlocks (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSizeInBytes,
> + OUT VOID *Buffer
> + )
> +{
> + UINT32 NumBlocks;
> + UINTN StartAddress;
> +
> + DEBUG ((
> + DEBUG_BLKIO,
> + "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
> + BufferSizeInBytes,
> + Instance->Media.BlockSize,
> + Instance->Media.LastBlock,
> + Lba
> + ));
> +
> + // The buffer must be valid
> + if (Buffer == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + // Return if we have not any byte to read
> + if (BufferSizeInBytes == 0) {
> + return EFI_SUCCESS;
> + }
> +
> + // The size of the buffer must be a multiple of the block size
> + if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // All blocks must be within the device
> + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
> +
> + if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
> + DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + // Get the address to start reading from
> + StartAddress = GET_NOR_BLOCK_ADDRESS (
> + Instance->RegionBaseAddress,
> + Lba,
> + Instance->Media.BlockSize
> + );
> +
> + // Put the device into Read Array mode
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> +
> + // Readout the data
> + AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
> +
> + return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +NorFlashRead (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN UINTN BufferSizeInBytes,
> + OUT VOID *Buffer
> + )
> +{
> + UINTN StartAddress;
> +
> + // The buffer must be valid
> + if (Buffer == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + // Return if we have not any byte to read
> + if (BufferSizeInBytes == 0) {
> + return EFI_SUCCESS;
> + }
> +
> + if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
> + DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + // Get the address to start reading from
> + StartAddress = GET_NOR_BLOCK_ADDRESS (
> + Instance->RegionBaseAddress,
> + Lba,
> + Instance->Media.BlockSize
> + );
> +
> + // Put the device into Read Array mode
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> +
> + // Readout the data
> + AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/*
> + Write a full or portion of a block. It must not span block boundaries; that is,
> + Offset + *NumBytes <= Instance->Media.BlockSize.
> +*/
> +EFI_STATUS
> +NorFlashWriteSingleBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN OUT UINTN *NumBytes,
> + IN UINT8 *Buffer
> + )
> +{
> + EFI_STATUS TempStatus;
> + UINT32 Tmp;
> + UINT32 TmpBuf;
> + UINT32 WordToWrite;
> + UINT32 Mask;
> + BOOLEAN DoErase;
> + UINTN BytesToWrite;
> + UINTN CurOffset;
> + UINTN WordAddr;
> + UINTN BlockSize;
> + UINTN BlockAddress;
> + UINTN PrevBlockAddress;
> +
> + PrevBlockAddress = 0;
> +
> + DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
> +
> + // Detect WriteDisabled state
> + if (Instance->Media.ReadOnly == TRUE) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not write: Device is in WriteDisabled state.\n"));
> + // It is in WriteDisabled state, return an error right away
> + return EFI_ACCESS_DENIED;
> + }
> +
> + // Cache the block size to avoid de-referencing pointers all the time
> + BlockSize = Instance->Media.BlockSize;
> +
> + // The write must not span block boundaries.
> + // We need to check each variable individually because adding two large values together overflows.
> + if ((Offset >= BlockSize) ||
> + (*NumBytes > BlockSize) ||
> + ((Offset + *NumBytes) > BlockSize))
> + {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // We must have some bytes to write
> + if (*NumBytes == 0) {
> + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // Pick 128bytes as a good start for word operations as opposed to erasing the
> + // block and writing the data regardless if an erase is really needed.
> + // It looks like most individual NV variable writes are smaller than 128bytes.
> + if (*NumBytes <= 128) {
> + // Check to see if we need to erase before programming the data into NOR.
> + // If the destination bits are only changing from 1s to 0s we can just write.
> + // After a block is erased all bits in the block is set to 1.
> + // If any byte requires us to erase we just give up and rewrite all of it.
> + DoErase = FALSE;
> + BytesToWrite = *NumBytes;
> + CurOffset = Offset;
> +
> + while (BytesToWrite > 0) {
> + // Read full word from NOR, splice as required. A word is the smallest
> + // unit we can write.
> + TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof (Tmp), &Tmp);
> + if (EFI_ERROR (TempStatus)) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + // Physical address of word in NOR to write.
> + WordAddr = (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS (
> + Instance->RegionBaseAddress,
> + Lba,
> + BlockSize
> + );
> + // The word of data that is to be written.
> + TmpBuf = *((UINT32 *)(Buffer + (*NumBytes - BytesToWrite)));
> +
> + // First do word aligned chunks.
> + if ((CurOffset & 0x3) == 0) {
> + if (BytesToWrite >= 4) {
> + // Is the destination still in 'erased' state?
> + if (~Tmp != 0) {
> + // Check to see if we are only changing bits to zero.
> + if ((Tmp ^ TmpBuf) & TmpBuf) {
> + DoErase = TRUE;
> + break;
> + }
> + }
> +
> + // Write this word to NOR
> + WordToWrite = TmpBuf;
> + CurOffset += sizeof (TmpBuf);
> + BytesToWrite -= sizeof (TmpBuf);
> + } else {
> + // BytesToWrite < 4. Do small writes and left-overs
> + Mask = ~((~0) << (BytesToWrite * 8));
> + // Mask out the bytes we want.
> + TmpBuf &= Mask;
> + // Is the destination still in 'erased' state?
> + if ((Tmp & Mask) != Mask) {
> + // Check to see if we are only changing bits to zero.
> + if ((Tmp ^ TmpBuf) & TmpBuf) {
> + DoErase = TRUE;
> + break;
> + }
> + }
> +
> + // Merge old and new data. Write merged word to NOR
> + WordToWrite = (Tmp & ~Mask) | TmpBuf;
> + CurOffset += BytesToWrite;
> + BytesToWrite = 0;
> + }
> + } else {
> + // Do multiple words, but starting unaligned.
> + if (BytesToWrite > (4 - (CurOffset & 0x3))) {
> + Mask = ((~0) << ((CurOffset & 0x3) * 8));
> + // Mask out the bytes we want.
> + TmpBuf &= Mask;
> + // Is the destination still in 'erased' state?
> + if ((Tmp & Mask) != Mask) {
> + // Check to see if we are only changing bits to zero.
> + if ((Tmp ^ TmpBuf) & TmpBuf) {
> + DoErase = TRUE;
> + break;
> + }
> + }
> +
> + // Merge old and new data. Write merged word to NOR
> + WordToWrite = (Tmp & ~Mask) | TmpBuf;
> + BytesToWrite -= (4 - (CurOffset & 0x3));
> + CurOffset += (4 - (CurOffset & 0x3));
> + } else {
> + // Unaligned and fits in one word.
> + Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8);
> + // Mask out the bytes we want.
> + TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;
> + // Is the destination still in 'erased' state?
> + if ((Tmp & Mask) != Mask) {
> + // Check to see if we are only changing bits to zero.
> + if ((Tmp ^ TmpBuf) & TmpBuf) {
> + DoErase = TRUE;
> + break;
> + }
> + }
> +
> + // Merge old and new data. Write merged word to NOR
> + WordToWrite = (Tmp & ~Mask) | TmpBuf;
> + CurOffset += BytesToWrite;
> + BytesToWrite = 0;
> + }
> + }
> +
> + //
> + // Write the word to NOR.
> + //
> +
> + BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
> + if (BlockAddress != PrevBlockAddress) {
> + TempStatus = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
> + if (EFI_ERROR (TempStatus)) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + PrevBlockAddress = BlockAddress;
> + }
> +
> + TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
> + if (EFI_ERROR (TempStatus)) {
> + return EFI_DEVICE_ERROR;
> + }
> + }
> +
> + // Exit if we got here and could write all the data. Otherwise do the
> + // Erase-Write cycle.
> + if (!DoErase) {
> + return EFI_SUCCESS;
> + }
> + }
> +
> + // Check we did get some memory. Buffer is BlockSize.
> + if (Instance->ShadowBuffer == NULL) {
> + DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
> + return EFI_DEVICE_ERROR;
> + }
> +
> + // Read NOR Flash data into shadow buffer
> + TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
> + if (EFI_ERROR (TempStatus)) {
> + // Return one of the pre-approved error statuses
> + return EFI_DEVICE_ERROR;
> + }
> +
> + // Put the data at the appropriate location inside the buffer area
> + CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
> +
> + // Write the modified buffer back to the NorFlash
> + TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
> + if (EFI_ERROR (TempStatus)) {
> + // Return one of the pre-approved error statuses
> + return EFI_DEVICE_ERROR;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/*
> + Although DiskIoDxe will automatically install the DiskIO protocol whenever
> + we install the BlockIO protocol, its implementation is sub-optimal as it reads
> + and writes entire blocks using the BlockIO protocol. In fact we can access
> + NOR flash with a finer granularity than that, so we can improve performance
> + by directly producing the DiskIO protocol.
> +*/
> +
> +/**
> + Read BufferSize bytes from Offset into Buffer.
> +
> + @param This Protocol instance pointer.
> + @param MediaId Id of the media, changes every time the media is replaced.
> + @param Offset The starting byte offset to read from
> + @param BufferSize Size of Buffer
> + @param Buffer Buffer containing read data
> +
> + @retval EFI_SUCCESS The data was read correctly from the device.
> + @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
> + @retval EFI_NO_MEDIA There is no media in the device.
> + @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
> + @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
> + valid for the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NorFlashDiskIoReadDisk (
> + IN EFI_DISK_IO_PROTOCOL *This,
> + IN UINT32 MediaId,
> + IN UINT64 DiskOffset,
> + IN UINTN BufferSize,
> + OUT VOID *Buffer
> + )
> +{
> + NOR_FLASH_INSTANCE *Instance;
> + UINT32 BlockSize;
> + UINT32 BlockOffset;
> + EFI_LBA Lba;
> +
> + Instance = INSTANCE_FROM_DISKIO_THIS (This);
> +
> + if (MediaId != Instance->Media.MediaId) {
> + return EFI_MEDIA_CHANGED;
> + }
> +
> + BlockSize = Instance->Media.BlockSize;
> + Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
> +
> + return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer);
> +}
> +
> +/**
> + Writes a specified number of bytes to a device.
> +
> + @param This Indicates a pointer to the calling context.
> + @param MediaId ID of the medium to be written.
> + @param Offset The starting byte offset on the logical block I/O device to write.
> + @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
> + @param Buffer A pointer to the buffer containing the data to be written.
> +
> + @retval EFI_SUCCESS The data was written correctly to the device.
> + @retval EFI_WRITE_PROTECTED The device can not be written to.
> + @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
> + @retval EFI_NO_MEDIA There is no media in the device.
> + @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
> + @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
> + valid for the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NorFlashDiskIoWriteDisk (
> + IN EFI_DISK_IO_PROTOCOL *This,
> + IN UINT32 MediaId,
> + IN UINT64 DiskOffset,
> + IN UINTN BufferSize,
> + IN VOID *Buffer
> + )
> +{
> + NOR_FLASH_INSTANCE *Instance;
> + UINT32 BlockSize;
> + UINT32 BlockOffset;
> + EFI_LBA Lba;
> + UINTN RemainingBytes;
> + UINTN WriteSize;
> + EFI_STATUS Status;
> +
> + Instance = INSTANCE_FROM_DISKIO_THIS (This);
> +
> + if (MediaId != Instance->Media.MediaId) {
> + return EFI_MEDIA_CHANGED;
> + }
> +
> + BlockSize = Instance->Media.BlockSize;
> + Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
> +
> + RemainingBytes = BufferSize;
> +
> + // Write either all the remaining bytes, or the number of bytes that bring
> + // us up to a block boundary, whichever is less.
> + // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next
> + // block boundary (even if it is already on one).
> + WriteSize = MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) - DiskOffset);
> +
> + do {
> + if (WriteSize == BlockSize) {
> + // Write a full block
> + Status = NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize / sizeof (UINT32));
> + } else {
> + // Write a partial block
> + Status = NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &WriteSize, Buffer);
> + }
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + // Now continue writing either all the remaining bytes or single blocks.
> + RemainingBytes -= WriteSize;
> + Buffer = (UINT8 *)Buffer + WriteSize;
> + Lba++;
> + BlockOffset = 0;
> + WriteSize = MIN (RemainingBytes, BlockSize);
> + } while (RemainingBytes);
> +
> + return Status;
> +}
> +
> +EFI_STATUS
> +NorFlashReset (
> + IN NOR_FLASH_INSTANCE *Instance
> + )
> +{
> + // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
> + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Fixup internal data so that EFI can be call in virtual mode.
> + Call the passed in Child Notify event and convert any pointers in
> + lib to virtual mode.
> +
> + @param[in] Event The Event that is being processed
> + @param[in] Context Event Context
> +**/
> +VOID
> +EFIAPI
> +NorFlashVirtualNotifyEvent (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + )
> +{
> + UINTN Index;
> +
> + for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress);
> +
> + // Convert BlockIo protocol
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
> +
> + // Convert Fvb
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Read);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Write);
> +
> + if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
> + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowBuffer);
> + }
> + }
> +
> + return;
> +}
> diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
> new file mode 100644
> index 000000000000..9d4732c6905a
> --- /dev/null
> +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
> @@ -0,0 +1,123 @@
> +/** @file NorFlashBlockIoDxe.c
> +
> + Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include "NorFlash.h"
> +
> +//
> +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashBlockIoReset (
> + IN EFI_BLOCK_IO_PROTOCOL *This,
> + IN BOOLEAN ExtendedVerification
> + )
> +{
> + NOR_FLASH_INSTANCE *Instance;
> +
> + Instance = INSTANCE_FROM_BLKIO_THIS (This);
> +
> + DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
> +
> + return NorFlashReset (Instance);
> +}
> +
> +//
> +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashBlockIoReadBlocks (
> + IN EFI_BLOCK_IO_PROTOCOL *This,
> + IN UINT32 MediaId,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSizeInBytes,
> + OUT VOID *Buffer
> + )
> +{
> + NOR_FLASH_INSTANCE *Instance;
> + EFI_STATUS Status;
> + EFI_BLOCK_IO_MEDIA *Media;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Instance = INSTANCE_FROM_BLKIO_THIS (This);
> + Media = This->Media;
> +
> + DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, BufferSizeInBytes, Buffer));
> +
> + if (!Media) {
> + Status = EFI_INVALID_PARAMETER;
> + } else if (!Media->MediaPresent) {
> + Status = EFI_NO_MEDIA;
> + } else if (Media->MediaId != MediaId) {
> + Status = EFI_MEDIA_CHANGED;
> + } else if ((Media->IoAlign > 2) && (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) {
> + Status = EFI_INVALID_PARAMETER;
> + } else {
> + Status = NorFlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
> + }
> +
> + return Status;
> +}
> +
> +//
> +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashBlockIoWriteBlocks (
> + IN EFI_BLOCK_IO_PROTOCOL *This,
> + IN UINT32 MediaId,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSizeInBytes,
> + IN VOID *Buffer
> + )
> +{
> + NOR_FLASH_INSTANCE *Instance;
> + EFI_STATUS Status;
> +
> + Instance = INSTANCE_FROM_BLKIO_THIS (This);
> +
> + DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes, BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
> +
> + if ( !This->Media->MediaPresent ) {
> + Status = EFI_NO_MEDIA;
> + } else if ( This->Media->MediaId != MediaId ) {
> + Status = EFI_MEDIA_CHANGED;
> + } else if ( This->Media->ReadOnly ) {
> + Status = EFI_WRITE_PROTECTED;
> + } else {
> + Status = NorFlashWriteBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
> + }
> +
> + return Status;
> +}
> +
> +//
> +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
> +//
> +EFI_STATUS
> +EFIAPI
> +NorFlashBlockIoFlushBlocks (
> + IN EFI_BLOCK_IO_PROTOCOL *This
> + )
> +{
> + // No Flush required for the NOR Flash driver
> + // because cache operations are not permitted.
> +
> + DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
> +
> + // Nothing to do so just return without error
> + return EFI_SUCCESS;
> +}
> diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
> new file mode 100644
> index 000000000000..f7b92de21a57
> --- /dev/null
> +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
> @@ -0,0 +1,506 @@
> +/** @file NorFlashDxe.c
> +
> + Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/UefiLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +
> +#include "NorFlash.h"
> +
> +STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
> +
> +//
> +// Global variable declarations
> +//
> +NOR_FLASH_INSTANCE **mNorFlashInstances;
> +UINT32 mNorFlashDeviceCount;
> +UINTN mFlashNvStorageVariableBase;
> +EFI_EVENT mFvbVirtualAddrChangeEvent;
> +
> +NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
> + NOR_FLASH_SIGNATURE, // Signature
> + NULL, // Handle ... NEED TO BE FILLED
> +
> + 0, // DeviceBaseAddress ... NEED TO BE FILLED
> + 0, // RegionBaseAddress ... NEED TO BE FILLED
> + 0, // Size ... NEED TO BE FILLED
> + 0, // StartLba
> +
> + {
> + EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision
> + NULL, // Media ... NEED TO BE FILLED
> + NorFlashBlockIoReset, // Reset;
> + NorFlashBlockIoReadBlocks, // ReadBlocks
> + NorFlashBlockIoWriteBlocks, // WriteBlocks
> + NorFlashBlockIoFlushBlocks // FlushBlocks
> + }, // BlockIoProtocol
> +
> + {
> + 0, // MediaId ... NEED TO BE FILLED
> + FALSE, // RemovableMedia
> + TRUE, // MediaPresent
> + FALSE, // LogicalPartition
> + FALSE, // ReadOnly
> + FALSE, // WriteCaching;
> + 0, // BlockSize ... NEED TO BE FILLED
> + 4, // IoAlign
> + 0, // LastBlock ... NEED TO BE FILLED
> + 0, // LowestAlignedLba
> + 1, // LogicalBlocksPerPhysicalBlock
> + }, // Media;
> +
> + {
> + EFI_DISK_IO_PROTOCOL_REVISION, // Revision
> + NorFlashDiskIoReadDisk, // ReadDisk
> + NorFlashDiskIoWriteDisk // WriteDisk
> + },
> +
> + {
> + FvbGetAttributes, // GetAttributes
> + FvbSetAttributes, // SetAttributes
> + FvbGetPhysicalAddress, // GetPhysicalAddress
> + FvbGetBlockSize, // GetBlockSize
> + FvbRead, // Read
> + FvbWrite, // Write
> + FvbEraseBlocks, // EraseBlocks
> + NULL, // ParentHandle
> + }, // FvbProtoccol;
> + NULL, // ShadowBuffer
> + {
> + {
> + {
> + HARDWARE_DEVICE_PATH,
> + HW_VENDOR_DP,
> + {
> + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),
> + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)
> + }
> + },
> + { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
> + }, // GUID ... NEED TO BE FILLED
> + },
> + 0, // Index
> + {
> + END_DEVICE_PATH_TYPE,
> + END_ENTIRE_DEVICE_PATH_SUBTYPE,
> + { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
> + }
> + } // DevicePath
> +};
> +
> +EFI_STATUS
> +NorFlashCreateInstance (
> + IN UINTN NorFlashDeviceBase,
> + IN UINTN NorFlashRegionBase,
> + IN UINTN NorFlashSize,
> + IN UINT32 Index,
> + IN UINT32 BlockSize,
> + IN BOOLEAN SupportFvb,
> + OUT NOR_FLASH_INSTANCE **NorFlashInstance
> + )
> +{
> + EFI_STATUS Status;
> + NOR_FLASH_INSTANCE *Instance;
> +
> + ASSERT (NorFlashInstance != NULL);
> +
> + Instance = AllocateRuntimeCopyPool (sizeof (NOR_FLASH_INSTANCE), &mNorFlashInstanceTemplate);
> + if (Instance == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Instance->DeviceBaseAddress = NorFlashDeviceBase;
> + Instance->RegionBaseAddress = NorFlashRegionBase;
> + Instance->Size = NorFlashSize;
> +
> + Instance->BlockIoProtocol.Media = &Instance->Media;
> + Instance->Media.MediaId = Index;
> + Instance->Media.BlockSize = BlockSize;
> + Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
> +
> + CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
> + Instance->DevicePath.Index = (UINT8)Index;
> +
> + Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);
> + if (Instance->ShadowBuffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + if (SupportFvb) {
> + NorFlashFvbInitialize (Instance);
> +
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + &Instance->Handle,
> + &gEfiDevicePathProtocolGuid,
> + &Instance->DevicePath,
> + &gEfiBlockIoProtocolGuid,
> + &Instance->BlockIoProtocol,
> + &gEfiFirmwareVolumeBlockProtocolGuid,
> + &Instance->FvbProtocol,
> + NULL
> + );
> + if (EFI_ERROR (Status)) {
> + FreePool (Instance);
> + return Status;
> + }
> + } else {
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + &Instance->Handle,
> + &gEfiDevicePathProtocolGuid,
> + &Instance->DevicePath,
> + &gEfiBlockIoProtocolGuid,
> + &Instance->BlockIoProtocol,
> + &gEfiDiskIoProtocolGuid,
> + &Instance->DiskIoProtocol,
> + NULL
> + );
> + if (EFI_ERROR (Status)) {
> + FreePool (Instance);
> + return Status;
> + }
> + }
> +
> + *NorFlashInstance = Instance;
> + return Status;
> +}
> +
> +/**
> + * This function unlock and erase an entire NOR Flash block.
> + **/
> +EFI_STATUS
> +NorFlashUnlockAndEraseSingleBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN UINTN BlockAddress
> + )
> +{
> + EFI_STATUS Status;
> + UINTN Index;
> + EFI_TPL OriginalTPL;
> +
> + if (!EfiAtRuntime ()) {
> + // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
> + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> + } else {
> + // This initialization is only to prevent the compiler to complain about the
> + // use of uninitialized variables
> + OriginalTPL = TPL_HIGH_LEVEL;
> + }
> +
> + Index = 0;
> + // The block erase might fail a first time (SW bug ?). Retry it ...
> + do {
> + // Unlock the block if we have to
> + Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
> + if (EFI_ERROR (Status)) {
> + break;
> + }
> +
> + Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
> + Index++;
> + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
> +
> + if (Index == NOR_FLASH_ERASE_RETRY) {
> + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));
> + }
> +
> + if (!EfiAtRuntime ()) {
> + // Interruptions can resume.
> + gBS->RestoreTPL (OriginalTPL);
> + }
> +
> + return Status;
> +}
> +
> +EFI_STATUS
> +NorFlashWriteFullBlock (
> + IN NOR_FLASH_INSTANCE *Instance,
> + IN EFI_LBA Lba,
> + IN UINT32 *DataBuffer,
> + IN UINT32 BlockSizeInWords
> + )
> +{
> + EFI_STATUS Status;
> + UINTN WordAddress;
> + UINT32 WordIndex;
> + UINTN BufferIndex;
> + UINTN BlockAddress;
> + UINTN BuffersInBlock;
> + UINTN RemainingWords;
> + EFI_TPL OriginalTPL;
> + UINTN Cnt;
> +
> + Status = EFI_SUCCESS;
> +
> + // Get the physical address of the block
> + BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4);
> +
> + // Start writing from the first address at the start of the block
> + WordAddress = BlockAddress;
> +
> + if (!EfiAtRuntime ()) {
> + // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
> + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> + } else {
> + // This initialization is only to prevent the compiler to complain about the
> + // use of uninitialized variables
> + OriginalTPL = TPL_HIGH_LEVEL;
> + }
> +
> + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
> + goto EXIT;
> + }
> +
> + // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
> +
> + // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero
> + if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) {
> + // First, break the entire block into buffer-sized chunks.
> + BuffersInBlock = (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;
> +
> + // Then feed each buffer chunk to the NOR Flash
> + // If a buffer does not contain any data, don't write it.
> + for (BufferIndex = 0;
> + BufferIndex < BuffersInBlock;
> + BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
> + )
> + {
> + // Check the buffer to see if it contains any data (not set all 1s).
> + for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {
> + if (~DataBuffer[Cnt] != 0 ) {
> + // Some data found, write the buffer.
> + Status = NorFlashWriteBuffer (
> + Instance,
> + WordAddress,
> + P30_MAX_BUFFER_SIZE_IN_BYTES,
> + DataBuffer
> + );
> + if (EFI_ERROR (Status)) {
> + goto EXIT;
> + }
> +
> + break;
> + }
> + }
> + }
> +
> + // Finally, finish off any remaining words that are less than the maximum size of the buffer
> + RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
> +
> + if (RemainingWords != 0) {
> + Status = NorFlashWriteBuffer (Instance, WordAddress, (RemainingWords * 4), DataBuffer);
> + if (EFI_ERROR (Status)) {
> + goto EXIT;
> + }
> + }
> + } else {
> + // For now, use the single word programming algorithm
> + // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,
> + // i.e. which ends in the range 0x......01 - 0x......7F.
> + for (WordIndex = 0; WordIndex < BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4) {
> + Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);
> + if (EFI_ERROR (Status)) {
> + goto EXIT;
> + }
> + }
> + }
> +
> +EXIT:
> + if (!EfiAtRuntime ()) {
> + // Interruptions can resume.
> + gBS->RestoreTPL (OriginalTPL);
> + }
> +
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
> + }
> +
> + return Status;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +NorFlashInitialise (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 Index;
> + NOR_FLASH_DESCRIPTION *NorFlashDevices;
> + BOOLEAN ContainVariableStorage;
> +
> + Status = NorFlashPlatformInitialization ();
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to initialize Nor Flash devices\n"));
> + return Status;
> + }
> +
> + Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to get Nor Flash devices\n"));
> + return Status;
> + }
> +
> + mNorFlashInstances = AllocateRuntimePool (sizeof (NOR_FLASH_INSTANCE *) * mNorFlashDeviceCount);
> +
> + for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
> + // Check if this NOR Flash device contain the variable storage region
> +
> + if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
> + ContainVariableStorage =
> + (NorFlashDevices[Index].RegionBaseAddress <= PcdGet64 (PcdFlashNvStorageVariableBase64)) &&
> + (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvStorageVariableSize) <=
> + NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
> + } else {
> + ContainVariableStorage =
> + (NorFlashDevices[Index].RegionBaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) &&
> + (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize) <=
> + NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
> + }
> +
> + Status = NorFlashCreateInstance (
> + NorFlashDevices[Index].DeviceBaseAddress,
> + NorFlashDevices[Index].RegionBaseAddress,
> + NorFlashDevices[Index].Size,
> + Index,
> + NorFlashDevices[Index].BlockSize,
> + ContainVariableStorage,
> + &mNorFlashInstances[Index]
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n", Index));
> + }
> + }
> +
> + //
> + // Register for the virtual address change event
> + //
> + Status = gBS->CreateEventEx (
> + EVT_NOTIFY_SIGNAL,
> + TPL_NOTIFY,
> + NorFlashVirtualNotifyEvent,
> + NULL,
> + &gEfiEventVirtualAddressChangeGuid,
> + &mNorFlashVirtualAddrChangeEvent
> + );
> + ASSERT_EFI_ERROR (Status);
> +
> + return Status;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +NorFlashFvbInitialize (
> + IN NOR_FLASH_INSTANCE *Instance
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 FvbNumLba;
> + EFI_BOOT_MODE BootMode;
> + UINTN RuntimeMmioRegionSize;
> +
> + DEBUG ((DEBUG_BLKIO, "NorFlashFvbInitialize\n"));
> + ASSERT ((Instance != NULL));
> +
> + //
> + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
> + //
> +
> + // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;
> + // even if we only use the small block region at the top of the NOR Flash.
> + // The reason is when the NOR Flash memory is set into program mode, the command
> + // is written as the base of the flash region (ie: Instance->DeviceBaseAddress)
> + RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
> +
> + Status = gDS->AddMemorySpace (
> + EfiGcdMemoryTypeMemoryMappedIo,
> + Instance->DeviceBaseAddress,
> + RuntimeMmioRegionSize,
> + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
> + );
> + ASSERT_EFI_ERROR (Status);
> +
> + Status = gDS->SetMemorySpaceAttributes (
> + Instance->DeviceBaseAddress,
> + RuntimeMmioRegionSize,
> + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
> + );
> + ASSERT_EFI_ERROR (Status);
> +
> + mFlashNvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
> + PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);
> +
> + // Set the index of the first LBA for the FVB
> + Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->Media.BlockSize;
> +
> + BootMode = GetBootModeHob ();
> + if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
> + Status = EFI_INVALID_PARAMETER;
> + } else {
> + // Determine if there is a valid header at the beginning of the NorFlash
> + Status = ValidateFvHeader (Instance);
> + }
> +
> + // Install the Default FVB header if required
> + if (EFI_ERROR (Status)) {
> + // There is no valid header, so time to install one.
> + DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: Installing a correct one for this volume.\n",
> + __FUNCTION__
> + ));
> +
> + // Erase all the NorFlash that is reserved for variable storage
> + FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
> +
> + Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + // Install all appropriate headers
> + Status = InitializeFvAndVariableStoreHeaders (Instance);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + //
> + // The driver implementing the variable read service can now be dispatched;
> + // the varstore headers are in place.
> + //
> + Status = gBS->InstallProtocolInterface (
> + &gImageHandle,
> + &gEdkiiNvVarStoreFormattedGuid,
> + EFI_NATIVE_INTERFACE,
> + NULL
> + );
> + ASSERT_EFI_ERROR (Status);
> +
> + //
> + // Register for the virtual address change event
> + //
> + Status = gBS->CreateEventEx (
> + EVT_NOTIFY_SIGNAL,
> + TPL_NOTIFY,
> + FvbVirtualNotifyEvent,
> + NULL,
> + &gEfiEventVirtualAddressChangeGuid,
> + &mFvbVirtualAddrChangeEvent
> + );
> + ASSERT_EFI_ERROR (Status);
> +
> + return Status;
> +}
> diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
> new file mode 100644
> index 000000000000..0767581308d2
> --- /dev/null
> +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
> @@ -0,0 +1,777 @@
> +/*++ @file NorFlashFvbDxe.c
> +
> + Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> + --*/
> +
> +#include <PiDxe.h>
> +
> +#include <Library/PcdLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +
> +#include <Guid/VariableFormat.h>
> +#include <Guid/SystemNvDataGuid.h>
> +#include <Guid/NvVarStoreFormatted.h>
> +
> +#include "NorFlash.h"
> +
> +extern UINTN mFlashNvStorageVariableBase;
> +///
> +/// The Firmware Volume Block Protocol is the low-level interface
> +/// to a firmware volume. File-level access to a firmware volume
> +/// should not be done using the Firmware Volume Block Protocol.
> +/// Normal access to a firmware volume must use the Firmware
> +/// Volume Protocol. Typically, only the file system driver that
> +/// produces the Firmware Volume Protocol will bind to the
> +/// Firmware Volume Block Protocol.
> +///
> +
> +/**
> + Initialises the FV Header and Variable Store Header
> + to support variable operations.
> +
> + @param[in] Ptr - Location to initialise the headers
> +
> +**/
> +EFI_STATUS
> +InitializeFvAndVariableStoreHeaders (
> + IN NOR_FLASH_INSTANCE *Instance
> + )
> +{
> + EFI_STATUS Status;
> + VOID *Headers;
> + UINTN HeadersLength;
> + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
> + VARIABLE_STORE_HEADER *VariableStoreHeader;
> + UINT32 NvStorageFtwSpareSize;
> + UINT32 NvStorageFtwWorkingSize;
> + UINT32 NvStorageVariableSize;
> + UINT64 NvStorageFtwSpareBase;
> + UINT64 NvStorageFtwWorkingBase;
> + UINT64 NvStorageVariableBase;
> +
> + HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + sizeof (VARIABLE_STORE_HEADER);
> + Headers = AllocateZeroPool (HeadersLength);
> +
> + NvStorageFtwWorkingSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
> + NvStorageFtwSpareSize = PcdGet32 (PcdFlashNvStorageFtwSpareSize);
> + NvStorageVariableSize = PcdGet32 (PcdFlashNvStorageVariableSize);
> +
> + NvStorageFtwSpareBase = (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) != 0) ?
> + PcdGet64 (PcdFlashNvStorageFtwSpareBase64) : PcdGet32 (PcdFlashNvStorageFtwSpareBase);
> + NvStorageFtwWorkingBase = (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) != 0) ?
> + PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) : PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
> + NvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
> + PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);
> +
> + // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
> + if ((NvStorageVariableBase + NvStorageVariableSize) != NvStorageFtwWorkingBase) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: NvStorageFtwWorkingBase is not contiguous with NvStorageVariableBase region\n",
> + __FUNCTION__
> + ));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if ((NvStorageFtwWorkingBase + NvStorageFtwWorkingSize) != NvStorageFtwSpareBase) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: NvStorageFtwSpareBase is not contiguous with NvStorageFtwWorkingBase region\n",
> + __FUNCTION__
> + ));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + // Check if the size of the area is at least one block size
> + if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->Media.BlockSize <= 0)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n",
> + __FUNCTION__,
> + NvStorageVariableSize
> + ));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->Media.BlockSize <= 0)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n",
> + __FUNCTION__,
> + NvStorageFtwWorkingSize
> + ));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->Media.BlockSize <= 0)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n",
> + __FUNCTION__,
> + NvStorageFtwSpareSize
> + ));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + // Ensure the Variable area Base Addresses are aligned on a block size boundaries
> + if ((NvStorageVariableBase % Instance->Media.BlockSize != 0) ||
> + (NvStorageFtwWorkingBase % Instance->Media.BlockSize != 0) ||
> + (NvStorageFtwSpareBase % Instance->Media.BlockSize != 0))
> + {
> + DEBUG ((DEBUG_ERROR, "%a: NvStorage Base addresses must be aligned to block size boundaries", __FUNCTION__));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // EFI_FIRMWARE_VOLUME_HEADER
> + //
> + FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers;
> + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
> + FirmwareVolumeHeader->FvLength =
> + PcdGet32 (PcdFlashNvStorageVariableSize) +
> + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
> + PcdGet32 (PcdFlashNvStorageFtwSpareSize);
> + FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
> + FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2)(
> + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
> + EFI_FVB2_READ_STATUS | // Reads are currently enabled
> + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
> + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
> + EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
> + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
> + EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
> + );
> + FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY);
> + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
> + FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
> + FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize;
> + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
> + FirmwareVolumeHeader->BlockMap[1].Length = 0;
> + FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength);
> +
> + //
> + // VARIABLE_STORE_HEADER
> + //
> + VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
> + CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
> + VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
> + VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
> + VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
> +
> + // Install the combined super-header in the NorFlash
> + Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
> +
> + FreePool (Headers);
> + return Status;
> +}
> +
> +/**
> + Check the integrity of firmware volume header.
> +
> + @param[in] FwVolHeader - A pointer to a firmware volume header
> +
> + @retval EFI_SUCCESS - The firmware volume is consistent
> + @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
> +
> +**/
> +EFI_STATUS
> +ValidateFvHeader (
> + IN NOR_FLASH_INSTANCE *Instance
> + )
> +{
> + UINT16 Checksum;
> + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
> + VARIABLE_STORE_HEADER *VariableStoreHeader;
> + UINTN VariableStoreLength;
> + UINTN FvLength;
> +
> + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress;
> +
> + FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
> + PcdGet32 (PcdFlashNvStorageFtwSpareSize);
> +
> + //
> + // Verify the header revision, header signature, length
> + // Length of FvBlock cannot be 2**64-1
> + // HeaderLength cannot be an odd number
> + //
> + if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
> + || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
> + || (FwVolHeader->FvLength != FvLength)
> + )
> + {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: No Firmware Volume header present\n",
> + __FUNCTION__
> + ));
> + return EFI_NOT_FOUND;
> + }
> +
> + // Check the Firmware Volume Guid
> + if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: Firmware Volume Guid non-compatible\n",
> + __FUNCTION__
> + ));
> + return EFI_NOT_FOUND;
> + }
> +
> + // Verify the header checksum
> + Checksum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength);
> + if (Checksum != 0) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: FV checksum is invalid (Checksum:0x%X)\n",
> + __FUNCTION__,
> + Checksum
> + ));
> + return EFI_NOT_FOUND;
> + }
> +
> + VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)FwVolHeader + FwVolHeader->HeaderLength);
> +
> + // Check the Variable Store Guid
> + if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
> + !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid))
> + {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: Variable Store Guid non-compatible\n",
> + __FUNCTION__
> + ));
> + return EFI_NOT_FOUND;
> + }
> +
> + VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
> + if (VariableStoreHeader->Size != VariableStoreLength) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: Variable Store Length does not match\n",
> + __FUNCTION__
> + ));
> + return EFI_NOT_FOUND;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + The GetAttributes() function retrieves the attributes and
> + current settings of the block.
> +
> + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> +
> + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
> + current settings are returned.
> + Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
> +
> + @retval EFI_SUCCESS The firmware volume attributes were returned.
> +
> + **/
> +EFI_STATUS
> +EFIAPI
> +FvbGetAttributes (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + OUT EFI_FVB_ATTRIBUTES_2 *Attributes
> + )
> +{
> + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
> + NOR_FLASH_INSTANCE *Instance;
> +
> + Instance = INSTANCE_FROM_FVB_THIS (This);
> +
> + FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2)(
> +
> + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
> + EFI_FVB2_READ_STATUS | // Reads are currently enabled
> + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
> + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
> + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
> +
> + );
> +
> + // Check if it is write protected
> + if (Instance->Media.ReadOnly != TRUE) {
> + FlashFvbAttributes = FlashFvbAttributes |
> + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
> + EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
> + }
> +
> + *Attributes = FlashFvbAttributes;
> +
> + DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + The SetAttributes() function sets configurable firmware volume attributes
> + and returns the new settings of the firmware volume.
> +
> +
> + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> +
> + @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2
> + that contains the desired firmware volume settings.
> + On successful return, it contains the new settings of
> + the firmware volume.
> + Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
> +
> + @retval EFI_SUCCESS The firmware volume attributes were returned.
> +
> + @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities
> + as declared in the firmware volume header.
> +
> + **/
> +EFI_STATUS
> +EFIAPI
> +FvbSetAttributes (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
> + )
> +{
> + DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n", *Attributes));
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + The GetPhysicalAddress() function retrieves the base address of
> + a memory-mapped firmware volume. This function should be called
> + only for memory-mapped firmware volumes.
> +
> + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> +
> + @param Address Pointer to a caller-allocated
> + EFI_PHYSICAL_ADDRESS that, on successful
> + return from GetPhysicalAddress(), contains the
> + base address of the firmware volume.
> +
> + @retval EFI_SUCCESS The firmware volume base address was returned.
> +
> + @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
> +
> + **/
> +EFI_STATUS
> +EFIAPI
> +FvbGetPhysicalAddress (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + OUT EFI_PHYSICAL_ADDRESS *Address
> + )
> +{
> + NOR_FLASH_INSTANCE *Instance;
> +
> + Instance = INSTANCE_FROM_FVB_THIS (This);
> +
> + DEBUG ((DEBUG_BLKIO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->RegionBaseAddress));
> +
> + ASSERT (Address != NULL);
> +
> + *Address = mFlashNvStorageVariableBase;
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + The GetBlockSize() function retrieves the size of the requested
> + block. It also returns the number of additional blocks with
> + the identical size. The GetBlockSize() function is used to
> + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
> +
> +
> + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> +
> + @param Lba Indicates the block for which to return the size.
> +
> + @param BlockSize Pointer to a caller-allocated UINTN in which
> + the size of the block is returned.
> +
> + @param NumberOfBlocks Pointer to a caller-allocated UINTN in
> + which the number of consecutive blocks,
> + starting with Lba, is returned. All
> + blocks in this range have a size of
> + BlockSize.
> +
> +
> + @retval EFI_SUCCESS The firmware volume base address was returned.
> +
> + @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
> +
> + **/
> +EFI_STATUS
> +EFIAPI
> +FvbGetBlockSize (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + IN EFI_LBA Lba,
> + OUT UINTN *BlockSize,
> + OUT UINTN *NumberOfBlocks
> + )
> +{
> + EFI_STATUS Status;
> + NOR_FLASH_INSTANCE *Instance;
> +
> + Instance = INSTANCE_FROM_FVB_THIS (This);
> +
> + DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->Media.BlockSize, Instance->Media.LastBlock));
> +
> + if (Lba > Instance->Media.LastBlock) {
> + DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock));
> + Status = EFI_INVALID_PARAMETER;
> + } else {
> + // This is easy because in this platform each NorFlash device has equal sized blocks.
> + *BlockSize = (UINTN)Instance->Media.BlockSize;
> + *NumberOfBlocks = (UINTN)(Instance->Media.LastBlock - Lba + 1);
> +
> + DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks));
> +
> + Status = EFI_SUCCESS;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Reads the specified number of bytes into a buffer from the specified block.
> +
> + The Read() function reads the requested number of bytes from the
> + requested block and stores them in the provided buffer.
> + Implementations should be mindful that the firmware volume
> + might be in the ReadDisabled state. If it is in this state,
> + the Read() function must return the status code
> + EFI_ACCESS_DENIED without modifying the contents of the
> + buffer. The Read() function must also prevent spanning block
> + boundaries. If a read is requested that would span a block
> + boundary, the read must read up to the boundary but not
> + beyond. The output parameter NumBytes must be set to correctly
> + indicate the number of bytes actually read. The caller must be
> + aware that a read may be partially completed.
> +
> + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> +
> + @param Lba The starting logical block index from which to read.
> +
> + @param Offset Offset into the block at which to begin reading.
> +
> + @param NumBytes Pointer to a UINTN.
> + At entry, *NumBytes contains the total size of the buffer.
> + At exit, *NumBytes contains the total number of bytes read.
> +
> + @param Buffer Pointer to a caller-allocated buffer that will be used
> + to hold the data that is read.
> +
> + @retval EFI_SUCCESS The firmware volume was read successfully, and contents are
> + in Buffer.
> +
> + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
> + On output, NumBytes contains the total number of bytes
> + returned in Buffer.
> +
> + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.
> +
> + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read.
> +
> + **/
> +EFI_STATUS
> +EFIAPI
> +FvbRead (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN OUT UINTN *NumBytes,
> + IN OUT UINT8 *Buffer
> + )
> +{
> + EFI_STATUS TempStatus;
> + UINTN BlockSize;
> + NOR_FLASH_INSTANCE *Instance;
> +
> + Instance = INSTANCE_FROM_FVB_THIS (This);
> +
> + DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
> +
> + TempStatus = EFI_SUCCESS;
> +
> + // Cache the block size to avoid de-referencing pointers all the time
> + BlockSize = Instance->Media.BlockSize;
> +
> + DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
> +
> + // The read must not span block boundaries.
> + // We need to check each variable individually because adding two large values together overflows.
> + if ((Offset >= BlockSize) ||
> + (*NumBytes > BlockSize) ||
> + ((Offset + *NumBytes) > BlockSize))
> + {
> + DEBUG ((DEBUG_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // We must have some bytes to read
> + if (*NumBytes == 0) {
> + return EFI_BAD_BUFFER_SIZE;
> + }
> +
> + // Decide if we are doing full block reads or not.
> + if (*NumBytes % BlockSize != 0) {
> + TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer);
> + if (EFI_ERROR (TempStatus)) {
> + return EFI_DEVICE_ERROR;
> + }
> + } else {
> + // Read NOR Flash data into shadow buffer
> + TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer);
> + if (EFI_ERROR (TempStatus)) {
> + // Return one of the pre-approved error statuses
> + return EFI_DEVICE_ERROR;
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Writes the specified number of bytes from the input buffer to the block.
> +
> + The Write() function writes the specified number of bytes from
> + the provided buffer to the specified block and offset. If the
> + firmware volume is sticky write, the caller must ensure that
> + all the bits of the specified range to write are in the
> + EFI_FVB_ERASE_POLARITY state before calling the Write()
> + function, or else the result will be unpredictable. This
> + unpredictability arises because, for a sticky-write firmware
> + volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
> + state but cannot flip it back again. Before calling the
> + Write() function, it is recommended for the caller to first call
> + the EraseBlocks() function to erase the specified block to
> + write. A block erase cycle will transition bits from the
> + (NOT)EFI_FVB_ERASE_POLARITY state back to the
> + EFI_FVB_ERASE_POLARITY state. Implementations should be
> + mindful that the firmware volume might be in the WriteDisabled
> + state. If it is in this state, the Write() function must
> + return the status code EFI_ACCESS_DENIED without modifying the
> + contents of the firmware volume. The Write() function must
> + also prevent spanning block boundaries. If a write is
> + requested that spans a block boundary, the write must store up
> + to the boundary but not beyond. The output parameter NumBytes
> + must be set to correctly indicate the number of bytes actually
> + written. The caller must be aware that a write may be
> + partially completed. All writes, partial or otherwise, must be
> + fully flushed to the hardware before the Write() service
> + returns.
> +
> + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> +
> + @param Lba The starting logical block index to write to.
> +
> + @param Offset Offset into the block at which to begin writing.
> +
> + @param NumBytes The pointer to a UINTN.
> + At entry, *NumBytes contains the total size of the buffer.
> + At exit, *NumBytes contains the total number of bytes actually written.
> +
> + @param Buffer The pointer to a caller-allocated buffer that contains the source for the write.
> +
> + @retval EFI_SUCCESS The firmware volume was written successfully.
> +
> + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
> + On output, NumBytes contains the total number of bytes
> + actually written.
> +
> + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
> +
> + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written.
> +
> +
> + **/
> +EFI_STATUS
> +EFIAPI
> +FvbWrite (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + IN EFI_LBA Lba,
> + IN UINTN Offset,
> + IN OUT UINTN *NumBytes,
> + IN UINT8 *Buffer
> + )
> +{
> + NOR_FLASH_INSTANCE *Instance;
> +
> + Instance = INSTANCE_FROM_FVB_THIS (This);
> +
> + return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset, NumBytes, Buffer);
> +}
> +
> +/**
> + Erases and initialises a firmware volume block.
> +
> + The EraseBlocks() function erases one or more blocks as denoted
> + by the variable argument list. The entire parameter list of
> + blocks must be verified before erasing any blocks. If a block is
> + requested that does not exist within the associated firmware
> + volume (it has a larger index than the last block of the
> + firmware volume), the EraseBlocks() function must return the
> + status code EFI_INVALID_PARAMETER without modifying the contents
> + of the firmware volume. Implementations should be mindful that
> + the firmware volume might be in the WriteDisabled state. If it
> + is in this state, the EraseBlocks() function must return the
> + status code EFI_ACCESS_DENIED without modifying the contents of
> + the firmware volume. All calls to EraseBlocks() must be fully
> + flushed to the hardware before the EraseBlocks() service
> + returns.
> +
> + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
> + instance.
> +
> + @param ... The variable argument list is a list of tuples.
> + Each tuple describes a range of LBAs to erase
> + and consists of the following:
> + - An EFI_LBA that indicates the starting LBA
> + - A UINTN that indicates the number of blocks to erase.
> +
> + The list is terminated with an EFI_LBA_LIST_TERMINATOR.
> + For example, the following indicates that two ranges of blocks
> + (5-7 and 10-11) are to be erased:
> + EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
> +
> + @retval EFI_SUCCESS The erase request successfully completed.
> +
> + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
> +
> + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written.
> + The firmware device may have been partially erased.
> +
> + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do
> + not exist in the firmware volume.
> +
> + **/
> +EFI_STATUS
> +EFIAPI
> +FvbEraseBlocks (
> + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> + ...
> + )
> +{
> + EFI_STATUS Status;
> + VA_LIST Args;
> + UINTN BlockAddress; // Physical address of Lba to erase
> + EFI_LBA StartingLba; // Lba from which we start erasing
> + UINTN NumOfLba; // Number of Lba blocks to erase
> + NOR_FLASH_INSTANCE *Instance;
> +
> + Instance = INSTANCE_FROM_FVB_THIS (This);
> +
> + DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n"));
> +
> + Status = EFI_SUCCESS;
> +
> + // Detect WriteDisabled state
> + if (Instance->Media.ReadOnly == TRUE) {
> + // Firmware volume is in WriteDisabled state
> + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"));
> + return EFI_ACCESS_DENIED;
> + }
> +
> + // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
> +
> + VA_START (Args, This);
> + do {
> + // Get the Lba from which we start erasing
> + StartingLba = VA_ARG (Args, EFI_LBA);
> +
> + // Have we reached the end of the list?
> + if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
> + // Exit the while loop
> + break;
> + }
> +
> + // How many Lba blocks are we requested to erase?
> + NumOfLba = VA_ARG (Args, UINTN);
> +
> + // All blocks must be within range
> + DEBUG ((
> + DEBUG_BLKIO,
> + "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n",
> + Instance->StartLba + StartingLba,
> + (UINT64)NumOfLba,
> + Instance->Media.LastBlock
> + ));
> + if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) {
> + VA_END (Args);
> + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> + } while (TRUE);
> +
> + VA_END (Args);
> +
> + //
> + // To get here, all must be ok, so start erasing
> + //
> + VA_START (Args, This);
> + do {
> + // Get the Lba from which we start erasing
> + StartingLba = VA_ARG (Args, EFI_LBA);
> +
> + // Have we reached the end of the list?
> + if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
> + // Exit the while loop
> + break;
> + }
> +
> + // How many Lba blocks are we requested to erase?
> + NumOfLba = VA_ARG (Args, UINTN);
> +
> + // Go through each one and erase it
> + while (NumOfLba > 0) {
> + // Get the physical address of Lba to erase
> + BlockAddress = GET_NOR_BLOCK_ADDRESS (
> + Instance->RegionBaseAddress,
> + Instance->StartLba + StartingLba,
> + Instance->Media.BlockSize
> + );
> +
> + // Erase it
> + DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress));
> + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
> + if (EFI_ERROR (Status)) {
> + VA_END (Args);
> + Status = EFI_DEVICE_ERROR;
> + goto EXIT;
> + }
> +
> + // Move to the next Lba
> + StartingLba++;
> + NumOfLba--;
> + }
> + } while (TRUE);
> +
> + VA_END (Args);
> +
> +EXIT:
> + return Status;
> +}
> +
> +/**
> + Fixup internal data so that EFI can be call in virtual mode.
> + Call the passed in Child Notify event and convert any pointers in
> + lib to virtual mode.
> +
> + @param[in] Event The Event that is being processed
> + @param[in] Context Event Context
> +**/
> +VOID
> +EFIAPI
> +FvbVirtualNotifyEvent (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + )
> +{
> + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase);
> + return;
> +}
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver
2022-10-10 10:39 ` Ard Biesheuvel
@ 2022-10-10 15:19 ` Sunil V L
2022-10-10 15:29 ` Ard Biesheuvel
0 siblings, 1 reply; 43+ messages in thread
From: Sunil V L @ 2022-10-10 15:19 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
On Mon, Oct 10, 2022 at 12:39:21PM +0200, Ard Biesheuvel wrote:
> On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
> >
> > RISC-V needs NorFlashDxe driver for qemu virt machine. The
> > ArmPlatformPkg has this driver but migrating it to generic
> > package like MdeModulePkg introduces circular dependencies.
> > So, add a simplified version of the NorFlashDxe driver in
> > OvmfPkg.
> >
>
> So what is the difference between this simplified version and the old
> version? And it is backed in QEMU by the same NOR flash emulation,
> shouldn't we use this driver for ArmVirtQemu as well?
I agree. If we can break the dependency on EmbeddedPkg due to
NvVarStoreFormattedLib, then we can migrate to MdeModulePkg and all
consumers can use the same driver which would be the best solution IMO.
Could you please let me know why NvVarStoreFormattedLib is added
in EmbeddedPkg instead of MdePkg or MdeModulePkg? Is it only for
non-server class platforms? I don't see it doing much so not sure
its use case.
Thanks
Sunil
>
>
> > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Gerd Hoffmann <kraxel@redhat.com>
> > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> > ---
> > OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf | 69 ++
> > OvmfPkg/Drivers/NorFlashDxe/NorFlash.h | 422 ++++++++
> > OvmfPkg/Drivers/NorFlashDxe/NorFlash.c | 972 ++++++++++++++++++
> > .../Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | 123 +++
> > OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c | 506 +++++++++
> > OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c | 777 ++++++++++++++
> > 6 files changed, 2869 insertions(+)
> > create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
> > create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
> > create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
> > create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
> > create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
> > create mode 100644 OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
> >
> > diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
> > new file mode 100644
> > index 000000000000..e327b2ac7405
> > --- /dev/null
> > +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
> > @@ -0,0 +1,69 @@
> > +#/** @file
> > +#
> > +# Component description file for NorFlashDxe module
> > +#
> > +# Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
> > +#
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +#**/
> > +
> > +[Defines]
> > + INF_VERSION = 0x00010005
> > + BASE_NAME = QemuNorFlashDxe
> > + FILE_GUID = D4F3B3FC-3AEF-4774-AC94-304438ABDA53
> > + MODULE_TYPE = DXE_RUNTIME_DRIVER
> > + VERSION_STRING = 1.0
> > + ENTRY_POINT = NorFlashInitialise
> > +
> > +[Sources.common]
> > + NorFlash.c
> > + NorFlash.h
> > + NorFlashDxe.c
> > + NorFlashFvb.c
> > + NorFlashBlockIoDxe.c
> > +
> > +[Packages]
> > + MdePkg/MdePkg.dec
> > + OvmfPkg/OvmfPkg.dec
> > + MdeModulePkg/MdeModulePkg.dec
> > + EmbeddedPkg/EmbeddedPkg.dec
> > +
> > +[LibraryClasses]
> > + IoLib
> > + BaseLib
> > + DebugLib
> > + HobLib
> > + NorFlashPlatformLib
> > + UefiLib
> > + UefiDriverEntryPoint
> > + UefiBootServicesTableLib
> > + UefiRuntimeLib
> > + DxeServicesTableLib
> > +
> > +[Guids]
> > + gEfiSystemNvDataFvGuid
> > + gEfiVariableGuid
> > + gEfiAuthenticatedVariableGuid
> > + gEfiEventVirtualAddressChangeGuid
> > + gEdkiiNvVarStoreFormattedGuid ## PRODUCES ## PROTOCOL
> > +
> > +[Protocols]
> > + gEfiBlockIoProtocolGuid
> > + gEfiDevicePathProtocolGuid
> > + gEfiFirmwareVolumeBlockProtocolGuid
> > + gEfiDiskIoProtocolGuid
> > +
> > +[Pcd.common]
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
> > +
> > +[Depex]
> > + gEfiCpuArchProtocolGuid
> > diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
> > new file mode 100644
> > index 000000000000..c83032e87d9c
> > --- /dev/null
> > +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.h
> > @@ -0,0 +1,422 @@
> > +/** @file NorFlash.h
> > +
> > + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
> > +
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef __NOR_FLASH_H__
> > +#define __NOR_FLASH_H__
> > +
> > +#include <Base.h>
> > +#include <PiDxe.h>
> > +
> > +#include <Guid/EventGroup.h>
> > +
> > +#include <Protocol/BlockIo.h>
> > +#include <Protocol/DiskIo.h>
> > +#include <Protocol/FirmwareVolumeBlock.h>
> > +
> > +#include <Library/DebugLib.h>
> > +#include <Library/IoLib.h>
> > +#include <Library/NorFlashPlatformLib.h>
> > +#include <Library/UefiLib.h>
> > +#include <Library/UefiRuntimeLib.h>
> > +
> > +#define NOR_FLASH_ERASE_RETRY 10
> > +
> > +// Device access macros
> > +// These are necessary because we use 2 x 16bit parts to make up 32bit data
> > +
> > +#define HIGH_16_BITS 0xFFFF0000
> > +#define LOW_16_BITS 0x0000FFFF
> > +#define LOW_8_BITS 0x000000FF
> > +
> > +#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
> > +
> > +#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )
> > +#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )
> > +
> > +// Each command must be sent simultaneously to both chips,
> > +// i.e. at the lower 16 bits AND at the higher 16 bits
> > +#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + ((OffsetAddr) << 2))
> > +#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
> > +#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))
> > +#define GET_NOR_BLOCK_ADDRESS(BaseAddr, Lba, LbaSize) ( BaseAddr + (UINTN)((Lba) * LbaSize) )
> > +
> > +// Status Register Bits
> > +#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)
> > +#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)
> > +#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)
> > +#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)
> > +#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)
> > +#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)
> > +#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)
> > +#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)
> > +
> > +// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
> > +
> > +// On chip buffer size for buffered programming operations
> > +// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
> > +// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
> > +#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)
> > +#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
> > +#define MAX_BUFFERED_PROG_ITERATIONS 10000000
> > +#define BOUNDARY_OF_32_WORDS 0x7F
> > +
> > +// CFI Addresses
> > +#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10
> > +#define P30_CFI_ADDR_VENDOR_ID 0x13
> > +
> > +// CFI Data
> > +#define CFI_QRY 0x00595251
> > +
> > +// READ Commands
> > +#define P30_CMD_READ_DEVICE_ID 0x0090
> > +#define P30_CMD_READ_STATUS_REGISTER 0x0070
> > +#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050
> > +#define P30_CMD_READ_ARRAY 0x00FF
> > +#define P30_CMD_READ_CFI_QUERY 0x0098
> > +
> > +// WRITE Commands
> > +#define P30_CMD_WORD_PROGRAM_SETUP 0x0040
> > +#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010
> > +#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8
> > +#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0
> > +#define P30_CMD_BEFP_SETUP 0x0080
> > +#define P30_CMD_BEFP_CONFIRM 0x00D0
> > +
> > +// ERASE Commands
> > +#define P30_CMD_BLOCK_ERASE_SETUP 0x0020
> > +#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0
> > +
> > +// SUSPEND Commands
> > +#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0
> > +#define P30_CMD_SUSPEND_RESUME 0x00D0
> > +
> > +// BLOCK LOCKING / UNLOCKING Commands
> > +#define P30_CMD_LOCK_BLOCK_SETUP 0x0060
> > +#define P30_CMD_LOCK_BLOCK 0x0001
> > +#define P30_CMD_UNLOCK_BLOCK 0x00D0
> > +#define P30_CMD_LOCK_DOWN_BLOCK 0x002F
> > +
> > +// PROTECTION Commands
> > +#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
> > +
> > +// CONFIGURATION Commands
> > +#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
> > +#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003
> > +
> > +#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
> > +#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
> > +#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
> > +#define INSTANCE_FROM_DISKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, DiskIoProtocol, NOR_FLASH_SIGNATURE)
> > +
> > +typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
> > +
> > +#pragma pack (1)
> > +typedef struct {
> > + VENDOR_DEVICE_PATH Vendor;
> > + UINT8 Index;
> > + EFI_DEVICE_PATH_PROTOCOL End;
> > +} NOR_FLASH_DEVICE_PATH;
> > +#pragma pack ()
> > +
> > +struct _NOR_FLASH_INSTANCE {
> > + UINT32 Signature;
> > + EFI_HANDLE Handle;
> > +
> > + UINTN DeviceBaseAddress;
> > + UINTN RegionBaseAddress;
> > + UINTN Size;
> > + EFI_LBA StartLba;
> > +
> > + EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
> > + EFI_BLOCK_IO_MEDIA Media;
> > + EFI_DISK_IO_PROTOCOL DiskIoProtocol;
> > +
> > + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
> > + VOID *ShadowBuffer;
> > +
> > + NOR_FLASH_DEVICE_PATH DevicePath;
> > +};
> > +
> > +EFI_STATUS
> > +NorFlashReadCfiData (
> > + IN UINTN DeviceBaseAddress,
> > + IN UINTN CFI_Offset,
> > + IN UINT32 NumberOfBytes,
> > + OUT UINT32 *Data
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashWriteBuffer (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN TargetAddress,
> > + IN UINTN BufferSizeInBytes,
> > + IN UINT32 *Buffer
> > + );
> > +
> > +//
> > +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashBlockIoReset (
> > + IN EFI_BLOCK_IO_PROTOCOL *This,
> > + IN BOOLEAN ExtendedVerification
> > + );
> > +
> > +//
> > +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashBlockIoReadBlocks (
> > + IN EFI_BLOCK_IO_PROTOCOL *This,
> > + IN UINT32 MediaId,
> > + IN EFI_LBA Lba,
> > + IN UINTN BufferSizeInBytes,
> > + OUT VOID *Buffer
> > + );
> > +
> > +//
> > +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashBlockIoWriteBlocks (
> > + IN EFI_BLOCK_IO_PROTOCOL *This,
> > + IN UINT32 MediaId,
> > + IN EFI_LBA Lba,
> > + IN UINTN BufferSizeInBytes,
> > + IN VOID *Buffer
> > + );
> > +
> > +//
> > +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashBlockIoFlushBlocks (
> > + IN EFI_BLOCK_IO_PROTOCOL *This
> > + );
> > +
> > +//
> > +// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.ReadDisk
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashDiskIoReadDisk (
> > + IN EFI_DISK_IO_PROTOCOL *This,
> > + IN UINT32 MediaId,
> > + IN UINT64 Offset,
> > + IN UINTN BufferSize,
> > + OUT VOID *Buffer
> > + );
> > +
> > +//
> > +// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.WriteDisk
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashDiskIoWriteDisk (
> > + IN EFI_DISK_IO_PROTOCOL *This,
> > + IN UINT32 MediaId,
> > + IN UINT64 Offset,
> > + IN UINTN BufferSize,
> > + IN VOID *Buffer
> > + );
> > +
> > +//
> > +// NorFlashFvbDxe.c
> > +//
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +FvbGetAttributes (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + OUT EFI_FVB_ATTRIBUTES_2 *Attributes
> > + );
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +FvbSetAttributes (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
> > + );
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +FvbGetPhysicalAddress (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + OUT EFI_PHYSICAL_ADDRESS *Address
> > + );
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +FvbGetBlockSize (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + IN EFI_LBA Lba,
> > + OUT UINTN *BlockSize,
> > + OUT UINTN *NumberOfBlocks
> > + );
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +FvbRead (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN OUT UINTN *NumBytes,
> > + IN OUT UINT8 *Buffer
> > + );
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +FvbWrite (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN OUT UINTN *NumBytes,
> > + IN UINT8 *Buffer
> > + );
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +FvbEraseBlocks (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + ...
> > + );
> > +
> > +EFI_STATUS
> > +ValidateFvHeader (
> > + IN NOR_FLASH_INSTANCE *Instance
> > + );
> > +
> > +EFI_STATUS
> > +InitializeFvAndVariableStoreHeaders (
> > + IN NOR_FLASH_INSTANCE *Instance
> > + );
> > +
> > +VOID
> > +EFIAPI
> > +FvbVirtualNotifyEvent (
> > + IN EFI_EVENT Event,
> > + IN VOID *Context
> > + );
> > +
> > +//
> > +// NorFlashDxe.c
> > +//
> > +
> > +EFI_STATUS
> > +NorFlashWriteFullBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINT32 *DataBuffer,
> > + IN UINT32 BlockSizeInWords
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashUnlockAndEraseSingleBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN BlockAddress
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashCreateInstance (
> > + IN UINTN NorFlashDeviceBase,
> > + IN UINTN NorFlashRegionBase,
> > + IN UINTN NorFlashSize,
> > + IN UINT32 Index,
> > + IN UINT32 BlockSize,
> > + IN BOOLEAN SupportFvb,
> > + OUT NOR_FLASH_INSTANCE **NorFlashInstance
> > + );
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashFvbInitialize (
> > + IN NOR_FLASH_INSTANCE *Instance
> > + );
> > +
> > +//
> > +// NorFlash.c
> > +//
> > +EFI_STATUS
> > +NorFlashWriteSingleBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN OUT UINTN *NumBytes,
> > + IN UINT8 *Buffer
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashWriteBlocks (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN BufferSizeInBytes,
> > + IN VOID *Buffer
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashReadBlocks (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN BufferSizeInBytes,
> > + OUT VOID *Buffer
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashRead (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN UINTN BufferSizeInBytes,
> > + OUT VOID *Buffer
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashWrite (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN OUT UINTN *NumBytes,
> > + IN UINT8 *Buffer
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashReset (
> > + IN NOR_FLASH_INSTANCE *Instance
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashEraseSingleBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN BlockAddress
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashUnlockSingleBlockIfNecessary (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN BlockAddress
> > + );
> > +
> > +EFI_STATUS
> > +NorFlashWriteSingleWord (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN WordAddress,
> > + IN UINT32 WriteData
> > + );
> > +
> > +VOID
> > +EFIAPI
> > +NorFlashVirtualNotifyEvent (
> > + IN EFI_EVENT Event,
> > + IN VOID *Context
> > + );
> > +
> > +#endif /* __NOR_FLASH_H__ */
> > diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
> > new file mode 100644
> > index 000000000000..c2a6aa281578
> > --- /dev/null
> > +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlash.c
> > @@ -0,0 +1,972 @@
> > +/** @file NorFlash.c
> > +
> > + Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.<BR>
> > + Copyright (c) 2020, Linaro, Ltd. All rights reserved.<BR>
> > +
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseMemoryLib.h>
> > +
> > +#include "NorFlash.h"
> > +
> > +//
> > +// Global variable declarations
> > +//
> > +extern NOR_FLASH_INSTANCE **mNorFlashInstances;
> > +extern UINT32 mNorFlashDeviceCount;
> > +
> > +UINT32
> > +NorFlashReadStatusRegister (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN SR_Address
> > + )
> > +{
> > + // Prepare to read the status register
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);
> > + return MmioRead32 (Instance->DeviceBaseAddress);
> > +}
> > +
> > +STATIC
> > +BOOLEAN
> > +NorFlashBlockIsLocked (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN BlockAddress
> > + )
> > +{
> > + UINT32 LockStatus;
> > +
> > + // Send command for reading device id
> > + SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
> > +
> > + // Read block lock status
> > + LockStatus = MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2));
> > +
> > + // Decode block lock status
> > + LockStatus = FOLD_32BIT_INTO_16BIT (LockStatus);
> > +
> > + if ((LockStatus & 0x2) != 0) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN\n"));
> > + }
> > +
> > + return ((LockStatus & 0x1) != 0);
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +NorFlashUnlockSingleBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN BlockAddress
> > + )
> > +{
> > + UINT32 LockStatus;
> > +
> > + // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
> > + // and to protect shared data structures.
> > +
> > + // Request a lock setup
> > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
> > +
> > + // Request an unlock
> > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
> > +
> > + // Wait until the status register gives us the all clear
> > + do {
> > + LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
> > + } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
> > +
> > + // Put device back into Read Array mode
> > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY);
> > +
> > + DEBUG ((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x\n", BlockAddress));
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +EFI_STATUS
> > +NorFlashUnlockSingleBlockIfNecessary (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN BlockAddress
> > + )
> > +{
> > + EFI_STATUS Status;
> > +
> > + Status = EFI_SUCCESS;
> > +
> > + if (NorFlashBlockIsLocked (Instance, BlockAddress)) {
> > + Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
> > + }
> > +
> > + return Status;
> > +}
> > +
> > +/**
> > + * The following function presumes that the block has already been unlocked.
> > + **/
> > +EFI_STATUS
> > +NorFlashEraseSingleBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN BlockAddress
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT32 StatusRegister;
> > +
> > + Status = EFI_SUCCESS;
> > +
> > + // Request a block erase and then confirm it
> > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP);
> > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM);
> > +
> > + // Wait until the status register gives us the all clear
> > + do {
> > + StatusRegister = NorFlashReadStatusRegister (Instance, BlockAddress);
> > + } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
> > +
> > + if (StatusRegister & P30_SR_BIT_VPP) {
> > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: VPP Range Error\n", BlockAddress));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) == (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) {
> > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Command Sequence Error\n", BlockAddress));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if (StatusRegister & P30_SR_BIT_ERASE) {
> > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Erase Error StatusRegister:0x%X\n", BlockAddress, StatusRegister));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
> > + // The debug level message has been reduced because a device lock might happen. In this case we just retry it ...
> > + DEBUG ((DEBUG_INFO, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error\n", BlockAddress));
> > + Status = EFI_WRITE_PROTECTED;
> > + }
> > +
> > + if (EFI_ERROR (Status)) {
> > + // Clear the Status Register
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
> > + }
> > +
> > + // Put device back into Read Array mode
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> > +
> > + return Status;
> > +}
> > +
> > +EFI_STATUS
> > +NorFlashWriteSingleWord (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN WordAddress,
> > + IN UINT32 WriteData
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT32 StatusRegister;
> > +
> > + Status = EFI_SUCCESS;
> > +
> > + // Request a write single word command
> > + SEND_NOR_COMMAND (WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP);
> > +
> > + // Store the word into NOR Flash;
> > + MmioWrite32 (WordAddress, WriteData);
> > +
> > + // Wait for the write to complete and then check for any errors; i.e. check the Status Register
> > + do {
> > + // Prepare to read the status register
> > + StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress);
> > + // The chip is busy while the WRITE bit is not asserted
> > + } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
> > +
> > + // Perform a full status check:
> > + // Mask the relevant bits of Status Register.
> > + // Everything should be zero, if not, we have a problem
> > +
> > + if (StatusRegister & P30_SR_BIT_VPP) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): VPP Range Error\n", WordAddress));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if (StatusRegister & P30_SR_BIT_PROGRAM) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Program Error\n", WordAddress));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Device Protect Error\n", WordAddress));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if (!EFI_ERROR (Status)) {
> > + // Clear the Status Register
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
> > + }
> > +
> > + // Put device back into Read Array mode
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> > +
> > + return Status;
> > +}
> > +
> > +/*
> > + * Writes data to the NOR Flash using the Buffered Programming method.
> > + *
> > + * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions.
> > + * Therefore this function will only handle buffers up to 32 words or 128 bytes.
> > + * To deal with larger buffers, call this function again.
> > + *
> > + * This function presumes that both the TargetAddress and the TargetAddress+BufferSize
> > + * exist entirely within the NOR Flash. Therefore these conditions will not be checked here.
> > + *
> > + * In buffered programming, if the target address not at the beginning of a 32-bit word boundary,
> > + * then programming time is doubled and power consumption is increased.
> > + * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries.
> > + * i.e. the last 4 bits of the target start address must be zero: 0x......00
> > + */
> > +EFI_STATUS
> > +NorFlashWriteBuffer (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN TargetAddress,
> > + IN UINTN BufferSizeInBytes,
> > + IN UINT32 *Buffer
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINTN BufferSizeInWords;
> > + UINTN Count;
> > + volatile UINT32 *Data;
> > + UINTN WaitForBuffer;
> > + BOOLEAN BufferAvailable;
> > + UINT32 StatusRegister;
> > +
> > + WaitForBuffer = MAX_BUFFERED_PROG_ITERATIONS;
> > + BufferAvailable = FALSE;
> > +
> > + // Check that the target address does not cross a 32-word boundary.
> > + if ((TargetAddress & BOUNDARY_OF_32_WORDS) != 0) {
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + // Check there are some data to program
> > + if (BufferSizeInBytes == 0) {
> > + return EFI_BUFFER_TOO_SMALL;
> > + }
> > +
> > + // Check that the buffer size does not exceed the maximum hardware buffer size on chip.
> > + if (BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES) {
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // Check that the buffer size is a multiple of 32-bit words
> > + if ((BufferSizeInBytes % 4) != 0) {
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // Pre-programming conditions checked, now start the algorithm.
> > +
> > + // Prepare the data destination address
> > + Data = (UINT32 *)TargetAddress;
> > +
> > + // Check the availability of the buffer
> > + do {
> > + // Issue the Buffered Program Setup command
> > + SEND_NOR_COMMAND (TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP);
> > +
> > + // Read back the status register bit#7 from the same address
> > + if (((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE) {
> > + BufferAvailable = TRUE;
> > + }
> > +
> > + // Update the loop counter
> > + WaitForBuffer--;
> > + } while ((WaitForBuffer > 0) && (BufferAvailable == FALSE));
> > +
> > + // The buffer was not available for writing
> > + if (WaitForBuffer == 0) {
> > + Status = EFI_DEVICE_ERROR;
> > + goto EXIT;
> > + }
> > +
> > + // From now on we work in 32-bit words
> > + BufferSizeInWords = BufferSizeInBytes / (UINTN)4;
> > +
> > + // Write the word count, which is (buffer_size_in_words - 1),
> > + // because word count 0 means one word.
> > + SEND_NOR_COMMAND (TargetAddress, 0, (BufferSizeInWords - 1));
> > +
> > + // Write the data to the NOR Flash, advancing each address by 4 bytes
> > + for (Count = 0; Count < BufferSizeInWords; Count++, Data++, Buffer++) {
> > + MmioWrite32 ((UINTN)Data, *Buffer);
> > + }
> > +
> > + // Issue the Buffered Program Confirm command, to start the programming operation
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM);
> > +
> > + // Wait for the write to complete and then check for any errors; i.e. check the Status Register
> > + do {
> > + StatusRegister = NorFlashReadStatusRegister (Instance, TargetAddress);
> > + // The chip is busy while the WRITE bit is not asserted
> > + } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
> > +
> > + // Perform a full status check:
> > + // Mask the relevant bits of Status Register.
> > + // Everything should be zero, if not, we have a problem
> > +
> > + Status = EFI_SUCCESS;
> > +
> > + if (StatusRegister & P30_SR_BIT_VPP) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): VPP Range Error\n", TargetAddress));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if (StatusRegister & P30_SR_BIT_PROGRAM) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Program Error\n", TargetAddress));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Device Protect Error\n", TargetAddress));
> > + Status = EFI_DEVICE_ERROR;
> > + }
> > +
> > + if (!EFI_ERROR (Status)) {
> > + // Clear the Status Register
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
> > + }
> > +
> > +EXIT:
> > + // Put device back into Read Array mode
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> > +
> > + return Status;
> > +}
> > +
> > +EFI_STATUS
> > +NorFlashWriteBlocks (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN BufferSizeInBytes,
> > + IN VOID *Buffer
> > + )
> > +{
> > + UINT32 *pWriteBuffer;
> > + EFI_STATUS Status;
> > + EFI_LBA CurrentBlock;
> > + UINT32 BlockSizeInWords;
> > + UINT32 NumBlocks;
> > + UINT32 BlockCount;
> > +
> > + Status = EFI_SUCCESS;
> > +
> > + // The buffer must be valid
> > + if (Buffer == NULL) {
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + if (Instance->Media.ReadOnly == TRUE) {
> > + return EFI_WRITE_PROTECTED;
> > + }
> > +
> > + // We must have some bytes to read
> > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes));
> > + if (BufferSizeInBytes == 0) {
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // The size of the buffer must be a multiple of the block size
> > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize));
> > + if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // All blocks must be within the device
> > + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
> > +
> > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba));
> > +
> > + if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + BlockSizeInWords = Instance->Media.BlockSize / 4;
> > +
> > + // Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer
> > + // to a proper data type, so use *ReadBuffer
> > + pWriteBuffer = (UINT32 *)Buffer;
> > +
> > + CurrentBlock = Lba;
> > + for (BlockCount = 0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++, pWriteBuffer = pWriteBuffer + BlockSizeInWords) {
> > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock));
> > +
> > + Status = NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffer, BlockSizeInWords);
> > +
> > + if (EFI_ERROR (Status)) {
> > + break;
> > + }
> > + }
> > +
> > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status));
> > + return Status;
> > +}
> > +
> > +#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0)
> > +
> > +/**
> > + Copy Length bytes from Source to Destination, using aligned accesses only.
> > + Note that this implementation uses memcpy() semantics rather then memmove()
> > + semantics, i.e., SourceBuffer and DestinationBuffer should not overlap.
> > +
> > + @param DestinationBuffer The target of the copy request.
> > + @param SourceBuffer The place to copy from.
> > + @param Length The number of bytes to copy.
> > +
> > + @return Destination
> > +
> > +**/
> > +STATIC
> > +VOID *
> > +AlignedCopyMem (
> > + OUT VOID *DestinationBuffer,
> > + IN CONST VOID *SourceBuffer,
> > + IN UINTN Length
> > + )
> > +{
> > + UINT8 *Destination8;
> > + CONST UINT8 *Source8;
> > + UINT32 *Destination32;
> > + CONST UINT32 *Source32;
> > + UINT64 *Destination64;
> > + CONST UINT64 *Source64;
> > +
> > + if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 8) && (Length >= 8)) {
> > + Destination64 = DestinationBuffer;
> > + Source64 = SourceBuffer;
> > + while (Length >= 8) {
> > + *Destination64++ = *Source64++;
> > + Length -= 8;
> > + }
> > +
> > + Destination8 = (UINT8 *)Destination64;
> > + Source8 = (CONST UINT8 *)Source64;
> > + } else if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 4) && (Length >= 4)) {
> > + Destination32 = DestinationBuffer;
> > + Source32 = SourceBuffer;
> > + while (Length >= 4) {
> > + *Destination32++ = *Source32++;
> > + Length -= 4;
> > + }
> > +
> > + Destination8 = (UINT8 *)Destination32;
> > + Source8 = (CONST UINT8 *)Source32;
> > + } else {
> > + Destination8 = DestinationBuffer;
> > + Source8 = SourceBuffer;
> > + }
> > +
> > + while (Length-- != 0) {
> > + *Destination8++ = *Source8++;
> > + }
> > +
> > + return DestinationBuffer;
> > +}
> > +
> > +EFI_STATUS
> > +NorFlashReadBlocks (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN BufferSizeInBytes,
> > + OUT VOID *Buffer
> > + )
> > +{
> > + UINT32 NumBlocks;
> > + UINTN StartAddress;
> > +
> > + DEBUG ((
> > + DEBUG_BLKIO,
> > + "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
> > + BufferSizeInBytes,
> > + Instance->Media.BlockSize,
> > + Instance->Media.LastBlock,
> > + Lba
> > + ));
> > +
> > + // The buffer must be valid
> > + if (Buffer == NULL) {
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + // Return if we have not any byte to read
> > + if (BufferSizeInBytes == 0) {
> > + return EFI_SUCCESS;
> > + }
> > +
> > + // The size of the buffer must be a multiple of the block size
> > + if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // All blocks must be within the device
> > + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
> > +
> > + if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + // Get the address to start reading from
> > + StartAddress = GET_NOR_BLOCK_ADDRESS (
> > + Instance->RegionBaseAddress,
> > + Lba,
> > + Instance->Media.BlockSize
> > + );
> > +
> > + // Put the device into Read Array mode
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> > +
> > + // Readout the data
> > + AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +EFI_STATUS
> > +NorFlashRead (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN UINTN BufferSizeInBytes,
> > + OUT VOID *Buffer
> > + )
> > +{
> > + UINTN StartAddress;
> > +
> > + // The buffer must be valid
> > + if (Buffer == NULL) {
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + // Return if we have not any byte to read
> > + if (BufferSizeInBytes == 0) {
> > + return EFI_SUCCESS;
> > + }
> > +
> > + if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n"));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + // Get the address to start reading from
> > + StartAddress = GET_NOR_BLOCK_ADDRESS (
> > + Instance->RegionBaseAddress,
> > + Lba,
> > + Instance->Media.BlockSize
> > + );
> > +
> > + // Put the device into Read Array mode
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> > +
> > + // Readout the data
> > + AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/*
> > + Write a full or portion of a block. It must not span block boundaries; that is,
> > + Offset + *NumBytes <= Instance->Media.BlockSize.
> > +*/
> > +EFI_STATUS
> > +NorFlashWriteSingleBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN OUT UINTN *NumBytes,
> > + IN UINT8 *Buffer
> > + )
> > +{
> > + EFI_STATUS TempStatus;
> > + UINT32 Tmp;
> > + UINT32 TmpBuf;
> > + UINT32 WordToWrite;
> > + UINT32 Mask;
> > + BOOLEAN DoErase;
> > + UINTN BytesToWrite;
> > + UINTN CurOffset;
> > + UINTN WordAddr;
> > + UINTN BlockSize;
> > + UINTN BlockAddress;
> > + UINTN PrevBlockAddress;
> > +
> > + PrevBlockAddress = 0;
> > +
> > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
> > +
> > + // Detect WriteDisabled state
> > + if (Instance->Media.ReadOnly == TRUE) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not write: Device is in WriteDisabled state.\n"));
> > + // It is in WriteDisabled state, return an error right away
> > + return EFI_ACCESS_DENIED;
> > + }
> > +
> > + // Cache the block size to avoid de-referencing pointers all the time
> > + BlockSize = Instance->Media.BlockSize;
> > +
> > + // The write must not span block boundaries.
> > + // We need to check each variable individually because adding two large values together overflows.
> > + if ((Offset >= BlockSize) ||
> > + (*NumBytes > BlockSize) ||
> > + ((Offset + *NumBytes) > BlockSize))
> > + {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // We must have some bytes to write
> > + if (*NumBytes == 0) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // Pick 128bytes as a good start for word operations as opposed to erasing the
> > + // block and writing the data regardless if an erase is really needed.
> > + // It looks like most individual NV variable writes are smaller than 128bytes.
> > + if (*NumBytes <= 128) {
> > + // Check to see if we need to erase before programming the data into NOR.
> > + // If the destination bits are only changing from 1s to 0s we can just write.
> > + // After a block is erased all bits in the block is set to 1.
> > + // If any byte requires us to erase we just give up and rewrite all of it.
> > + DoErase = FALSE;
> > + BytesToWrite = *NumBytes;
> > + CurOffset = Offset;
> > +
> > + while (BytesToWrite > 0) {
> > + // Read full word from NOR, splice as required. A word is the smallest
> > + // unit we can write.
> > + TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof (Tmp), &Tmp);
> > + if (EFI_ERROR (TempStatus)) {
> > + return EFI_DEVICE_ERROR;
> > + }
> > +
> > + // Physical address of word in NOR to write.
> > + WordAddr = (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS (
> > + Instance->RegionBaseAddress,
> > + Lba,
> > + BlockSize
> > + );
> > + // The word of data that is to be written.
> > + TmpBuf = *((UINT32 *)(Buffer + (*NumBytes - BytesToWrite)));
> > +
> > + // First do word aligned chunks.
> > + if ((CurOffset & 0x3) == 0) {
> > + if (BytesToWrite >= 4) {
> > + // Is the destination still in 'erased' state?
> > + if (~Tmp != 0) {
> > + // Check to see if we are only changing bits to zero.
> > + if ((Tmp ^ TmpBuf) & TmpBuf) {
> > + DoErase = TRUE;
> > + break;
> > + }
> > + }
> > +
> > + // Write this word to NOR
> > + WordToWrite = TmpBuf;
> > + CurOffset += sizeof (TmpBuf);
> > + BytesToWrite -= sizeof (TmpBuf);
> > + } else {
> > + // BytesToWrite < 4. Do small writes and left-overs
> > + Mask = ~((~0) << (BytesToWrite * 8));
> > + // Mask out the bytes we want.
> > + TmpBuf &= Mask;
> > + // Is the destination still in 'erased' state?
> > + if ((Tmp & Mask) != Mask) {
> > + // Check to see if we are only changing bits to zero.
> > + if ((Tmp ^ TmpBuf) & TmpBuf) {
> > + DoErase = TRUE;
> > + break;
> > + }
> > + }
> > +
> > + // Merge old and new data. Write merged word to NOR
> > + WordToWrite = (Tmp & ~Mask) | TmpBuf;
> > + CurOffset += BytesToWrite;
> > + BytesToWrite = 0;
> > + }
> > + } else {
> > + // Do multiple words, but starting unaligned.
> > + if (BytesToWrite > (4 - (CurOffset & 0x3))) {
> > + Mask = ((~0) << ((CurOffset & 0x3) * 8));
> > + // Mask out the bytes we want.
> > + TmpBuf &= Mask;
> > + // Is the destination still in 'erased' state?
> > + if ((Tmp & Mask) != Mask) {
> > + // Check to see if we are only changing bits to zero.
> > + if ((Tmp ^ TmpBuf) & TmpBuf) {
> > + DoErase = TRUE;
> > + break;
> > + }
> > + }
> > +
> > + // Merge old and new data. Write merged word to NOR
> > + WordToWrite = (Tmp & ~Mask) | TmpBuf;
> > + BytesToWrite -= (4 - (CurOffset & 0x3));
> > + CurOffset += (4 - (CurOffset & 0x3));
> > + } else {
> > + // Unaligned and fits in one word.
> > + Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8);
> > + // Mask out the bytes we want.
> > + TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;
> > + // Is the destination still in 'erased' state?
> > + if ((Tmp & Mask) != Mask) {
> > + // Check to see if we are only changing bits to zero.
> > + if ((Tmp ^ TmpBuf) & TmpBuf) {
> > + DoErase = TRUE;
> > + break;
> > + }
> > + }
> > +
> > + // Merge old and new data. Write merged word to NOR
> > + WordToWrite = (Tmp & ~Mask) | TmpBuf;
> > + CurOffset += BytesToWrite;
> > + BytesToWrite = 0;
> > + }
> > + }
> > +
> > + //
> > + // Write the word to NOR.
> > + //
> > +
> > + BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
> > + if (BlockAddress != PrevBlockAddress) {
> > + TempStatus = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
> > + if (EFI_ERROR (TempStatus)) {
> > + return EFI_DEVICE_ERROR;
> > + }
> > +
> > + PrevBlockAddress = BlockAddress;
> > + }
> > +
> > + TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
> > + if (EFI_ERROR (TempStatus)) {
> > + return EFI_DEVICE_ERROR;
> > + }
> > + }
> > +
> > + // Exit if we got here and could write all the data. Otherwise do the
> > + // Erase-Write cycle.
> > + if (!DoErase) {
> > + return EFI_SUCCESS;
> > + }
> > + }
> > +
> > + // Check we did get some memory. Buffer is BlockSize.
> > + if (Instance->ShadowBuffer == NULL) {
> > + DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
> > + return EFI_DEVICE_ERROR;
> > + }
> > +
> > + // Read NOR Flash data into shadow buffer
> > + TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
> > + if (EFI_ERROR (TempStatus)) {
> > + // Return one of the pre-approved error statuses
> > + return EFI_DEVICE_ERROR;
> > + }
> > +
> > + // Put the data at the appropriate location inside the buffer area
> > + CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
> > +
> > + // Write the modified buffer back to the NorFlash
> > + TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
> > + if (EFI_ERROR (TempStatus)) {
> > + // Return one of the pre-approved error statuses
> > + return EFI_DEVICE_ERROR;
> > + }
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/*
> > + Although DiskIoDxe will automatically install the DiskIO protocol whenever
> > + we install the BlockIO protocol, its implementation is sub-optimal as it reads
> > + and writes entire blocks using the BlockIO protocol. In fact we can access
> > + NOR flash with a finer granularity than that, so we can improve performance
> > + by directly producing the DiskIO protocol.
> > +*/
> > +
> > +/**
> > + Read BufferSize bytes from Offset into Buffer.
> > +
> > + @param This Protocol instance pointer.
> > + @param MediaId Id of the media, changes every time the media is replaced.
> > + @param Offset The starting byte offset to read from
> > + @param BufferSize Size of Buffer
> > + @param Buffer Buffer containing read data
> > +
> > + @retval EFI_SUCCESS The data was read correctly from the device.
> > + @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
> > + @retval EFI_NO_MEDIA There is no media in the device.
> > + @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
> > + @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
> > + valid for the device.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashDiskIoReadDisk (
> > + IN EFI_DISK_IO_PROTOCOL *This,
> > + IN UINT32 MediaId,
> > + IN UINT64 DiskOffset,
> > + IN UINTN BufferSize,
> > + OUT VOID *Buffer
> > + )
> > +{
> > + NOR_FLASH_INSTANCE *Instance;
> > + UINT32 BlockSize;
> > + UINT32 BlockOffset;
> > + EFI_LBA Lba;
> > +
> > + Instance = INSTANCE_FROM_DISKIO_THIS (This);
> > +
> > + if (MediaId != Instance->Media.MediaId) {
> > + return EFI_MEDIA_CHANGED;
> > + }
> > +
> > + BlockSize = Instance->Media.BlockSize;
> > + Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
> > +
> > + return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer);
> > +}
> > +
> > +/**
> > + Writes a specified number of bytes to a device.
> > +
> > + @param This Indicates a pointer to the calling context.
> > + @param MediaId ID of the medium to be written.
> > + @param Offset The starting byte offset on the logical block I/O device to write.
> > + @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
> > + @param Buffer A pointer to the buffer containing the data to be written.
> > +
> > + @retval EFI_SUCCESS The data was written correctly to the device.
> > + @retval EFI_WRITE_PROTECTED The device can not be written to.
> > + @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
> > + @retval EFI_NO_MEDIA There is no media in the device.
> > + @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
> > + @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
> > + valid for the device.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashDiskIoWriteDisk (
> > + IN EFI_DISK_IO_PROTOCOL *This,
> > + IN UINT32 MediaId,
> > + IN UINT64 DiskOffset,
> > + IN UINTN BufferSize,
> > + IN VOID *Buffer
> > + )
> > +{
> > + NOR_FLASH_INSTANCE *Instance;
> > + UINT32 BlockSize;
> > + UINT32 BlockOffset;
> > + EFI_LBA Lba;
> > + UINTN RemainingBytes;
> > + UINTN WriteSize;
> > + EFI_STATUS Status;
> > +
> > + Instance = INSTANCE_FROM_DISKIO_THIS (This);
> > +
> > + if (MediaId != Instance->Media.MediaId) {
> > + return EFI_MEDIA_CHANGED;
> > + }
> > +
> > + BlockSize = Instance->Media.BlockSize;
> > + Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
> > +
> > + RemainingBytes = BufferSize;
> > +
> > + // Write either all the remaining bytes, or the number of bytes that bring
> > + // us up to a block boundary, whichever is less.
> > + // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next
> > + // block boundary (even if it is already on one).
> > + WriteSize = MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) - DiskOffset);
> > +
> > + do {
> > + if (WriteSize == BlockSize) {
> > + // Write a full block
> > + Status = NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize / sizeof (UINT32));
> > + } else {
> > + // Write a partial block
> > + Status = NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &WriteSize, Buffer);
> > + }
> > +
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // Now continue writing either all the remaining bytes or single blocks.
> > + RemainingBytes -= WriteSize;
> > + Buffer = (UINT8 *)Buffer + WriteSize;
> > + Lba++;
> > + BlockOffset = 0;
> > + WriteSize = MIN (RemainingBytes, BlockSize);
> > + } while (RemainingBytes);
> > +
> > + return Status;
> > +}
> > +
> > +EFI_STATUS
> > +NorFlashReset (
> > + IN NOR_FLASH_INSTANCE *Instance
> > + )
> > +{
> > + // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
> > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + Fixup internal data so that EFI can be call in virtual mode.
> > + Call the passed in Child Notify event and convert any pointers in
> > + lib to virtual mode.
> > +
> > + @param[in] Event The Event that is being processed
> > + @param[in] Context Event Context
> > +**/
> > +VOID
> > +EFIAPI
> > +NorFlashVirtualNotifyEvent (
> > + IN EFI_EVENT Event,
> > + IN VOID *Context
> > + )
> > +{
> > + UINTN Index;
> > +
> > + for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress);
> > +
> > + // Convert BlockIo protocol
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
> > +
> > + // Convert Fvb
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Read);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Write);
> > +
> > + if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
> > + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowBuffer);
> > + }
> > + }
> > +
> > + return;
> > +}
> > diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
> > new file mode 100644
> > index 000000000000..9d4732c6905a
> > --- /dev/null
> > +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
> > @@ -0,0 +1,123 @@
> > +/** @file NorFlashBlockIoDxe.c
> > +
> > + Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
> > +
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +
> > +#include "NorFlash.h"
> > +
> > +//
> > +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashBlockIoReset (
> > + IN EFI_BLOCK_IO_PROTOCOL *This,
> > + IN BOOLEAN ExtendedVerification
> > + )
> > +{
> > + NOR_FLASH_INSTANCE *Instance;
> > +
> > + Instance = INSTANCE_FROM_BLKIO_THIS (This);
> > +
> > + DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
> > +
> > + return NorFlashReset (Instance);
> > +}
> > +
> > +//
> > +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashBlockIoReadBlocks (
> > + IN EFI_BLOCK_IO_PROTOCOL *This,
> > + IN UINT32 MediaId,
> > + IN EFI_LBA Lba,
> > + IN UINTN BufferSizeInBytes,
> > + OUT VOID *Buffer
> > + )
> > +{
> > + NOR_FLASH_INSTANCE *Instance;
> > + EFI_STATUS Status;
> > + EFI_BLOCK_IO_MEDIA *Media;
> > +
> > + if (This == NULL) {
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + Instance = INSTANCE_FROM_BLKIO_THIS (This);
> > + Media = This->Media;
> > +
> > + DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, BufferSizeInBytes, Buffer));
> > +
> > + if (!Media) {
> > + Status = EFI_INVALID_PARAMETER;
> > + } else if (!Media->MediaPresent) {
> > + Status = EFI_NO_MEDIA;
> > + } else if (Media->MediaId != MediaId) {
> > + Status = EFI_MEDIA_CHANGED;
> > + } else if ((Media->IoAlign > 2) && (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) {
> > + Status = EFI_INVALID_PARAMETER;
> > + } else {
> > + Status = NorFlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
> > + }
> > +
> > + return Status;
> > +}
> > +
> > +//
> > +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashBlockIoWriteBlocks (
> > + IN EFI_BLOCK_IO_PROTOCOL *This,
> > + IN UINT32 MediaId,
> > + IN EFI_LBA Lba,
> > + IN UINTN BufferSizeInBytes,
> > + IN VOID *Buffer
> > + )
> > +{
> > + NOR_FLASH_INSTANCE *Instance;
> > + EFI_STATUS Status;
> > +
> > + Instance = INSTANCE_FROM_BLKIO_THIS (This);
> > +
> > + DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes, BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
> > +
> > + if ( !This->Media->MediaPresent ) {
> > + Status = EFI_NO_MEDIA;
> > + } else if ( This->Media->MediaId != MediaId ) {
> > + Status = EFI_MEDIA_CHANGED;
> > + } else if ( This->Media->ReadOnly ) {
> > + Status = EFI_WRITE_PROTECTED;
> > + } else {
> > + Status = NorFlashWriteBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
> > + }
> > +
> > + return Status;
> > +}
> > +
> > +//
> > +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashBlockIoFlushBlocks (
> > + IN EFI_BLOCK_IO_PROTOCOL *This
> > + )
> > +{
> > + // No Flush required for the NOR Flash driver
> > + // because cache operations are not permitted.
> > +
> > + DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
> > +
> > + // Nothing to do so just return without error
> > + return EFI_SUCCESS;
> > +}
> > diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
> > new file mode 100644
> > index 000000000000..f7b92de21a57
> > --- /dev/null
> > +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashDxe.c
> > @@ -0,0 +1,506 @@
> > +/** @file NorFlashDxe.c
> > +
> > + Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
> > +
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/UefiLib.h>
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/MemoryAllocationLib.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +#include <Library/PcdLib.h>
> > +#include <Library/HobLib.h>
> > +#include <Library/DxeServicesTableLib.h>
> > +
> > +#include "NorFlash.h"
> > +
> > +STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
> > +
> > +//
> > +// Global variable declarations
> > +//
> > +NOR_FLASH_INSTANCE **mNorFlashInstances;
> > +UINT32 mNorFlashDeviceCount;
> > +UINTN mFlashNvStorageVariableBase;
> > +EFI_EVENT mFvbVirtualAddrChangeEvent;
> > +
> > +NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
> > + NOR_FLASH_SIGNATURE, // Signature
> > + NULL, // Handle ... NEED TO BE FILLED
> > +
> > + 0, // DeviceBaseAddress ... NEED TO BE FILLED
> > + 0, // RegionBaseAddress ... NEED TO BE FILLED
> > + 0, // Size ... NEED TO BE FILLED
> > + 0, // StartLba
> > +
> > + {
> > + EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision
> > + NULL, // Media ... NEED TO BE FILLED
> > + NorFlashBlockIoReset, // Reset;
> > + NorFlashBlockIoReadBlocks, // ReadBlocks
> > + NorFlashBlockIoWriteBlocks, // WriteBlocks
> > + NorFlashBlockIoFlushBlocks // FlushBlocks
> > + }, // BlockIoProtocol
> > +
> > + {
> > + 0, // MediaId ... NEED TO BE FILLED
> > + FALSE, // RemovableMedia
> > + TRUE, // MediaPresent
> > + FALSE, // LogicalPartition
> > + FALSE, // ReadOnly
> > + FALSE, // WriteCaching;
> > + 0, // BlockSize ... NEED TO BE FILLED
> > + 4, // IoAlign
> > + 0, // LastBlock ... NEED TO BE FILLED
> > + 0, // LowestAlignedLba
> > + 1, // LogicalBlocksPerPhysicalBlock
> > + }, // Media;
> > +
> > + {
> > + EFI_DISK_IO_PROTOCOL_REVISION, // Revision
> > + NorFlashDiskIoReadDisk, // ReadDisk
> > + NorFlashDiskIoWriteDisk // WriteDisk
> > + },
> > +
> > + {
> > + FvbGetAttributes, // GetAttributes
> > + FvbSetAttributes, // SetAttributes
> > + FvbGetPhysicalAddress, // GetPhysicalAddress
> > + FvbGetBlockSize, // GetBlockSize
> > + FvbRead, // Read
> > + FvbWrite, // Write
> > + FvbEraseBlocks, // EraseBlocks
> > + NULL, // ParentHandle
> > + }, // FvbProtoccol;
> > + NULL, // ShadowBuffer
> > + {
> > + {
> > + {
> > + HARDWARE_DEVICE_PATH,
> > + HW_VENDOR_DP,
> > + {
> > + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),
> > + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)
> > + }
> > + },
> > + { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
> > + }, // GUID ... NEED TO BE FILLED
> > + },
> > + 0, // Index
> > + {
> > + END_DEVICE_PATH_TYPE,
> > + END_ENTIRE_DEVICE_PATH_SUBTYPE,
> > + { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
> > + }
> > + } // DevicePath
> > +};
> > +
> > +EFI_STATUS
> > +NorFlashCreateInstance (
> > + IN UINTN NorFlashDeviceBase,
> > + IN UINTN NorFlashRegionBase,
> > + IN UINTN NorFlashSize,
> > + IN UINT32 Index,
> > + IN UINT32 BlockSize,
> > + IN BOOLEAN SupportFvb,
> > + OUT NOR_FLASH_INSTANCE **NorFlashInstance
> > + )
> > +{
> > + EFI_STATUS Status;
> > + NOR_FLASH_INSTANCE *Instance;
> > +
> > + ASSERT (NorFlashInstance != NULL);
> > +
> > + Instance = AllocateRuntimeCopyPool (sizeof (NOR_FLASH_INSTANCE), &mNorFlashInstanceTemplate);
> > + if (Instance == NULL) {
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + Instance->DeviceBaseAddress = NorFlashDeviceBase;
> > + Instance->RegionBaseAddress = NorFlashRegionBase;
> > + Instance->Size = NorFlashSize;
> > +
> > + Instance->BlockIoProtocol.Media = &Instance->Media;
> > + Instance->Media.MediaId = Index;
> > + Instance->Media.BlockSize = BlockSize;
> > + Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
> > +
> > + CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
> > + Instance->DevicePath.Index = (UINT8)Index;
> > +
> > + Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);
> > + if (Instance->ShadowBuffer == NULL) {
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + if (SupportFvb) {
> > + NorFlashFvbInitialize (Instance);
> > +
> > + Status = gBS->InstallMultipleProtocolInterfaces (
> > + &Instance->Handle,
> > + &gEfiDevicePathProtocolGuid,
> > + &Instance->DevicePath,
> > + &gEfiBlockIoProtocolGuid,
> > + &Instance->BlockIoProtocol,
> > + &gEfiFirmwareVolumeBlockProtocolGuid,
> > + &Instance->FvbProtocol,
> > + NULL
> > + );
> > + if (EFI_ERROR (Status)) {
> > + FreePool (Instance);
> > + return Status;
> > + }
> > + } else {
> > + Status = gBS->InstallMultipleProtocolInterfaces (
> > + &Instance->Handle,
> > + &gEfiDevicePathProtocolGuid,
> > + &Instance->DevicePath,
> > + &gEfiBlockIoProtocolGuid,
> > + &Instance->BlockIoProtocol,
> > + &gEfiDiskIoProtocolGuid,
> > + &Instance->DiskIoProtocol,
> > + NULL
> > + );
> > + if (EFI_ERROR (Status)) {
> > + FreePool (Instance);
> > + return Status;
> > + }
> > + }
> > +
> > + *NorFlashInstance = Instance;
> > + return Status;
> > +}
> > +
> > +/**
> > + * This function unlock and erase an entire NOR Flash block.
> > + **/
> > +EFI_STATUS
> > +NorFlashUnlockAndEraseSingleBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN UINTN BlockAddress
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINTN Index;
> > + EFI_TPL OriginalTPL;
> > +
> > + if (!EfiAtRuntime ()) {
> > + // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
> > + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> > + } else {
> > + // This initialization is only to prevent the compiler to complain about the
> > + // use of uninitialized variables
> > + OriginalTPL = TPL_HIGH_LEVEL;
> > + }
> > +
> > + Index = 0;
> > + // The block erase might fail a first time (SW bug ?). Retry it ...
> > + do {
> > + // Unlock the block if we have to
> > + Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
> > + if (EFI_ERROR (Status)) {
> > + break;
> > + }
> > +
> > + Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
> > + Index++;
> > + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
> > +
> > + if (Index == NOR_FLASH_ERASE_RETRY) {
> > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));
> > + }
> > +
> > + if (!EfiAtRuntime ()) {
> > + // Interruptions can resume.
> > + gBS->RestoreTPL (OriginalTPL);
> > + }
> > +
> > + return Status;
> > +}
> > +
> > +EFI_STATUS
> > +NorFlashWriteFullBlock (
> > + IN NOR_FLASH_INSTANCE *Instance,
> > + IN EFI_LBA Lba,
> > + IN UINT32 *DataBuffer,
> > + IN UINT32 BlockSizeInWords
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINTN WordAddress;
> > + UINT32 WordIndex;
> > + UINTN BufferIndex;
> > + UINTN BlockAddress;
> > + UINTN BuffersInBlock;
> > + UINTN RemainingWords;
> > + EFI_TPL OriginalTPL;
> > + UINTN Cnt;
> > +
> > + Status = EFI_SUCCESS;
> > +
> > + // Get the physical address of the block
> > + BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4);
> > +
> > + // Start writing from the first address at the start of the block
> > + WordAddress = BlockAddress;
> > +
> > + if (!EfiAtRuntime ()) {
> > + // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
> > + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> > + } else {
> > + // This initialization is only to prevent the compiler to complain about the
> > + // use of uninitialized variables
> > + OriginalTPL = TPL_HIGH_LEVEL;
> > + }
> > +
> > + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
> > + goto EXIT;
> > + }
> > +
> > + // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
> > +
> > + // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero
> > + if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) {
> > + // First, break the entire block into buffer-sized chunks.
> > + BuffersInBlock = (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;
> > +
> > + // Then feed each buffer chunk to the NOR Flash
> > + // If a buffer does not contain any data, don't write it.
> > + for (BufferIndex = 0;
> > + BufferIndex < BuffersInBlock;
> > + BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
> > + )
> > + {
> > + // Check the buffer to see if it contains any data (not set all 1s).
> > + for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {
> > + if (~DataBuffer[Cnt] != 0 ) {
> > + // Some data found, write the buffer.
> > + Status = NorFlashWriteBuffer (
> > + Instance,
> > + WordAddress,
> > + P30_MAX_BUFFER_SIZE_IN_BYTES,
> > + DataBuffer
> > + );
> > + if (EFI_ERROR (Status)) {
> > + goto EXIT;
> > + }
> > +
> > + break;
> > + }
> > + }
> > + }
> > +
> > + // Finally, finish off any remaining words that are less than the maximum size of the buffer
> > + RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
> > +
> > + if (RemainingWords != 0) {
> > + Status = NorFlashWriteBuffer (Instance, WordAddress, (RemainingWords * 4), DataBuffer);
> > + if (EFI_ERROR (Status)) {
> > + goto EXIT;
> > + }
> > + }
> > + } else {
> > + // For now, use the single word programming algorithm
> > + // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,
> > + // i.e. which ends in the range 0x......01 - 0x......7F.
> > + for (WordIndex = 0; WordIndex < BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4) {
> > + Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);
> > + if (EFI_ERROR (Status)) {
> > + goto EXIT;
> > + }
> > + }
> > + }
> > +
> > +EXIT:
> > + if (!EfiAtRuntime ()) {
> > + // Interruptions can resume.
> > + gBS->RestoreTPL (OriginalTPL);
> > + }
> > +
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
> > + }
> > +
> > + return Status;
> > +}
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashInitialise (
> > + IN EFI_HANDLE ImageHandle,
> > + IN EFI_SYSTEM_TABLE *SystemTable
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT32 Index;
> > + NOR_FLASH_DESCRIPTION *NorFlashDevices;
> > + BOOLEAN ContainVariableStorage;
> > +
> > + Status = NorFlashPlatformInitialization ();
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to initialize Nor Flash devices\n"));
> > + return Status;
> > + }
> > +
> > + Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to get Nor Flash devices\n"));
> > + return Status;
> > + }
> > +
> > + mNorFlashInstances = AllocateRuntimePool (sizeof (NOR_FLASH_INSTANCE *) * mNorFlashDeviceCount);
> > +
> > + for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
> > + // Check if this NOR Flash device contain the variable storage region
> > +
> > + if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
> > + ContainVariableStorage =
> > + (NorFlashDevices[Index].RegionBaseAddress <= PcdGet64 (PcdFlashNvStorageVariableBase64)) &&
> > + (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvStorageVariableSize) <=
> > + NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
> > + } else {
> > + ContainVariableStorage =
> > + (NorFlashDevices[Index].RegionBaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) &&
> > + (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize) <=
> > + NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
> > + }
> > +
> > + Status = NorFlashCreateInstance (
> > + NorFlashDevices[Index].DeviceBaseAddress,
> > + NorFlashDevices[Index].RegionBaseAddress,
> > + NorFlashDevices[Index].Size,
> > + Index,
> > + NorFlashDevices[Index].BlockSize,
> > + ContainVariableStorage,
> > + &mNorFlashInstances[Index]
> > + );
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n", Index));
> > + }
> > + }
> > +
> > + //
> > + // Register for the virtual address change event
> > + //
> > + Status = gBS->CreateEventEx (
> > + EVT_NOTIFY_SIGNAL,
> > + TPL_NOTIFY,
> > + NorFlashVirtualNotifyEvent,
> > + NULL,
> > + &gEfiEventVirtualAddressChangeGuid,
> > + &mNorFlashVirtualAddrChangeEvent
> > + );
> > + ASSERT_EFI_ERROR (Status);
> > +
> > + return Status;
> > +}
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +NorFlashFvbInitialize (
> > + IN NOR_FLASH_INSTANCE *Instance
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT32 FvbNumLba;
> > + EFI_BOOT_MODE BootMode;
> > + UINTN RuntimeMmioRegionSize;
> > +
> > + DEBUG ((DEBUG_BLKIO, "NorFlashFvbInitialize\n"));
> > + ASSERT ((Instance != NULL));
> > +
> > + //
> > + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
> > + //
> > +
> > + // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;
> > + // even if we only use the small block region at the top of the NOR Flash.
> > + // The reason is when the NOR Flash memory is set into program mode, the command
> > + // is written as the base of the flash region (ie: Instance->DeviceBaseAddress)
> > + RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
> > +
> > + Status = gDS->AddMemorySpace (
> > + EfiGcdMemoryTypeMemoryMappedIo,
> > + Instance->DeviceBaseAddress,
> > + RuntimeMmioRegionSize,
> > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
> > + );
> > + ASSERT_EFI_ERROR (Status);
> > +
> > + Status = gDS->SetMemorySpaceAttributes (
> > + Instance->DeviceBaseAddress,
> > + RuntimeMmioRegionSize,
> > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
> > + );
> > + ASSERT_EFI_ERROR (Status);
> > +
> > + mFlashNvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
> > + PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);
> > +
> > + // Set the index of the first LBA for the FVB
> > + Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->Media.BlockSize;
> > +
> > + BootMode = GetBootModeHob ();
> > + if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
> > + Status = EFI_INVALID_PARAMETER;
> > + } else {
> > + // Determine if there is a valid header at the beginning of the NorFlash
> > + Status = ValidateFvHeader (Instance);
> > + }
> > +
> > + // Install the Default FVB header if required
> > + if (EFI_ERROR (Status)) {
> > + // There is no valid header, so time to install one.
> > + DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
> > + DEBUG ((
> > + DEBUG_INFO,
> > + "%a: Installing a correct one for this volume.\n",
> > + __FUNCTION__
> > + ));
> > +
> > + // Erase all the NorFlash that is reserved for variable storage
> > + FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
> > +
> > + Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // Install all appropriate headers
> > + Status = InitializeFvAndVariableStoreHeaders (Instance);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > + }
> > +
> > + //
> > + // The driver implementing the variable read service can now be dispatched;
> > + // the varstore headers are in place.
> > + //
> > + Status = gBS->InstallProtocolInterface (
> > + &gImageHandle,
> > + &gEdkiiNvVarStoreFormattedGuid,
> > + EFI_NATIVE_INTERFACE,
> > + NULL
> > + );
> > + ASSERT_EFI_ERROR (Status);
> > +
> > + //
> > + // Register for the virtual address change event
> > + //
> > + Status = gBS->CreateEventEx (
> > + EVT_NOTIFY_SIGNAL,
> > + TPL_NOTIFY,
> > + FvbVirtualNotifyEvent,
> > + NULL,
> > + &gEfiEventVirtualAddressChangeGuid,
> > + &mFvbVirtualAddrChangeEvent
> > + );
> > + ASSERT_EFI_ERROR (Status);
> > +
> > + return Status;
> > +}
> > diff --git a/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c b/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
> > new file mode 100644
> > index 000000000000..0767581308d2
> > --- /dev/null
> > +++ b/OvmfPkg/Drivers/NorFlashDxe/NorFlashFvb.c
> > @@ -0,0 +1,777 @@
> > +/*++ @file NorFlashFvbDxe.c
> > +
> > + Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
> > +
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > + --*/
> > +
> > +#include <PiDxe.h>
> > +
> > +#include <Library/PcdLib.h>
> > +#include <Library/BaseLib.h>
> > +#include <Library/UefiLib.h>
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/MemoryAllocationLib.h>
> > +
> > +#include <Guid/VariableFormat.h>
> > +#include <Guid/SystemNvDataGuid.h>
> > +#include <Guid/NvVarStoreFormatted.h>
> > +
> > +#include "NorFlash.h"
> > +
> > +extern UINTN mFlashNvStorageVariableBase;
> > +///
> > +/// The Firmware Volume Block Protocol is the low-level interface
> > +/// to a firmware volume. File-level access to a firmware volume
> > +/// should not be done using the Firmware Volume Block Protocol.
> > +/// Normal access to a firmware volume must use the Firmware
> > +/// Volume Protocol. Typically, only the file system driver that
> > +/// produces the Firmware Volume Protocol will bind to the
> > +/// Firmware Volume Block Protocol.
> > +///
> > +
> > +/**
> > + Initialises the FV Header and Variable Store Header
> > + to support variable operations.
> > +
> > + @param[in] Ptr - Location to initialise the headers
> > +
> > +**/
> > +EFI_STATUS
> > +InitializeFvAndVariableStoreHeaders (
> > + IN NOR_FLASH_INSTANCE *Instance
> > + )
> > +{
> > + EFI_STATUS Status;
> > + VOID *Headers;
> > + UINTN HeadersLength;
> > + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
> > + VARIABLE_STORE_HEADER *VariableStoreHeader;
> > + UINT32 NvStorageFtwSpareSize;
> > + UINT32 NvStorageFtwWorkingSize;
> > + UINT32 NvStorageVariableSize;
> > + UINT64 NvStorageFtwSpareBase;
> > + UINT64 NvStorageFtwWorkingBase;
> > + UINT64 NvStorageVariableBase;
> > +
> > + HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + sizeof (VARIABLE_STORE_HEADER);
> > + Headers = AllocateZeroPool (HeadersLength);
> > +
> > + NvStorageFtwWorkingSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
> > + NvStorageFtwSpareSize = PcdGet32 (PcdFlashNvStorageFtwSpareSize);
> > + NvStorageVariableSize = PcdGet32 (PcdFlashNvStorageVariableSize);
> > +
> > + NvStorageFtwSpareBase = (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) != 0) ?
> > + PcdGet64 (PcdFlashNvStorageFtwSpareBase64) : PcdGet32 (PcdFlashNvStorageFtwSpareBase);
> > + NvStorageFtwWorkingBase = (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) != 0) ?
> > + PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) : PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
> > + NvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
> > + PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);
> > +
> > + // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
> > + if ((NvStorageVariableBase + NvStorageVariableSize) != NvStorageFtwWorkingBase) {
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: NvStorageFtwWorkingBase is not contiguous with NvStorageVariableBase region\n",
> > + __FUNCTION__
> > + ));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + if ((NvStorageFtwWorkingBase + NvStorageFtwWorkingSize) != NvStorageFtwSpareBase) {
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: NvStorageFtwSpareBase is not contiguous with NvStorageFtwWorkingBase region\n",
> > + __FUNCTION__
> > + ));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + // Check if the size of the area is at least one block size
> > + if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->Media.BlockSize <= 0)) {
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n",
> > + __FUNCTION__,
> > + NvStorageVariableSize
> > + ));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->Media.BlockSize <= 0)) {
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n",
> > + __FUNCTION__,
> > + NvStorageFtwWorkingSize
> > + ));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->Media.BlockSize <= 0)) {
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n",
> > + __FUNCTION__,
> > + NvStorageFtwSpareSize
> > + ));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + // Ensure the Variable area Base Addresses are aligned on a block size boundaries
> > + if ((NvStorageVariableBase % Instance->Media.BlockSize != 0) ||
> > + (NvStorageFtwWorkingBase % Instance->Media.BlockSize != 0) ||
> > + (NvStorageFtwSpareBase % Instance->Media.BlockSize != 0))
> > + {
> > + DEBUG ((DEBUG_ERROR, "%a: NvStorage Base addresses must be aligned to block size boundaries", __FUNCTION__));
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + //
> > + // EFI_FIRMWARE_VOLUME_HEADER
> > + //
> > + FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers;
> > + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
> > + FirmwareVolumeHeader->FvLength =
> > + PcdGet32 (PcdFlashNvStorageVariableSize) +
> > + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
> > + PcdGet32 (PcdFlashNvStorageFtwSpareSize);
> > + FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
> > + FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2)(
> > + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
> > + EFI_FVB2_READ_STATUS | // Reads are currently enabled
> > + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
> > + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
> > + EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
> > + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
> > + EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
> > + );
> > + FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY);
> > + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
> > + FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
> > + FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize;
> > + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
> > + FirmwareVolumeHeader->BlockMap[1].Length = 0;
> > + FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength);
> > +
> > + //
> > + // VARIABLE_STORE_HEADER
> > + //
> > + VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
> > + CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
> > + VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
> > + VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
> > + VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
> > +
> > + // Install the combined super-header in the NorFlash
> > + Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
> > +
> > + FreePool (Headers);
> > + return Status;
> > +}
> > +
> > +/**
> > + Check the integrity of firmware volume header.
> > +
> > + @param[in] FwVolHeader - A pointer to a firmware volume header
> > +
> > + @retval EFI_SUCCESS - The firmware volume is consistent
> > + @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
> > +
> > +**/
> > +EFI_STATUS
> > +ValidateFvHeader (
> > + IN NOR_FLASH_INSTANCE *Instance
> > + )
> > +{
> > + UINT16 Checksum;
> > + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
> > + VARIABLE_STORE_HEADER *VariableStoreHeader;
> > + UINTN VariableStoreLength;
> > + UINTN FvLength;
> > +
> > + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress;
> > +
> > + FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
> > + PcdGet32 (PcdFlashNvStorageFtwSpareSize);
> > +
> > + //
> > + // Verify the header revision, header signature, length
> > + // Length of FvBlock cannot be 2**64-1
> > + // HeaderLength cannot be an odd number
> > + //
> > + if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
> > + || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
> > + || (FwVolHeader->FvLength != FvLength)
> > + )
> > + {
> > + DEBUG ((
> > + DEBUG_INFO,
> > + "%a: No Firmware Volume header present\n",
> > + __FUNCTION__
> > + ));
> > + return EFI_NOT_FOUND;
> > + }
> > +
> > + // Check the Firmware Volume Guid
> > + if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
> > + DEBUG ((
> > + DEBUG_INFO,
> > + "%a: Firmware Volume Guid non-compatible\n",
> > + __FUNCTION__
> > + ));
> > + return EFI_NOT_FOUND;
> > + }
> > +
> > + // Verify the header checksum
> > + Checksum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength);
> > + if (Checksum != 0) {
> > + DEBUG ((
> > + DEBUG_INFO,
> > + "%a: FV checksum is invalid (Checksum:0x%X)\n",
> > + __FUNCTION__,
> > + Checksum
> > + ));
> > + return EFI_NOT_FOUND;
> > + }
> > +
> > + VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)FwVolHeader + FwVolHeader->HeaderLength);
> > +
> > + // Check the Variable Store Guid
> > + if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
> > + !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid))
> > + {
> > + DEBUG ((
> > + DEBUG_INFO,
> > + "%a: Variable Store Guid non-compatible\n",
> > + __FUNCTION__
> > + ));
> > + return EFI_NOT_FOUND;
> > + }
> > +
> > + VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
> > + if (VariableStoreHeader->Size != VariableStoreLength) {
> > + DEBUG ((
> > + DEBUG_INFO,
> > + "%a: Variable Store Length does not match\n",
> > + __FUNCTION__
> > + ));
> > + return EFI_NOT_FOUND;
> > + }
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + The GetAttributes() function retrieves the attributes and
> > + current settings of the block.
> > +
> > + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> > +
> > + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
> > + current settings are returned.
> > + Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
> > +
> > + @retval EFI_SUCCESS The firmware volume attributes were returned.
> > +
> > + **/
> > +EFI_STATUS
> > +EFIAPI
> > +FvbGetAttributes (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + OUT EFI_FVB_ATTRIBUTES_2 *Attributes
> > + )
> > +{
> > + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
> > + NOR_FLASH_INSTANCE *Instance;
> > +
> > + Instance = INSTANCE_FROM_FVB_THIS (This);
> > +
> > + FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2)(
> > +
> > + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
> > + EFI_FVB2_READ_STATUS | // Reads are currently enabled
> > + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
> > + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
> > + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
> > +
> > + );
> > +
> > + // Check if it is write protected
> > + if (Instance->Media.ReadOnly != TRUE) {
> > + FlashFvbAttributes = FlashFvbAttributes |
> > + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
> > + EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
> > + }
> > +
> > + *Attributes = FlashFvbAttributes;
> > +
> > + DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + The SetAttributes() function sets configurable firmware volume attributes
> > + and returns the new settings of the firmware volume.
> > +
> > +
> > + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> > +
> > + @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2
> > + that contains the desired firmware volume settings.
> > + On successful return, it contains the new settings of
> > + the firmware volume.
> > + Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
> > +
> > + @retval EFI_SUCCESS The firmware volume attributes were returned.
> > +
> > + @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities
> > + as declared in the firmware volume header.
> > +
> > + **/
> > +EFI_STATUS
> > +EFIAPI
> > +FvbSetAttributes (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
> > + )
> > +{
> > + DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n", *Attributes));
> > + return EFI_UNSUPPORTED;
> > +}
> > +
> > +/**
> > + The GetPhysicalAddress() function retrieves the base address of
> > + a memory-mapped firmware volume. This function should be called
> > + only for memory-mapped firmware volumes.
> > +
> > + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> > +
> > + @param Address Pointer to a caller-allocated
> > + EFI_PHYSICAL_ADDRESS that, on successful
> > + return from GetPhysicalAddress(), contains the
> > + base address of the firmware volume.
> > +
> > + @retval EFI_SUCCESS The firmware volume base address was returned.
> > +
> > + @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
> > +
> > + **/
> > +EFI_STATUS
> > +EFIAPI
> > +FvbGetPhysicalAddress (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + OUT EFI_PHYSICAL_ADDRESS *Address
> > + )
> > +{
> > + NOR_FLASH_INSTANCE *Instance;
> > +
> > + Instance = INSTANCE_FROM_FVB_THIS (This);
> > +
> > + DEBUG ((DEBUG_BLKIO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->RegionBaseAddress));
> > +
> > + ASSERT (Address != NULL);
> > +
> > + *Address = mFlashNvStorageVariableBase;
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + The GetBlockSize() function retrieves the size of the requested
> > + block. It also returns the number of additional blocks with
> > + the identical size. The GetBlockSize() function is used to
> > + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
> > +
> > +
> > + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> > +
> > + @param Lba Indicates the block for which to return the size.
> > +
> > + @param BlockSize Pointer to a caller-allocated UINTN in which
> > + the size of the block is returned.
> > +
> > + @param NumberOfBlocks Pointer to a caller-allocated UINTN in
> > + which the number of consecutive blocks,
> > + starting with Lba, is returned. All
> > + blocks in this range have a size of
> > + BlockSize.
> > +
> > +
> > + @retval EFI_SUCCESS The firmware volume base address was returned.
> > +
> > + @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
> > +
> > + **/
> > +EFI_STATUS
> > +EFIAPI
> > +FvbGetBlockSize (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + IN EFI_LBA Lba,
> > + OUT UINTN *BlockSize,
> > + OUT UINTN *NumberOfBlocks
> > + )
> > +{
> > + EFI_STATUS Status;
> > + NOR_FLASH_INSTANCE *Instance;
> > +
> > + Instance = INSTANCE_FROM_FVB_THIS (This);
> > +
> > + DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->Media.BlockSize, Instance->Media.LastBlock));
> > +
> > + if (Lba > Instance->Media.LastBlock) {
> > + DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock));
> > + Status = EFI_INVALID_PARAMETER;
> > + } else {
> > + // This is easy because in this platform each NorFlash device has equal sized blocks.
> > + *BlockSize = (UINTN)Instance->Media.BlockSize;
> > + *NumberOfBlocks = (UINTN)(Instance->Media.LastBlock - Lba + 1);
> > +
> > + DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks));
> > +
> > + Status = EFI_SUCCESS;
> > + }
> > +
> > + return Status;
> > +}
> > +
> > +/**
> > + Reads the specified number of bytes into a buffer from the specified block.
> > +
> > + The Read() function reads the requested number of bytes from the
> > + requested block and stores them in the provided buffer.
> > + Implementations should be mindful that the firmware volume
> > + might be in the ReadDisabled state. If it is in this state,
> > + the Read() function must return the status code
> > + EFI_ACCESS_DENIED without modifying the contents of the
> > + buffer. The Read() function must also prevent spanning block
> > + boundaries. If a read is requested that would span a block
> > + boundary, the read must read up to the boundary but not
> > + beyond. The output parameter NumBytes must be set to correctly
> > + indicate the number of bytes actually read. The caller must be
> > + aware that a read may be partially completed.
> > +
> > + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> > +
> > + @param Lba The starting logical block index from which to read.
> > +
> > + @param Offset Offset into the block at which to begin reading.
> > +
> > + @param NumBytes Pointer to a UINTN.
> > + At entry, *NumBytes contains the total size of the buffer.
> > + At exit, *NumBytes contains the total number of bytes read.
> > +
> > + @param Buffer Pointer to a caller-allocated buffer that will be used
> > + to hold the data that is read.
> > +
> > + @retval EFI_SUCCESS The firmware volume was read successfully, and contents are
> > + in Buffer.
> > +
> > + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
> > + On output, NumBytes contains the total number of bytes
> > + returned in Buffer.
> > +
> > + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.
> > +
> > + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read.
> > +
> > + **/
> > +EFI_STATUS
> > +EFIAPI
> > +FvbRead (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN OUT UINTN *NumBytes,
> > + IN OUT UINT8 *Buffer
> > + )
> > +{
> > + EFI_STATUS TempStatus;
> > + UINTN BlockSize;
> > + NOR_FLASH_INSTANCE *Instance;
> > +
> > + Instance = INSTANCE_FROM_FVB_THIS (This);
> > +
> > + DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
> > +
> > + TempStatus = EFI_SUCCESS;
> > +
> > + // Cache the block size to avoid de-referencing pointers all the time
> > + BlockSize = Instance->Media.BlockSize;
> > +
> > + DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
> > +
> > + // The read must not span block boundaries.
> > + // We need to check each variable individually because adding two large values together overflows.
> > + if ((Offset >= BlockSize) ||
> > + (*NumBytes > BlockSize) ||
> > + ((Offset + *NumBytes) > BlockSize))
> > + {
> > + DEBUG ((DEBUG_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // We must have some bytes to read
> > + if (*NumBytes == 0) {
> > + return EFI_BAD_BUFFER_SIZE;
> > + }
> > +
> > + // Decide if we are doing full block reads or not.
> > + if (*NumBytes % BlockSize != 0) {
> > + TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer);
> > + if (EFI_ERROR (TempStatus)) {
> > + return EFI_DEVICE_ERROR;
> > + }
> > + } else {
> > + // Read NOR Flash data into shadow buffer
> > + TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer);
> > + if (EFI_ERROR (TempStatus)) {
> > + // Return one of the pre-approved error statuses
> > + return EFI_DEVICE_ERROR;
> > + }
> > + }
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + Writes the specified number of bytes from the input buffer to the block.
> > +
> > + The Write() function writes the specified number of bytes from
> > + the provided buffer to the specified block and offset. If the
> > + firmware volume is sticky write, the caller must ensure that
> > + all the bits of the specified range to write are in the
> > + EFI_FVB_ERASE_POLARITY state before calling the Write()
> > + function, or else the result will be unpredictable. This
> > + unpredictability arises because, for a sticky-write firmware
> > + volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
> > + state but cannot flip it back again. Before calling the
> > + Write() function, it is recommended for the caller to first call
> > + the EraseBlocks() function to erase the specified block to
> > + write. A block erase cycle will transition bits from the
> > + (NOT)EFI_FVB_ERASE_POLARITY state back to the
> > + EFI_FVB_ERASE_POLARITY state. Implementations should be
> > + mindful that the firmware volume might be in the WriteDisabled
> > + state. If it is in this state, the Write() function must
> > + return the status code EFI_ACCESS_DENIED without modifying the
> > + contents of the firmware volume. The Write() function must
> > + also prevent spanning block boundaries. If a write is
> > + requested that spans a block boundary, the write must store up
> > + to the boundary but not beyond. The output parameter NumBytes
> > + must be set to correctly indicate the number of bytes actually
> > + written. The caller must be aware that a write may be
> > + partially completed. All writes, partial or otherwise, must be
> > + fully flushed to the hardware before the Write() service
> > + returns.
> > +
> > + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> > +
> > + @param Lba The starting logical block index to write to.
> > +
> > + @param Offset Offset into the block at which to begin writing.
> > +
> > + @param NumBytes The pointer to a UINTN.
> > + At entry, *NumBytes contains the total size of the buffer.
> > + At exit, *NumBytes contains the total number of bytes actually written.
> > +
> > + @param Buffer The pointer to a caller-allocated buffer that contains the source for the write.
> > +
> > + @retval EFI_SUCCESS The firmware volume was written successfully.
> > +
> > + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
> > + On output, NumBytes contains the total number of bytes
> > + actually written.
> > +
> > + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
> > +
> > + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written.
> > +
> > +
> > + **/
> > +EFI_STATUS
> > +EFIAPI
> > +FvbWrite (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + IN EFI_LBA Lba,
> > + IN UINTN Offset,
> > + IN OUT UINTN *NumBytes,
> > + IN UINT8 *Buffer
> > + )
> > +{
> > + NOR_FLASH_INSTANCE *Instance;
> > +
> > + Instance = INSTANCE_FROM_FVB_THIS (This);
> > +
> > + return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset, NumBytes, Buffer);
> > +}
> > +
> > +/**
> > + Erases and initialises a firmware volume block.
> > +
> > + The EraseBlocks() function erases one or more blocks as denoted
> > + by the variable argument list. The entire parameter list of
> > + blocks must be verified before erasing any blocks. If a block is
> > + requested that does not exist within the associated firmware
> > + volume (it has a larger index than the last block of the
> > + firmware volume), the EraseBlocks() function must return the
> > + status code EFI_INVALID_PARAMETER without modifying the contents
> > + of the firmware volume. Implementations should be mindful that
> > + the firmware volume might be in the WriteDisabled state. If it
> > + is in this state, the EraseBlocks() function must return the
> > + status code EFI_ACCESS_DENIED without modifying the contents of
> > + the firmware volume. All calls to EraseBlocks() must be fully
> > + flushed to the hardware before the EraseBlocks() service
> > + returns.
> > +
> > + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
> > + instance.
> > +
> > + @param ... The variable argument list is a list of tuples.
> > + Each tuple describes a range of LBAs to erase
> > + and consists of the following:
> > + - An EFI_LBA that indicates the starting LBA
> > + - A UINTN that indicates the number of blocks to erase.
> > +
> > + The list is terminated with an EFI_LBA_LIST_TERMINATOR.
> > + For example, the following indicates that two ranges of blocks
> > + (5-7 and 10-11) are to be erased:
> > + EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
> > +
> > + @retval EFI_SUCCESS The erase request successfully completed.
> > +
> > + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
> > +
> > + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written.
> > + The firmware device may have been partially erased.
> > +
> > + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do
> > + not exist in the firmware volume.
> > +
> > + **/
> > +EFI_STATUS
> > +EFIAPI
> > +FvbEraseBlocks (
> > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> > + ...
> > + )
> > +{
> > + EFI_STATUS Status;
> > + VA_LIST Args;
> > + UINTN BlockAddress; // Physical address of Lba to erase
> > + EFI_LBA StartingLba; // Lba from which we start erasing
> > + UINTN NumOfLba; // Number of Lba blocks to erase
> > + NOR_FLASH_INSTANCE *Instance;
> > +
> > + Instance = INSTANCE_FROM_FVB_THIS (This);
> > +
> > + DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n"));
> > +
> > + Status = EFI_SUCCESS;
> > +
> > + // Detect WriteDisabled state
> > + if (Instance->Media.ReadOnly == TRUE) {
> > + // Firmware volume is in WriteDisabled state
> > + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"));
> > + return EFI_ACCESS_DENIED;
> > + }
> > +
> > + // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
> > +
> > + VA_START (Args, This);
> > + do {
> > + // Get the Lba from which we start erasing
> > + StartingLba = VA_ARG (Args, EFI_LBA);
> > +
> > + // Have we reached the end of the list?
> > + if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
> > + // Exit the while loop
> > + break;
> > + }
> > +
> > + // How many Lba blocks are we requested to erase?
> > + NumOfLba = VA_ARG (Args, UINTN);
> > +
> > + // All blocks must be within range
> > + DEBUG ((
> > + DEBUG_BLKIO,
> > + "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n",
> > + Instance->StartLba + StartingLba,
> > + (UINT64)NumOfLba,
> > + Instance->Media.LastBlock
> > + ));
> > + if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) {
> > + VA_END (Args);
> > + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
> > + Status = EFI_INVALID_PARAMETER;
> > + goto EXIT;
> > + }
> > + } while (TRUE);
> > +
> > + VA_END (Args);
> > +
> > + //
> > + // To get here, all must be ok, so start erasing
> > + //
> > + VA_START (Args, This);
> > + do {
> > + // Get the Lba from which we start erasing
> > + StartingLba = VA_ARG (Args, EFI_LBA);
> > +
> > + // Have we reached the end of the list?
> > + if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
> > + // Exit the while loop
> > + break;
> > + }
> > +
> > + // How many Lba blocks are we requested to erase?
> > + NumOfLba = VA_ARG (Args, UINTN);
> > +
> > + // Go through each one and erase it
> > + while (NumOfLba > 0) {
> > + // Get the physical address of Lba to erase
> > + BlockAddress = GET_NOR_BLOCK_ADDRESS (
> > + Instance->RegionBaseAddress,
> > + Instance->StartLba + StartingLba,
> > + Instance->Media.BlockSize
> > + );
> > +
> > + // Erase it
> > + DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress));
> > + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
> > + if (EFI_ERROR (Status)) {
> > + VA_END (Args);
> > + Status = EFI_DEVICE_ERROR;
> > + goto EXIT;
> > + }
> > +
> > + // Move to the next Lba
> > + StartingLba++;
> > + NumOfLba--;
> > + }
> > + } while (TRUE);
> > +
> > + VA_END (Args);
> > +
> > +EXIT:
> > + return Status;
> > +}
> > +
> > +/**
> > + Fixup internal data so that EFI can be call in virtual mode.
> > + Call the passed in Child Notify event and convert any pointers in
> > + lib to virtual mode.
> > +
> > + @param[in] Event The Event that is being processed
> > + @param[in] Context Event Context
> > +**/
> > +VOID
> > +EFIAPI
> > +FvbVirtualNotifyEvent (
> > + IN EFI_EVENT Event,
> > + IN VOID *Context
> > + )
> > +{
> > + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase);
> > + return;
> > +}
> > --
> > 2.25.1
> >
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver
2022-10-10 15:19 ` Sunil V L
@ 2022-10-10 15:29 ` Ard Biesheuvel
2022-10-10 16:05 ` Sunil V L
0 siblings, 1 reply; 43+ messages in thread
From: Ard Biesheuvel @ 2022-10-10 15:29 UTC (permalink / raw)
To: Sunil V L; +Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
On Mon, 10 Oct 2022 at 17:19, Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> On Mon, Oct 10, 2022 at 12:39:21PM +0200, Ard Biesheuvel wrote:
> > On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > >
> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
> > >
> > > RISC-V needs NorFlashDxe driver for qemu virt machine. The
> > > ArmPlatformPkg has this driver but migrating it to generic
> > > package like MdeModulePkg introduces circular dependencies.
> > > So, add a simplified version of the NorFlashDxe driver in
> > > OvmfPkg.
> > >
> >
> > So what is the difference between this simplified version and the old
> > version? And it is backed in QEMU by the same NOR flash emulation,
> > shouldn't we use this driver for ArmVirtQemu as well?
>
> I agree. If we can break the dependency on EmbeddedPkg due to
> NvVarStoreFormattedLib, then we can migrate to MdeModulePkg and all
> consumers can use the same driver which would be the best solution IMO.
>
> Could you please let me know why NvVarStoreFormattedLib is added
> in EmbeddedPkg instead of MdePkg or MdeModulePkg? Is it only for
> non-server class platforms? I don't see it doing much so not sure
> its use case.
>
I think that library as well as the definition of
gEdkiiNvVarStoreFormattedGuid should be moved to MdeModulePkg.
Then, we can look at moving NorFlashDxe in there as well.
But you haven't answered my question regarding how your version was simplified.
Note that there is some room for improvement in that driver in
relation to execution under KVM: switching between programming mode
and array mode involves setting up/tearing down the KVM memslot, and
currently, the driver is far from optimized when it comes to
minimizing the number of transitions between read mode and write mode.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver
2022-10-10 15:29 ` Ard Biesheuvel
@ 2022-10-10 16:05 ` Sunil V L
2022-10-10 16:16 ` Ard Biesheuvel
0 siblings, 1 reply; 43+ messages in thread
From: Sunil V L @ 2022-10-10 16:05 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
On Mon, Oct 10, 2022 at 05:29:15PM +0200, Ard Biesheuvel wrote:
> On Mon, 10 Oct 2022 at 17:19, Sunil V L <sunilvl@ventanamicro.com> wrote:
> >
> > On Mon, Oct 10, 2022 at 12:39:21PM +0200, Ard Biesheuvel wrote:
> > > On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > > >
> > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
> > > >
> > > > RISC-V needs NorFlashDxe driver for qemu virt machine. The
> > > > ArmPlatformPkg has this driver but migrating it to generic
> > > > package like MdeModulePkg introduces circular dependencies.
> > > > So, add a simplified version of the NorFlashDxe driver in
> > > > OvmfPkg.
> > > >
> > >
> > > So what is the difference between this simplified version and the old
> > > version? And it is backed in QEMU by the same NOR flash emulation,
> > > shouldn't we use this driver for ArmVirtQemu as well?
> >
> > I agree. If we can break the dependency on EmbeddedPkg due to
> > NvVarStoreFormattedLib, then we can migrate to MdeModulePkg and all
> > consumers can use the same driver which would be the best solution IMO.
> >
> > Could you please let me know why NvVarStoreFormattedLib is added
> > in EmbeddedPkg instead of MdePkg or MdeModulePkg? Is it only for
> > non-server class platforms? I don't see it doing much so not sure
> > its use case.
> >
>
> I think that library as well as the definition of
> gEdkiiNvVarStoreFormattedGuid should be moved to MdeModulePkg.
>
> Then, we can look at moving NorFlashDxe in there as well.
Great. Let me rework these patches then.
>
> But you haven't answered my question regarding how your version was simplified.
>
Oh sorry. I forgot to modify the commit message but what I really meant
was removing the code which depends upon PcdNorFlashCheckBlockLocked for
virtual platforms. I thought it is useful only for real platforms and
qemu doesn't emulate it. Let me know if I am wrong.
Since the driver is copied for OVMF, I didn't want to add the PCD unnecessarily.
> Note that there is some room for improvement in that driver in
> relation to execution under KVM: switching between programming mode
> and array mode involves setting up/tearing down the KVM memslot, and
> currently, the driver is far from optimized when it comes to
> minimizing the number of transitions between read mode and write mode.
I was not looking at optimizing it at this point of time.
Thanks
Sunil
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver
2022-10-10 16:05 ` Sunil V L
@ 2022-10-10 16:16 ` Ard Biesheuvel
2022-10-10 17:20 ` Sunil V L
0 siblings, 1 reply; 43+ messages in thread
From: Ard Biesheuvel @ 2022-10-10 16:16 UTC (permalink / raw)
To: Sunil V L; +Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
On Mon, 10 Oct 2022 at 18:05, Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> On Mon, Oct 10, 2022 at 05:29:15PM +0200, Ard Biesheuvel wrote:
> > On Mon, 10 Oct 2022 at 17:19, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > >
> > > On Mon, Oct 10, 2022 at 12:39:21PM +0200, Ard Biesheuvel wrote:
> > > > On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > > > >
> > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
> > > > >
> > > > > RISC-V needs NorFlashDxe driver for qemu virt machine. The
> > > > > ArmPlatformPkg has this driver but migrating it to generic
> > > > > package like MdeModulePkg introduces circular dependencies.
> > > > > So, add a simplified version of the NorFlashDxe driver in
> > > > > OvmfPkg.
> > > > >
> > > >
> > > > So what is the difference between this simplified version and the old
> > > > version? And it is backed in QEMU by the same NOR flash emulation,
> > > > shouldn't we use this driver for ArmVirtQemu as well?
> > >
> > > I agree. If we can break the dependency on EmbeddedPkg due to
> > > NvVarStoreFormattedLib, then we can migrate to MdeModulePkg and all
> > > consumers can use the same driver which would be the best solution IMO.
> > >
> > > Could you please let me know why NvVarStoreFormattedLib is added
> > > in EmbeddedPkg instead of MdePkg or MdeModulePkg? Is it only for
> > > non-server class platforms? I don't see it doing much so not sure
> > > its use case.
> > >
> >
> > I think that library as well as the definition of
> > gEdkiiNvVarStoreFormattedGuid should be moved to MdeModulePkg.
> >
> > Then, we can look at moving NorFlashDxe in there as well.
>
> Great. Let me rework these patches then.
> >
> > But you haven't answered my question regarding how your version was simplified.
> >
>
> Oh sorry. I forgot to modify the commit message but what I really meant
> was removing the code which depends upon PcdNorFlashCheckBlockLocked for
> virtual platforms. I thought it is useful only for real platforms and
> qemu doesn't emulate it. Let me know if I am wrong.
> Since the driver is copied for OVMF, I didn't want to add the PCD unnecessarily.
>
What I would like to do is the following:
- move NvVarstoreFormattedLib into MdeModulePkg (as you proposed already)
- create a new NorFlashDxe in Ovmf that is cleaned up, drops the
handling of locked blocks (as you suggest) and minimizes the number of
transitions between array mode and programming mode (i have some
patches i can share as a starting point)
- move ArmPlatformPkg's NorFlashDxe into its only remaining user,
which is is Platform/ARM in edk2-platforms (there are two more users
in edk2-platforms, but both are QEMU based on so they can switch to
the OVMF one)
> > Note that there is some room for improvement in that driver in
> > relation to execution under KVM: switching between programming mode
> > and array mode involves setting up/tearing down the KVM memslot, and
> > currently, the driver is far from optimized when it comes to
> > minimizing the number of transitions between read mode and write mode.
>
> I was not looking at optimizing it at this point of time.
>
I understand. And yet you are already proposing a different version of
NorFlashDxe, and I don't want to clone the existing NorFlashDxe
without cleaning it up first.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver
2022-10-10 16:16 ` Ard Biesheuvel
@ 2022-10-10 17:20 ` Sunil V L
2022-10-11 11:09 ` Ard Biesheuvel
0 siblings, 1 reply; 43+ messages in thread
From: Sunil V L @ 2022-10-10 17:20 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
On Mon, Oct 10, 2022 at 06:16:28PM +0200, Ard Biesheuvel wrote:
> On Mon, 10 Oct 2022 at 18:05, Sunil V L <sunilvl@ventanamicro.com> wrote:
> >
> > On Mon, Oct 10, 2022 at 05:29:15PM +0200, Ard Biesheuvel wrote:
> > > On Mon, 10 Oct 2022 at 17:19, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > > >
> > > > On Mon, Oct 10, 2022 at 12:39:21PM +0200, Ard Biesheuvel wrote:
> > > > > On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > > > > >
> > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
> > > > > >
> > > > > > RISC-V needs NorFlashDxe driver for qemu virt machine. The
> > > > > > ArmPlatformPkg has this driver but migrating it to generic
> > > > > > package like MdeModulePkg introduces circular dependencies.
> > > > > > So, add a simplified version of the NorFlashDxe driver in
> > > > > > OvmfPkg.
> > > > > >
> > > > >
> > > > > So what is the difference between this simplified version and the old
> > > > > version? And it is backed in QEMU by the same NOR flash emulation,
> > > > > shouldn't we use this driver for ArmVirtQemu as well?
> > > >
> > > > I agree. If we can break the dependency on EmbeddedPkg due to
> > > > NvVarStoreFormattedLib, then we can migrate to MdeModulePkg and all
> > > > consumers can use the same driver which would be the best solution IMO.
> > > >
> > > > Could you please let me know why NvVarStoreFormattedLib is added
> > > > in EmbeddedPkg instead of MdePkg or MdeModulePkg? Is it only for
> > > > non-server class platforms? I don't see it doing much so not sure
> > > > its use case.
> > > >
> > >
> > > I think that library as well as the definition of
> > > gEdkiiNvVarStoreFormattedGuid should be moved to MdeModulePkg.
> > >
> > > Then, we can look at moving NorFlashDxe in there as well.
> >
> > Great. Let me rework these patches then.
> > >
> > > But you haven't answered my question regarding how your version was simplified.
> > >
> >
> > Oh sorry. I forgot to modify the commit message but what I really meant
> > was removing the code which depends upon PcdNorFlashCheckBlockLocked for
> > virtual platforms. I thought it is useful only for real platforms and
> > qemu doesn't emulate it. Let me know if I am wrong.
> > Since the driver is copied for OVMF, I didn't want to add the PCD unnecessarily.
> >
>
> What I would like to do is the following:
>
> - move NvVarstoreFormattedLib into MdeModulePkg (as you proposed already)
> - create a new NorFlashDxe in Ovmf that is cleaned up, drops the
> handling of locked blocks (as you suggest) and minimizes the number of
> transitions between array mode and programming mode (i have some
> patches i can share as a starting point)
> - move ArmPlatformPkg's NorFlashDxe into its only remaining user,
> which is is Platform/ARM in edk2-platforms (there are two more users
> in edk2-platforms, but both are QEMU based on so they can switch to
> the OVMF one)
Interesting. In that case, we can continue with current approach of copy in Ovmf
and add the optimization. I was assuming you want the same driver for
real and virtual platforms in MdeModulePkg :-).
Sure, please share those optimization changes. I will create patches as
you have outlined here.
>
>
> > > Note that there is some room for improvement in that driver in
> > > relation to execution under KVM: switching between programming mode
> > > and array mode involves setting up/tearing down the KVM memslot, and
> > > currently, the driver is far from optimized when it comes to
> > > minimizing the number of transitions between read mode and write mode.
> >
> > I was not looking at optimizing it at this point of time.
> >
>
> I understand. And yet you are already proposing a different version of
> NorFlashDxe, and I don't want to clone the existing NorFlashDxe
> without cleaning it up first.
Understood. Thanks for your help.
Thanks
Sunil
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver
2022-10-10 17:20 ` Sunil V L
@ 2022-10-11 11:09 ` Ard Biesheuvel
0 siblings, 0 replies; 43+ messages in thread
From: Ard Biesheuvel @ 2022-10-11 11:09 UTC (permalink / raw)
To: Sunil V L; +Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann
On Mon, 10 Oct 2022 at 19:20, Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> On Mon, Oct 10, 2022 at 06:16:28PM +0200, Ard Biesheuvel wrote:
> > On Mon, 10 Oct 2022 at 18:05, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > >
> > > On Mon, Oct 10, 2022 at 05:29:15PM +0200, Ard Biesheuvel wrote:
> > > > On Mon, 10 Oct 2022 at 17:19, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > > > >
> > > > > On Mon, Oct 10, 2022 at 12:39:21PM +0200, Ard Biesheuvel wrote:
> > > > > > On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > > > > > >
> > > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
> > > > > > >
> > > > > > > RISC-V needs NorFlashDxe driver for qemu virt machine. The
> > > > > > > ArmPlatformPkg has this driver but migrating it to generic
> > > > > > > package like MdeModulePkg introduces circular dependencies.
> > > > > > > So, add a simplified version of the NorFlashDxe driver in
> > > > > > > OvmfPkg.
> > > > > > >
> > > > > >
> > > > > > So what is the difference between this simplified version and the old
> > > > > > version? And it is backed in QEMU by the same NOR flash emulation,
> > > > > > shouldn't we use this driver for ArmVirtQemu as well?
> > > > >
> > > > > I agree. If we can break the dependency on EmbeddedPkg due to
> > > > > NvVarStoreFormattedLib, then we can migrate to MdeModulePkg and all
> > > > > consumers can use the same driver which would be the best solution IMO.
> > > > >
> > > > > Could you please let me know why NvVarStoreFormattedLib is added
> > > > > in EmbeddedPkg instead of MdePkg or MdeModulePkg? Is it only for
> > > > > non-server class platforms? I don't see it doing much so not sure
> > > > > its use case.
> > > > >
> > > >
> > > > I think that library as well as the definition of
> > > > gEdkiiNvVarStoreFormattedGuid should be moved to MdeModulePkg.
> > > >
> > > > Then, we can look at moving NorFlashDxe in there as well.
> > >
> > > Great. Let me rework these patches then.
> > > >
> > > > But you haven't answered my question regarding how your version was simplified.
> > > >
> > >
> > > Oh sorry. I forgot to modify the commit message but what I really meant
> > > was removing the code which depends upon PcdNorFlashCheckBlockLocked for
> > > virtual platforms. I thought it is useful only for real platforms and
> > > qemu doesn't emulate it. Let me know if I am wrong.
> > > Since the driver is copied for OVMF, I didn't want to add the PCD unnecessarily.
> > >
> >
> > What I would like to do is the following:
> >
> > - move NvVarstoreFormattedLib into MdeModulePkg (as you proposed already)
> > - create a new NorFlashDxe in Ovmf that is cleaned up, drops the
> > handling of locked blocks (as you suggest) and minimizes the number of
> > transitions between array mode and programming mode (i have some
> > patches i can share as a starting point)
> > - move ArmPlatformPkg's NorFlashDxe into its only remaining user,
> > which is is Platform/ARM in edk2-platforms (there are two more users
> > in edk2-platforms, but both are QEMU based on so they can switch to
> > the OVMF one)
>
> Interesting. In that case, we can continue with current approach of copy in Ovmf
> and add the optimization. I was assuming you want the same driver for
> real and virtual platforms in MdeModulePkg :-).
>
On the one hand, I agree with Leif that having a single 'industry
standard' driver in MdeModulePkg is the optimal approach. But otoh, we
shouldn't kid ourselves and pretend that this driver can fulfil that
role without some drastic changes. And given that nobody (including
myself) seems to have time for that anyway, let's just be pragmatic
here, and adopt the approach I suggested above.
> Sure, please share those optimization changes. I will create patches as
> you have outlined here.
>
There are two patches here. They seem to work but haven't seen any
rigorous testing (or review).
https://github.com/ardbiesheuvel/edk2/tree/norflash-for-ovmf
> >
> >
> > > > Note that there is some room for improvement in that driver in
> > > > relation to execution under KVM: switching between programming mode
> > > > and array mode involves setting up/tearing down the KVM memslot, and
> > > > currently, the driver is far from optimized when it comes to
> > > > minimizing the number of transitions between read mode and write mode.
> > >
> > > I was not looking at optimizing it at this point of time.
> > >
> >
> > I understand. And yet you are already proposing a different version of
> > NorFlashDxe, and I don't want to clone the existing NorFlashDxe
> > without cleaning it up first.
>
> Understood. Thanks for your help.
>
> Thanks
> Sunil
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library Sunil V L
@ 2022-10-19 12:19 ` Ard Biesheuvel
2022-10-19 12:40 ` Sunil V L
2022-10-19 13:05 ` [edk2-devel] " Sami Mujawar
0 siblings, 2 replies; 43+ messages in thread
From: Ard Biesheuvel @ 2022-10-19 12:19 UTC (permalink / raw)
To: Sunil V L
Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Daniel Schaefer
On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
>
> This is copied from ArmVirtPkg since it is required for
> other architectures also.
>
> It also adds the instance for single flash drive which has
> both code and variables. This is copied from SbsaQemu.
>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Cc: Daniel Schaefer <git@danielschaefer.me>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Let's call these
QemuNorFlashPlatformLib [for the library class]
QemuNorFlashDeviceTreeLib
QemuNorFlashStaticLib
and for the driver
QemuNorFlashDxe
i sent out some patches for edk2-platforms to eliminate the dependency
on ArmPlatformPkg's NorFlashDxe and NorFlashPlatformLib definitions.
Once we move everything in OvmfPkg over to these ones, we can drop the
old one altogether.
> ---
> OvmfPkg/OvmfPkg.dec | 8 ++
> .../NorFlashQemuLib/NorFlashQemuLib.inf | 40 ++++++
> .../NorFlashQemuUnifiedLib.inf | 30 ++++
> OvmfPkg/Include/Library/NorFlashPlatformLib.h | 30 ++++
> .../Library/NorFlashQemuLib/NorFlashQemuLib.c | 136 ++++++++++++++++++
> .../NorFlashQemuLib/NorFlashQemuUnifiedLib.c | 40 ++++++
> 6 files changed, 284 insertions(+)
> create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
> create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
> create mode 100644 OvmfPkg/Include/Library/NorFlashPlatformLib.h
> create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
> create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
>
> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index 7d2acc5ea0e0..0697c91c6836 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -129,6 +129,10 @@ [LibraryClasses]
> #
> HardwareInfoLib|Include/Library/HardwareInfoLib.h
>
> + ## @libraryclass NorFlashQemuLib
> + #
> + NorFlashPlatformLib|Include/Library/NorFlashPlatformLib.h
> +
> [Guids]
> gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
> gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
> @@ -405,6 +409,10 @@ [PcdsFixedAtBuild]
> # check to decide whether to abort dispatch of the driver it is linked into.
> gUefiOvmfPkgTokenSpaceGuid.PcdEntryPointOverrideFwCfgVarName|""|VOID*|0x68
>
> + ## The base address and size of the FVMAIN
> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvBaseAddress|0|UINT64|0x71
> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvSize|0|UINT32|0x72
> +
> [PcdsDynamic, PcdsDynamicEx]
> gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
> diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
> new file mode 100644
> index 000000000000..ecd8059b3508
> --- /dev/null
> +++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
> @@ -0,0 +1,40 @@
> +#/** @file
> +#
> +# Component description file for NorFlashQemuLib module
> +#
> +# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#**/
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = NorFlashQemuLib
> + FILE_GUID = 42C30D8E-BFAD-4E77-9041-E7DAAE88DF7A
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = NorFlashPlatformLib
> +
> +[Sources.common]
> + NorFlashQemuLib.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + OvmfPkg/OvmfPkg.dec
> + EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + DebugLib
> + UefiBootServicesTableLib
> +
> +[Protocols]
> + gFdtClientProtocolGuid ## CONSUMES
> +
> +[Depex]
> + gFdtClientProtocolGuid
> +
> +[Pcd]
> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvBaseAddress
> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvSize
> diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
> new file mode 100644
> index 000000000000..91d1406fc3e7
> --- /dev/null
> +++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
> @@ -0,0 +1,30 @@
> +#/** @file
> +#
> +# Component description file for NorFlashQemuLib module
> +#
> +# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#**/
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = NorFlashQemuUnifiedLib
> + FILE_GUID = 064742F1-E531-4D7D-A154-22315889CC23
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = NorFlashPlatformLib
> +
> +[Sources.common]
> + NorFlashQemuUnifiedLib.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + OvmfPkg/OvmfPkg.dec
> +
> +[Pcd]
> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize
> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
> diff --git a/OvmfPkg/Include/Library/NorFlashPlatformLib.h b/OvmfPkg/Include/Library/NorFlashPlatformLib.h
> new file mode 100644
> index 000000000000..6ef5b70e9948
> --- /dev/null
> +++ b/OvmfPkg/Include/Library/NorFlashPlatformLib.h
> @@ -0,0 +1,30 @@
> +/** @file
> +
> + Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> + **/
> +
> +#ifndef _NORFLASHPLATFORMLIB_H_
> +#define _NORFLASHPLATFORMLIB_H_
> +
> +typedef struct {
> + UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA)
> + UINTN RegionBaseAddress; // Start address of one single region
> + UINTN Size;
> + UINTN BlockSize;
> +} NOR_FLASH_DESCRIPTION;
> +
> +EFI_STATUS
> +NorFlashPlatformInitialization (
> + VOID
> + );
> +
> +EFI_STATUS
> +NorFlashPlatformGetDevices (
> + OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
> + OUT UINT32 *Count
> + );
> +
> +#endif /* _NORFLASHPLATFORMLIB_H_ */
> diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
> new file mode 100644
> index 000000000000..3632fa9e7a98
> --- /dev/null
> +++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
> @@ -0,0 +1,136 @@
> +/** @file
> +
> + Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> + **/
> +
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/NorFlashPlatformLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/FdtClient.h>
> +
> +#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
> +
> +#define MAX_FLASH_BANKS 4
> +
> +EFI_STATUS
> +NorFlashPlatformInitialization (
> + VOID
> + )
> +{
> + return EFI_SUCCESS;
> +}
> +
> +NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
> +
> +EFI_STATUS
> +NorFlashPlatformGetDevices (
> + OUT 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;
> +
> + Status = gBS->LocateProtocol (
> + &gFdtClientProtocolGuid,
> + NULL,
> + (VOID **)&FdtClient
> + );
> + ASSERT_EFI_ERROR (Status);
> +
> + Num = 0;
> + 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",
> + __FUNCTION__,
> + 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 ((PcdGet64 (PcdOvmfFvBaseAddress) + PcdGet32 (PcdOvmfFvSize) > Base) &&
> + ((Base + Size) > PcdGet64 (PcdOvmfFvBaseAddress)))
> + {
> + continue;
> + }
> +
> + mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base;
> + mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base;
> + mNorFlashDevices[Num].Size = (UINTN)Size;
> + mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE;
> + Num++;
> + }
> +
> + //
> + // 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/NorFlashQemuLib/NorFlashQemuUnifiedLib.c b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
> new file mode 100644
> index 000000000000..1420fb5b596c
> --- /dev/null
> +++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
> @@ -0,0 +1,40 @@
> +/** @file
> +
> + Copyright (c) 2019, Linaro Ltd. All rights reserved
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> + **/
> +
> +#include <Base.h>
> +#include <PiDxe.h>
> +#include <Library/NorFlashPlatformLib.h>
> +
> +#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
> +
> +EFI_STATUS
> +NorFlashPlatformInitialization (
> + VOID
> + )
> +{
> + return EFI_SUCCESS;
> +}
> +
> +NOR_FLASH_DESCRIPTION mNorFlashDevice =
> +{
> + FixedPcdGet32 (PcdOvmfFdBaseAddress),
> + FixedPcdGet64 (PcdFlashNvStorageVariableBase),
> + FixedPcdGet32 (PcdOvmfFirmwareFdSize),
> + QEMU_NOR_BLOCK_SIZE
> +};
> +
> +EFI_STATUS
> +NorFlashPlatformGetDevices (
> + OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
> + OUT UINT32 *Count
> + )
> +{
> + *NorFlashDescriptions = &mNorFlashDevice;
> + *Count = 1;
> + return EFI_SUCCESS;
> +}
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library
2022-10-19 12:19 ` Ard Biesheuvel
@ 2022-10-19 12:40 ` Sunil V L
2022-10-19 13:05 ` [edk2-devel] " Sami Mujawar
1 sibling, 0 replies; 43+ messages in thread
From: Sunil V L @ 2022-10-19 12:40 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: devel, Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Daniel Schaefer
On Wed, Oct 19, 2022 at 02:19:28PM +0200, Ard Biesheuvel wrote:
> On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
> >
> > This is copied from ArmVirtPkg since it is required for
> > other architectures also.
> >
> > It also adds the instance for single flash drive which has
> > both code and variables. This is copied from SbsaQemu.
> >
> > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Gerd Hoffmann <kraxel@redhat.com>
> > Cc: Daniel Schaefer <git@danielschaefer.me>
> > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
>
> Let's call these
>
> QemuNorFlashPlatformLib [for the library class]
>
> QemuNorFlashDeviceTreeLib
> QemuNorFlashStaticLib
>
> and for the driver
>
> QemuNorFlashDxe
Sure. I will make these changes when I send next version.
>
>
> i sent out some patches for edk2-platforms to eliminate the dependency
> on ArmPlatformPkg's NorFlashDxe and NorFlashPlatformLib definitions.
> Once we move everything in OvmfPkg over to these ones, we can drop the
> old one altogether.
Sure.
Thanks!
Sunil
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-devel] [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library
2022-10-19 12:19 ` Ard Biesheuvel
2022-10-19 12:40 ` Sunil V L
@ 2022-10-19 13:05 ` Sami Mujawar
2022-10-19 13:14 ` Ard Biesheuvel
1 sibling, 1 reply; 43+ messages in thread
From: Sami Mujawar @ 2022-10-19 13:05 UTC (permalink / raw)
To: devel, ardb, Sunil V L
Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Daniel Schaefer, nd@arm.com
Hi Ard,
Please see my query inline marked [SAMI].
Regards,
Sami Mujawar
On 19/10/2022 01:19 pm, Ard Biesheuvel via groups.io wrote:
> On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
>> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
>>
>> This is copied from ArmVirtPkg since it is required for
>> other architectures also.
>>
>> It also adds the instance for single flash drive which has
>> both code and variables. This is copied from SbsaQemu.
>>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Gerd Hoffmann <kraxel@redhat.com>
>> Cc: Daniel Schaefer <git@danielschaefer.me>
>> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> Let's call these
>
> QemuNorFlashPlatformLib [for the library class]
>
> QemuNorFlashDeviceTreeLib
> QemuNorFlashStaticLib
>
> and for the driver
>
> QemuNorFlashDxe
[SAMI] We use the NorFlashDxe for the Kvmtool guest firmware, see
https://github.com/tianocore/edk2/blob/master/ArmVirtPkg/ArmVirtKvmTool.dsc#L294
Considering this, should QemuNorFlashDxe be called OvmfNorFlashDxe?
[/SAMI]
>
>
> i sent out some patches for edk2-platforms to eliminate the dependency
> on ArmPlatformPkg's NorFlashDxe and NorFlashPlatformLib definitions.
> Once we move everything in OvmfPkg over to these ones, we can drop the
> old one altogether.
>
>
>
>> ---
>> OvmfPkg/OvmfPkg.dec | 8 ++
>> .../NorFlashQemuLib/NorFlashQemuLib.inf | 40 ++++++
>> .../NorFlashQemuUnifiedLib.inf | 30 ++++
>> OvmfPkg/Include/Library/NorFlashPlatformLib.h | 30 ++++
>> .../Library/NorFlashQemuLib/NorFlashQemuLib.c | 136 ++++++++++++++++++
>> .../NorFlashQemuLib/NorFlashQemuUnifiedLib.c | 40 ++++++
>> 6 files changed, 284 insertions(+)
>> create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
>> create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
>> create mode 100644 OvmfPkg/Include/Library/NorFlashPlatformLib.h
>> create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
>> create mode 100644 OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
>>
>> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
>> index 7d2acc5ea0e0..0697c91c6836 100644
>> --- a/OvmfPkg/OvmfPkg.dec
>> +++ b/OvmfPkg/OvmfPkg.dec
>> @@ -129,6 +129,10 @@ [LibraryClasses]
>> #
>> HardwareInfoLib|Include/Library/HardwareInfoLib.h
>>
>> + ## @libraryclass NorFlashQemuLib
>> + #
>> + NorFlashPlatformLib|Include/Library/NorFlashPlatformLib.h
>> +
>> [Guids]
>> gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
>> gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
>> @@ -405,6 +409,10 @@ [PcdsFixedAtBuild]
>> # check to decide whether to abort dispatch of the driver it is linked into.
>> gUefiOvmfPkgTokenSpaceGuid.PcdEntryPointOverrideFwCfgVarName|""|VOID*|0x68
>>
>> + ## The base address and size of the FVMAIN
>> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvBaseAddress|0|UINT64|0x71
>> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvSize|0|UINT32|0x72
>> +
>> [PcdsDynamic, PcdsDynamicEx]
>> gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
>> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
>> diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
>> new file mode 100644
>> index 000000000000..ecd8059b3508
>> --- /dev/null
>> +++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
>> @@ -0,0 +1,40 @@
>> +#/** @file
>> +#
>> +# Component description file for NorFlashQemuLib module
>> +#
>> +# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
>> +#
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +#
>> +#**/
>> +
>> +[Defines]
>> + INF_VERSION = 0x00010005
>> + BASE_NAME = NorFlashQemuLib
>> + FILE_GUID = 42C30D8E-BFAD-4E77-9041-E7DAAE88DF7A
>> + MODULE_TYPE = DXE_DRIVER
>> + VERSION_STRING = 1.0
>> + LIBRARY_CLASS = NorFlashPlatformLib
>> +
>> +[Sources.common]
>> + NorFlashQemuLib.c
>> +
>> +[Packages]
>> + MdePkg/MdePkg.dec
>> + OvmfPkg/OvmfPkg.dec
>> + EmbeddedPkg/EmbeddedPkg.dec
>> +
>> +[LibraryClasses]
>> + BaseLib
>> + DebugLib
>> + UefiBootServicesTableLib
>> +
>> +[Protocols]
>> + gFdtClientProtocolGuid ## CONSUMES
>> +
>> +[Depex]
>> + gFdtClientProtocolGuid
>> +
>> +[Pcd]
>> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvBaseAddress
>> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFvSize
>> diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
>> new file mode 100644
>> index 000000000000..91d1406fc3e7
>> --- /dev/null
>> +++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.inf
>> @@ -0,0 +1,30 @@
>> +#/** @file
>> +#
>> +# Component description file for NorFlashQemuLib module
>> +#
>> +# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
>> +#
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +#
>> +#**/
>> +
>> +[Defines]
>> + INF_VERSION = 0x00010005
>> + BASE_NAME = NorFlashQemuUnifiedLib
>> + FILE_GUID = 064742F1-E531-4D7D-A154-22315889CC23
>> + MODULE_TYPE = DXE_DRIVER
>> + VERSION_STRING = 1.0
>> + LIBRARY_CLASS = NorFlashPlatformLib
>> +
>> +[Sources.common]
>> + NorFlashQemuUnifiedLib.c
>> +
>> +[Packages]
>> + MdePkg/MdePkg.dec
>> + MdeModulePkg/MdeModulePkg.dec
>> + OvmfPkg/OvmfPkg.dec
>> +
>> +[Pcd]
>> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
>> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize
>> + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
>> diff --git a/OvmfPkg/Include/Library/NorFlashPlatformLib.h b/OvmfPkg/Include/Library/NorFlashPlatformLib.h
>> new file mode 100644
>> index 000000000000..6ef5b70e9948
>> --- /dev/null
>> +++ b/OvmfPkg/Include/Library/NorFlashPlatformLib.h
>> @@ -0,0 +1,30 @@
>> +/** @file
>> +
>> + Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
>> +
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> + **/
>> +
>> +#ifndef _NORFLASHPLATFORMLIB_H_
>> +#define _NORFLASHPLATFORMLIB_H_
>> +
>> +typedef struct {
>> + UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA)
>> + UINTN RegionBaseAddress; // Start address of one single region
>> + UINTN Size;
>> + UINTN BlockSize;
>> +} NOR_FLASH_DESCRIPTION;
>> +
>> +EFI_STATUS
>> +NorFlashPlatformInitialization (
>> + VOID
>> + );
>> +
>> +EFI_STATUS
>> +NorFlashPlatformGetDevices (
>> + OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
>> + OUT UINT32 *Count
>> + );
>> +
>> +#endif /* _NORFLASHPLATFORMLIB_H_ */
>> diff --git a/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
>> new file mode 100644
>> index 000000000000..3632fa9e7a98
>> --- /dev/null
>> +++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
>> @@ -0,0 +1,136 @@
>> +/** @file
>> +
>> + Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
>> +
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> + **/
>> +
>> +#include <Library/BaseLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/NorFlashPlatformLib.h>
>> +#include <Library/UefiBootServicesTableLib.h>
>> +
>> +#include <Protocol/FdtClient.h>
>> +
>> +#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
>> +
>> +#define MAX_FLASH_BANKS 4
>> +
>> +EFI_STATUS
>> +NorFlashPlatformInitialization (
>> + VOID
>> + )
>> +{
>> + return EFI_SUCCESS;
>> +}
>> +
>> +NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
>> +
>> +EFI_STATUS
>> +NorFlashPlatformGetDevices (
>> + OUT 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;
>> +
>> + Status = gBS->LocateProtocol (
>> + &gFdtClientProtocolGuid,
>> + NULL,
>> + (VOID **)&FdtClient
>> + );
>> + ASSERT_EFI_ERROR (Status);
>> +
>> + Num = 0;
>> + 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",
>> + __FUNCTION__,
>> + 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 ((PcdGet64 (PcdOvmfFvBaseAddress) + PcdGet32 (PcdOvmfFvSize) > Base) &&
>> + ((Base + Size) > PcdGet64 (PcdOvmfFvBaseAddress)))
>> + {
>> + continue;
>> + }
>> +
>> + mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base;
>> + mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base;
>> + mNorFlashDevices[Num].Size = (UINTN)Size;
>> + mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE;
>> + Num++;
>> + }
>> +
>> + //
>> + // 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/NorFlashQemuLib/NorFlashQemuUnifiedLib.c b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
>> new file mode 100644
>> index 000000000000..1420fb5b596c
>> --- /dev/null
>> +++ b/OvmfPkg/Library/NorFlashQemuLib/NorFlashQemuUnifiedLib.c
>> @@ -0,0 +1,40 @@
>> +/** @file
>> +
>> + Copyright (c) 2019, Linaro Ltd. All rights reserved
>> +
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> + **/
>> +
>> +#include <Base.h>
>> +#include <PiDxe.h>
>> +#include <Library/NorFlashPlatformLib.h>
>> +
>> +#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
>> +
>> +EFI_STATUS
>> +NorFlashPlatformInitialization (
>> + VOID
>> + )
>> +{
>> + return EFI_SUCCESS;
>> +}
>> +
>> +NOR_FLASH_DESCRIPTION mNorFlashDevice =
>> +{
>> + FixedPcdGet32 (PcdOvmfFdBaseAddress),
>> + FixedPcdGet64 (PcdFlashNvStorageVariableBase),
>> + FixedPcdGet32 (PcdOvmfFirmwareFdSize),
>> + QEMU_NOR_BLOCK_SIZE
>> +};
>> +
>> +EFI_STATUS
>> +NorFlashPlatformGetDevices (
>> + OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
>> + OUT UINT32 *Count
>> + )
>> +{
>> + *NorFlashDescriptions = &mNorFlashDevice;
>> + *Count = 1;
>> + return EFI_SUCCESS;
>> +}
>> --
>> 2.25.1
>>
>
>
>
>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-devel] [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library
2022-10-19 13:05 ` [edk2-devel] " Sami Mujawar
@ 2022-10-19 13:14 ` Ard Biesheuvel
2022-10-19 13:19 ` Sami Mujawar
0 siblings, 1 reply; 43+ messages in thread
From: Ard Biesheuvel @ 2022-10-19 13:14 UTC (permalink / raw)
To: Sami Mujawar, Leif Lindholm
Cc: devel, Sunil V L, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Daniel Schaefer, nd@arm.com
On Wed, 19 Oct 2022 at 15:06, Sami Mujawar <sami.mujawar@arm.com> wrote:
>
> Hi Ard,
>
> Please see my query inline marked [SAMI].
>
> Regards,
>
> Sami Mujawar
>
> On 19/10/2022 01:19 pm, Ard Biesheuvel via groups.io wrote:
> > On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
> >> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
> >>
> >> This is copied from ArmVirtPkg since it is required for
> >> other architectures also.
> >>
> >> It also adds the instance for single flash drive which has
> >> both code and variables. This is copied from SbsaQemu.
> >>
> >> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> >> Cc: Jiewen Yao <jiewen.yao@intel.com>
> >> Cc: Jordan Justen <jordan.l.justen@intel.com>
> >> Cc: Gerd Hoffmann <kraxel@redhat.com>
> >> Cc: Daniel Schaefer <git@danielschaefer.me>
> >> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> > Let's call these
> >
> > QemuNorFlashPlatformLib [for the library class]
> >
> > QemuNorFlashDeviceTreeLib
> > QemuNorFlashStaticLib
> >
> > and for the driver
> >
> > QemuNorFlashDxe
>
> [SAMI] We use the NorFlashDxe for the Kvmtool guest firmware, see
> https://github.com/tianocore/edk2/blob/master/ArmVirtPkg/ArmVirtKvmTool.dsc#L294
>
> Considering this, should QemuNorFlashDxe be called OvmfNorFlashDxe?
>
> [/SAMI]
>
Ah yes, good point. So using Qemu as a prefix is slightly problematic.
My intent is for this driver to be optimized towards NOR flash
emulation the way QEMU implements it. The main difference between the
platforms is that some of them (notably, ArmVirtQemu.dsc) also execute
from the emulated region, which requires an executable (read-only)
memslot in KVM, as instruction fetches (as opposed to explicit loads
and stores) cannot be emulated by KVM. KvmTool only uses the NOR flash
for variables, so it doesn't really care how the emulation is
implemented, as long as the loads and stores are carried out in the
expected way.
I don't think the Ovmf prefix makes sense here either - OVMF is still
primarily x86, which uses a different flash emulation altogether.
Maybe VirtNorFlashDxe, to emphasize that it does not expect to be
dealing with actual NOR flash?
Suggestions welcome :-)
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-devel] [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library
2022-10-19 13:14 ` Ard Biesheuvel
@ 2022-10-19 13:19 ` Sami Mujawar
2022-10-19 13:46 ` Leif Lindholm
0 siblings, 1 reply; 43+ messages in thread
From: Sami Mujawar @ 2022-10-19 13:19 UTC (permalink / raw)
To: Ard Biesheuvel, Leif Lindholm
Cc: devel, Sunil V L, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
Daniel Schaefer, nd@arm.com
Hi Ard,
On 19/10/2022 02:14 pm, Ard Biesheuvel wrote:
> On Wed, 19 Oct 2022 at 15:06, Sami Mujawar <sami.mujawar@arm.com> wrote:
>> Hi Ard,
>>
>> Please see my query inline marked [SAMI].
>>
>> Regards,
>>
>> Sami Mujawar
>>
>> On 19/10/2022 01:19 pm, Ard Biesheuvel via groups.io wrote:
>>> On Mon, 10 Oct 2022 at 12:13, Sunil V L <sunilvl@ventanamicro.com> wrote:
>>>> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076
>>>>
>>>> This is copied from ArmVirtPkg since it is required for
>>>> other architectures also.
>>>>
>>>> It also adds the instance for single flash drive which has
>>>> both code and variables. This is copied from SbsaQemu.
>>>>
>>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>>> Cc: Gerd Hoffmann <kraxel@redhat.com>
>>>> Cc: Daniel Schaefer <git@danielschaefer.me>
>>>> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
>>> Let's call these
>>>
>>> QemuNorFlashPlatformLib [for the library class]
>>>
>>> QemuNorFlashDeviceTreeLib
>>> QemuNorFlashStaticLib
>>>
>>> and for the driver
>>>
>>> QemuNorFlashDxe
>> [SAMI] We use the NorFlashDxe for the Kvmtool guest firmware, see
>> https://github.com/tianocore/edk2/blob/master/ArmVirtPkg/ArmVirtKvmTool.dsc#L294
>>
>> Considering this, should QemuNorFlashDxe be called OvmfNorFlashDxe?
>>
>> [/SAMI]
>>
> Ah yes, good point. So using Qemu as a prefix is slightly problematic.
>
> My intent is for this driver to be optimized towards NOR flash
> emulation the way QEMU implements it. The main difference between the
> platforms is that some of them (notably, ArmVirtQemu.dsc) also execute
> from the emulated region, which requires an executable (read-only)
> memslot in KVM, as instruction fetches (as opposed to explicit loads
> and stores) cannot be emulated by KVM. KvmTool only uses the NOR flash
> for variables, so it doesn't really care how the emulation is
> implemented, as long as the loads and stores are carried out in the
> expected way.
>
> I don't think the Ovmf prefix makes sense here either - OVMF is still
> primarily x86, which uses a different flash emulation altogether.
> Maybe VirtNorFlashDxe, to emphasize that it does not expect to be
> dealing with actual NOR flash?
VirtNorFlashDxe sounds good to me.
Regards,
Sami Mujawar
>
> Suggestions welcome :-)
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [edk2-devel] [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library
2022-10-19 13:19 ` Sami Mujawar
@ 2022-10-19 13:46 ` Leif Lindholm
0 siblings, 0 replies; 43+ messages in thread
From: Leif Lindholm @ 2022-10-19 13:46 UTC (permalink / raw)
To: Sami Mujawar
Cc: Ard Biesheuvel, devel, Sunil V L, Jiewen Yao, Jordan Justen,
Gerd Hoffmann, Daniel Schaefer, nd@arm.com
On Wed, Oct 19, 2022 at 14:19:28 +0100, Sami Mujawar wrote:
> > > Considering this, should QemuNorFlashDxe be called OvmfNorFlashDxe?
> > >
> > > [/SAMI]
> > >
> > Ah yes, good point. So using Qemu as a prefix is slightly problematic.
> >
> > My intent is for this driver to be optimized towards NOR flash
> > emulation the way QEMU implements it. The main difference between the
> > platforms is that some of them (notably, ArmVirtQemu.dsc) also execute
> > from the emulated region, which requires an executable (read-only)
> > memslot in KVM, as instruction fetches (as opposed to explicit loads
> > and stores) cannot be emulated by KVM. KvmTool only uses the NOR flash
> > for variables, so it doesn't really care how the emulation is
> > implemented, as long as the loads and stores are carried out in the
> > expected way.
> >
> > I don't think the Ovmf prefix makes sense here either - OVMF is still
> > primarily x86, which uses a different flash emulation altogether.
> > Maybe VirtNorFlashDxe, to emphasize that it does not expect to be
> > dealing with actual NOR flash?
>
> VirtNorFlashDxe sounds good to me.
Sounds good to me too.
/
Leif
^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2022-10-19 13:47 UTC | newest]
Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-10 10:11 [edk2-staging/RiscV64QemuVirt PATCH 00/29] Add support for RISC-V virt machine Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 01/29] MdePkg/Register: Add register definition header files for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 02/29] MdePkg: Add RISCV_EFI_BOOT_PROTOCOL related definitions Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 03/29] MdePkg/BaseLib: RISC-V: Add few more helper functions Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 04/29] MdePkg: Add BaseRiscVSbiLib Library for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 05/29] OvmfPkg/PlatformInitLib: Refactor to allow other architectures Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 06/29] OvmfPkg/PlatformInitLib: Add support for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 07/29] OvmfPkg/ResetSystemLib: Refactor to allow other architectures Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 08/29] OvmfPkg/ResetSystemLib: Add support for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 09/29] OvmfPkg/Sec: Refactor to allow other architectures Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 10/29] OvmfPkg/Sec: Add RISC-V support Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 11/29] OvmfPkg/PlatformPei: Refactor to allow other architectures Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 12/29] OvmfPkg/PlatformPei: Add support for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 13/29] UefiCpuPkg/CpuTimerLib: Refactor to allow other architectures Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 14/29] UefiCpuPkg/CpuTimerLib: Add support for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 15/29] UefiCpuPkg/CpuExceptionHandlerLib: Refactor to allow other architectures Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 16/29] UefiCpuPkg/CpuExceptionHandlerLib: Add support for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 17/29] UefiCpuPkg/CpuDxe: Refactor to allow other architectures Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 18/29] UefiCpuPkg/CpuDxe: Add support for RISC-V Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 19/29] UefiCpuPkg/CpuDxe: Add RISC-V Boot protocol support Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 20/29] UefiCpuPkg: Add CpuTimerDxe module Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 21/29] ArmVirtPkg/PlatformHasAcpiDtDxe: Move to OvmfPkg Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 22/29] ArmVirtPkg: Fix up the location of PlatformHasAcpiDtDxe Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 23/29] ArmVirtPkg/PlatformBootManagerLib: Move to OvmfPkg Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 24/29] ArmVirtPkg: Fix up the paths to PlatformBootManagerLib Sunil V L
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 25/29] OvmfPkg: Add NorFlashQemuLib library Sunil V L
2022-10-19 12:19 ` Ard Biesheuvel
2022-10-19 12:40 ` Sunil V L
2022-10-19 13:05 ` [edk2-devel] " Sami Mujawar
2022-10-19 13:14 ` Ard Biesheuvel
2022-10-19 13:19 ` Sami Mujawar
2022-10-19 13:46 ` Leif Lindholm
2022-10-10 10:11 ` [edk2-staging/RiscV64QemuVirt PATCH 26/29] OvmfPkg: Add generic Qemu NOR flash DXE driver Sunil V L
2022-10-10 10:39 ` Ard Biesheuvel
2022-10-10 15:19 ` Sunil V L
2022-10-10 15:29 ` Ard Biesheuvel
2022-10-10 16:05 ` Sunil V L
2022-10-10 16:16 ` Ard Biesheuvel
2022-10-10 17:20 ` Sunil V L
2022-10-11 11:09 ` Ard Biesheuvel
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 27/29] OvmfPkg: RiscVVirt: Add Qemu Virt platform support Sunil V L
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 28/29] Maintainers.txt: Add entry for OvmfPkg/RiscVVirt Sunil V L
2022-10-10 10:12 ` [edk2-staging/RiscV64QemuVirt PATCH 29/29] UefiCpuPkg/UefiCpuPkg.ci.yaml: Ignore RISC-V file Sunil V L
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox