diff --git a/0124-Backport-Add-AcpiErrorInjectionTableDxe-and-AcpiHardwareErrorTableDxe-Support-for-OS-RAS-SSE-Validation.patch b/0124-Backport-Add-AcpiErrorInjectionTableDxe-and-AcpiHardwareErrorTableDxe-Support-for-OS-RAS-SSE-Validation.patch new file mode 100644 index 0000000000000000000000000000000000000000..6cc3e0011ec1041ba22be73ca78700ba0e3810f3 --- /dev/null +++ b/0124-Backport-Add-AcpiErrorInjectionTableDxe-and-AcpiHardwareErrorTableDxe-Support-for-OS-RAS-SSE-Validation.patch @@ -0,0 +1,2162 @@ +From 0e021918af7e0c95ea2d929709a29ae497c8eebb Mon Sep 17 00:00:00 2001 +From: hu.yuye +Date: Mon, 3 Nov 2025 19:51:48 +0800 +Subject: [PATCH]Backport-Add AcpiErrorInjectionTableDxe and AcpiHardwareErrorTableDxe +Support for OS RAS SSE validation + +Signed-off-by: liuqingtao + +--- + .../ErrorInjectionTableDxe.c | 239 ++++++++ + .../ErrorInjectionTableDxe.inf | 59 ++ + .../ErrorInjectionTableDxe.uni | 14 + + .../ErrorInjectionTableDxeExtra.uni | 14 + + .../HardwareErrorSourceTableDxe.c | 243 +++++++++ + .../HardwareErrorSourceTableDxe.inf | 59 ++ + .../HardwareErrorSourceTableDxe.uni | 14 + + .../HardwareErrorSourceTableDxeExtra.uni | 14 + + MdePkg/Include/Library/BaseRiscVSbiLib.h | 24 + + MdePkg/Include/Library/DxeRiscvMpxy.h | 123 +++++ + .../Include/Library/DxeRiscvRasAgentClient.h | 116 ++++ + .../Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c | 22 + + MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.c | 508 ++++++++++++++++++ + .../Library/DxeRiscvMpxyLib/DxeRiscvMpxy.inf | 30 ++ + .../Library/DxeRiscvMpxyLib/DxeRiscvMpxy.uni | 15 + + .../DxeRiscvRasAgentClient.c | 421 +++++++++++++++ + .../DxeRiscvRasAgentClientLib.inf | 38 ++ + OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc | 4 + + OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf | 2 + + 19 files changed, 1959 insertions(+) + create mode 100644 MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.c + create mode 100644 MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.inf + create mode 100644 MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.uni + create mode 100644 MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxeExtra.uni + create mode 100644 MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.c + create mode 100644 MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.inf + create mode 100644 MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.uni + create mode 100644 MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxeExtra.uni + create mode 100644 MdePkg/Include/Library/DxeRiscvMpxy.h + create mode 100644 MdePkg/Include/Library/DxeRiscvRasAgentClient.h + create mode 100644 MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.c + create mode 100644 MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.inf + create mode 100644 MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.uni + create mode 100644 MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClient.c + create mode 100644 MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClientLib.inf + +diff --git a/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.c b/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.c +new file mode 100644 +index 00000000..6ee0cbf9 +--- /dev/null ++++ b/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.c +@@ -0,0 +1,239 @@ ++/** @file ++ This module installs ACPI Error Injection Table (EINJ) ++ ++ Copyright (c) 2025, Ventana Micro Systems, Inc. ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++EFI_EVENT mEinjReadyToBootEvent; ++UINTN mEinjTableKey = 0; ++BOOLEAN mAcpiEinjInstalled = FALSE; ++BOOLEAN mAcpiEinjStatusChanged = FALSE; ++BOOLEAN mAcpiEinjBufferChanged = FALSE; ++ ++#define STATUS_BLOCK_SIZE 1024 ++#define MPXY_SHMEM_SIZE 4096 ++ ++// ++// ACPI Error Injection Table template ++// ++EFI_ACPI_6_5_ERROR_INJECTION_TABLE_HEADER mEinjTemplate = { ++ { ++ EFI_ACPI_6_5_ERROR_INJECTION_TABLE_SIGNATURE, ++ sizeof (EFI_ACPI_6_5_ERROR_INJECTION_TABLE_HEADER), ++ EFI_ACPI_6_5_ERROR_INJECTION_TABLE_REVISION, // Revision ++ 0x00, // Checksum will be updated at runtime ++ // ++ // It is expected that these values will be updated at EntryPoint. ++ // ++ { 0x00 }, // OEM ID is a 6 bytes long field ++ 0x00, // OEM Table ID(8 bytes long) ++ 0x00, // OEM Revision ++ 0x00, // Creator ID ++ 0x00, // Creator Revision ++ }, ++ 0 // Number of error source ++}; ++ ++/** ++ Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to ++ install the Hardware Error Source Table. ++ ++ @param[in] Event The Event that is being processed. ++ @param[in] Context The Event Context. ++ ++**/ ++VOID ++EinjReadyToBootEventNotify ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; ++ EFI_ACPI_DESCRIPTION_HEADER *Header; ++ UINT32 NumInstructions; ++ INTN i; ++ VOID *EinjTable; ++ UINT32 EinjPages, EinjTableSize; ++ EFI_ACPI_6_5_EINJ_INJECTION_INSTRUCTION_ENTRY *BaseEntry, *tBaseEntry; ++ EFI_ACPI_6_5_ERROR_INJECTION_TABLE_HEADER *EinjHdr; ++ VOID *Inst; ++ UINT32 InstSize; ++#define EINJ_TO_BASE_INJECTION_ACTION_TABLE(_table) \ ++ (EFI_ACPI_6_5_EINJ_INJECTION_INSTRUCTION_ENTRY *) \ ++ ((UINT8 *)_table + \ ++ sizeof(EFI_ACPI_6_5_ERROR_INJECTION_TABLE_HEADER)); ++ ++ Header = &mEinjTemplate.Header; ++ ++ // ++ // Get ACPI Table protocol. ++ // ++ Status = gBS->LocateProtocol ( ++ &gEfiAcpiTableProtocolGuid, ++ NULL, ++ (VOID **)&AcpiTableProtocol ++ ); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ // ++ // Check if HEST is already installed. ++ // ++ if (mAcpiEinjInstalled) { ++ Status = AcpiTableProtocol->UninstallAcpiTable ( ++ AcpiTableProtocol, ++ mEinjTableKey ++ ); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ } ++ ++ // Initialize the RAS agent client library. ++ Status = RacInit (); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ // Fetch the number of hardware error sources available ++ Status = RacGetNumberErrorInjectionEntries(&NumInstructions); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ mEinjTemplate.InjectionEntryCount = NumInstructions; ++ ++ // Allocate memory for all the error source descriptors ++ EinjTableSize = sizeof(mEinjTemplate) + ++ sizeof(EFI_ACPI_6_5_EINJ_INJECTION_INSTRUCTION_ENTRY) ++ * NumInstructions; ++ ++ EinjPages = EFI_SIZE_TO_PAGES(EinjTableSize); ++ EinjTable = AllocateAlignedPages(EinjPages, 4096); ++ ++ if (EinjTable == NULL) { ++ return; ++ } ++ ++ EinjHdr = (EFI_ACPI_6_5_ERROR_INJECTION_TABLE_HEADER *)EinjTable; ++ CopyMem (EinjTable, &mEinjTemplate, sizeof(mEinjTemplate)); ++ EinjHdr->InjectionHeaderSize = sizeof(mEinjTemplate); ++ EinjHdr->InjectionFlags = 0; ++ EinjHdr->InjectionEntryCount = NumInstructions; ++ ++ tBaseEntry = BaseEntry = EINJ_TO_BASE_INJECTION_ACTION_TABLE(EinjTable); ++ ++ for (i = 0; i < NumInstructions; i++) { ++ Status = RacGetEinjInstruction (i, &Inst, &InstSize); ++ if (EFI_ERROR(Status)) { ++ return; ++ } ++ ++ CopyMem (tBaseEntry, Inst, InstSize); ++ tBaseEntry++; ++ } ++ ++ Header = &((typeof(mEinjTemplate) *)EinjTable)->Header; ++ Header->Length = EinjTableSize; ++ ++ // ++ // Update Checksum in Hest Table ++ // ++ Header->Checksum = 0; ++ Header->Checksum = ++ CalculateCheckSum8 ( ++ (UINT8 *)&EinjTable, ++ EinjTableSize ++ ); ++ ++ // ++ // Publish Boot Graphics Resource Table. ++ // ++ Status = AcpiTableProtocol->InstallAcpiTable ( ++ AcpiTableProtocol, ++ EinjTable, ++ EinjTableSize, ++ &mEinjTableKey ++ ); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ mAcpiEinjInstalled = TRUE; ++} ++ ++/** ++ The module Entry Point of the Boot Graphics Resource Table DXE driver. ++ ++ @param[in] ImageHandle The firmware allocated handle for the EFI image. ++ @param[in] SystemTable A pointer to the EFI System Table. ++ ++ @retval EFI_SUCCESS The entry point is executed successfully. ++ @retval Other Some error occurs when executing this entry point. ++ ++**/ ++EFI_STATUS ++EFIAPI ++ErrorInjectionDxeEntryPoint ( ++ IN EFI_HANDLE ImageHandle, ++ IN EFI_SYSTEM_TABLE *SystemTable ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_ACPI_DESCRIPTION_HEADER *Header; ++ ++ // ++ // Update Header fields of HEST ++ // ++ Header = &mEinjTemplate.Header; ++ ZeroMem (Header->OemId, sizeof (Header->OemId)); ++ CopyMem ( ++ Header->OemId, ++ PcdGetPtr (PcdAcpiDefaultOemId), ++ MIN (PcdGetSize (PcdAcpiDefaultOemId), sizeof (Header->OemId)) ++ ); ++ ++ WriteUnaligned64 (&Header->OemTableId, PcdGet64 (PcdAcpiDefaultOemTableId)); ++ Header->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); ++ Header->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); ++ Header->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); ++ ++ // ++ // Register notify function to install EINJ on ReadyToBoot Event. ++ // ++ Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_CALLBACK, ++ EinjReadyToBootEventNotify, ++ NULL, ++ &gEfiEventReadyToBootGuid, ++ &mEinjReadyToBootEvent ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ return Status; ++} +diff --git a/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.inf b/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.inf +new file mode 100644 +index 00000000..2998d9a1 +--- /dev/null ++++ b/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.inf +@@ -0,0 +1,59 @@ ++## @file ++# This module install ACPI Error Injection Table (EINJ) ++# ++# Copyright (c) 2025, Ventana Micro Systems, Inc. ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++## ++ ++[Defines] ++ INF_VERSION = 0x00010005 ++ BASE_NAME = ErrorInjectionTableDxe ++ MODULE_UNI_FILE = ErrorInjectionTableDxe.uni ++ FILE_GUID = 07619d3d-6ded-4c57-a0ba-509162bf5c88 ++ MODULE_TYPE = UEFI_DRIVER ++ VERSION_STRING = 1.0 ++ ENTRY_POINT = ErrorInjectionDxeEntryPoint ++ ++# ++# The following information is for reference only and not required by the build tools. ++# ++# VALID_ARCHITECTURES = RISCV64 ++# ++ ++[Sources] ++ ErrorInjectionTableDxe.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ ++[LibraryClasses] ++ UefiDriverEntryPoint ++ BaseLib ++ BaseMemoryLib ++ MemoryAllocationLib ++ UefiLib ++ UefiBootServicesTableLib ++ DebugLib ++ PcdLib ++ SafeIntLib ++ RiscVSbiLib ++ DxeRiscvMpxyLib ++ DxeRiscvRasAgentClientLib ++ ++[Protocols] ++ gEfiAcpiTableProtocolGuid ## CONSUMES ++ ++[Pcd] ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES ++ ++[Guids] ++ gEfiEventReadyToBootGuid ## CONSUMES ## Event ++ ++[UserExtensions.TianoCore."ExtraFiles"] ++ ErrorInectionTableTableDxeExtra.uni +diff --git a/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.uni b/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.uni +new file mode 100644 +index 00000000..e58efb83 +--- /dev/null ++++ b/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.uni +@@ -0,0 +1,14 @@ ++// /** @file ++// This module install ACPI Error Injection Table (EINJ). ++// ++// Copyright (c) 2025, Ventana Micro Systems, Inc. ++// ++// SPDX-License-Identifier: BSD-2-Clause-Patent ++// ++// **/ ++ ++ ++#string STR_MODULE_ABSTRACT #language en-US "Installs ACPI Error Injection Table (EINJ)" ++ ++#string STR_MODULE_DESCRIPTION #language en-US "This module installs the ACPI Hardware Error Injection Table (EINJ)" ++ +diff --git a/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxeExtra.uni b/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxeExtra.uni +new file mode 100644 +index 00000000..0139f6ad +--- /dev/null ++++ b/MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxeExtra.uni +@@ -0,0 +1,14 @@ ++// /** @file ++// ErrorInjectionTableDxe Localized Strings and Content ++// ++// Copyright (c) 2025, Ventana Micro Systems, Inc. ++// ++// SPDX-License-Identifier: BSD-2-Clause-Patent ++// ++// **/ ++ ++#string STR_PROPERTIES_MODULE_NAME ++#language en-US ++"ACPI Error Injection Table DXE Driver" ++ ++ +diff --git a/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.c b/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.c +new file mode 100644 +index 00000000..ee42cfc6 +--- /dev/null ++++ b/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.c +@@ -0,0 +1,243 @@ ++/** @file ++ This module installs ACPI Hardware Error Source Table (HEST) ++ ++ Copyright (c) 2024, Ventana Micro Systems, Inc. ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++EFI_EVENT mHestReadyToBootEvent; ++UINTN mHestTableKey = 0; ++BOOLEAN mAcpiHestInstalled = FALSE; ++BOOLEAN mAcpiHestStatusChanged = FALSE; ++BOOLEAN mAcpiHestBufferChanged = FALSE; ++ ++#define STATUS_BLOCK_SIZE 1024 ++#define MPXY_SHMEM_SIZE 4096 ++ ++// ++// ACPI Hardware Error Source Table template ++// ++EFI_ACPI_6_5_HARDWARE_ERROR_SOURCE_TABLE_HEADER mHestTemplate = { ++ { ++ EFI_ACPI_6_5_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE, ++ sizeof (EFI_ACPI_6_5_HARDWARE_ERROR_SOURCE_TABLE_HEADER), ++ EFI_ACPI_6_5_HARDWARE_ERROR_SOURCE_TABLE_REVISION, // Revision ++ 0x00, // Checksum will be updated at runtime ++ // ++ // It is expected that these values will be updated at EntryPoint. ++ // ++ { 0x00 }, // OEM ID is a 6 bytes long field ++ 0x00, // OEM Table ID(8 bytes long) ++ 0x00, // OEM Revision ++ 0x00, // Creator ID ++ 0x00, // Creator Revision ++ }, ++ 0 // Number of error source ++}; ++ ++/** ++ Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to ++ install the Hardware Error Source Table. ++ ++ @param[in] Event The Event that is being processed. ++ @param[in] Context The Event Context. ++ ++**/ ++VOID ++EFIAPI ++HestReadyToBootEventNotify ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; ++ EFI_ACPI_DESCRIPTION_HEADER *Header; ++ VOID *ErrDesc; ++ UINT32 NumSources, *ErrSources, ErrDescSize; ++ INTN i; ++ VOID *HestTable; ++ UINT32 HestPages, HestTableSize; ++ UINTN DescriptorType; ++ EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE *BaseErrSrcStructure, *tESS; ++#define HEST_TO_BASE_ERROR_STRUCTURE(_table) \ ++ (EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE *) \ ++ ((UINT8 *)_table + \ ++ sizeof(typeof(EFI_ACPI_6_5_HARDWARE_ERROR_SOURCE_TABLE_HEADER))); ++ ++ Header = &mHestTemplate.Header; ++ ++ // ++ // Get ACPI Table protocol. ++ // ++ Status = gBS->LocateProtocol ( ++ &gEfiAcpiTableProtocolGuid, ++ NULL, ++ (VOID **)&AcpiTableProtocol ++ ); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ // ++ // Check if HEST is already installed. ++ // ++ if (mAcpiHestInstalled) { ++ Status = AcpiTableProtocol->UninstallAcpiTable ( ++ AcpiTableProtocol, ++ mHestTableKey ++ ); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ } ++ ++ // Initialize the RAS agent client library. ++ Status = RacInit (); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ // Fetch the number of hardware error sources available ++ Status = RacGetNumberErrorSources(&NumSources); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ // Fetch the unique source ID for each error source. ++ Status = RacGetErrorSourceIDList(&ErrSources, &NumSources); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ mHestTemplate.ErrorSourceCount = NumSources; ++ ++ // Allocate memory for all the error source descriptors ++ HestTableSize = sizeof(mHestTemplate) + ++ sizeof(EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE) ++ * NumSources; ++ HestPages = EFI_SIZE_TO_PAGES(HestTableSize); ++ HestTable = AllocateAlignedPages(HestPages, 4096); ++ ++ if (HestTable == NULL) { ++ return; ++ } ++ ++ CopyMem (HestTable, &mHestTemplate, sizeof(mHestTemplate)); ++ ++ tESS = BaseErrSrcStructure = HEST_TO_BASE_ERROR_STRUCTURE(HestTable); ++ ++ for (i = 0; i < NumSources; i++) { ++ Status = RacGetErrorSourceDescriptor (ErrSources[i], ++ &DescriptorType, &ErrDesc, &ErrDescSize ++ ); ++ if (EFI_ERROR(Status)) { ++ return; ++ } ++ ++ ASSERT (DescriptorType == DT_GHESV2); ++ ++ CopyMem (tESS, ErrDesc, ErrDescSize); ++ tESS++; ++ } ++ ++ Header = &((typeof(mHestTemplate) *)HestTable)->Header; ++ Header->Length = HestTableSize; ++ // ++ // Update Checksum in Hest Table ++ // ++ Header->Checksum = 0; ++ Header->Checksum = ++ CalculateCheckSum8 ( ++ (UINT8 *)&HestTable, ++ HestTableSize ++ ); ++ ++ // ++ // Publish Boot Graphics Resource Table. ++ // ++ Status = AcpiTableProtocol->InstallAcpiTable ( ++ AcpiTableProtocol, ++ HestTable, ++ HestTableSize, ++ &mHestTableKey ++ ); ++ if (EFI_ERROR (Status)) { ++ return; ++ } ++ ++ mAcpiHestInstalled = TRUE; ++} ++ ++/** ++ The module Entry Point of the Boot Graphics Resource Table DXE driver. ++ ++ @param[in] ImageHandle The firmware allocated handle for the EFI image. ++ @param[in] SystemTable A pointer to the EFI System Table. ++ ++ @retval EFI_SUCCESS The entry point is executed successfully. ++ @retval Other Some error occurs when executing this entry point. ++ ++**/ ++EFI_STATUS ++EFIAPI ++HardwareErrorSourceDxeEntryPoint ( ++ IN EFI_HANDLE ImageHandle, ++ IN EFI_SYSTEM_TABLE *SystemTable ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_ACPI_DESCRIPTION_HEADER *Header; ++ ++ // ++ // Update Header fields of HEST ++ // ++ Header = &mHestTemplate.Header; ++ ZeroMem (Header->OemId, sizeof (Header->OemId)); ++ CopyMem ( ++ Header->OemId, ++ PcdGetPtr (PcdAcpiDefaultOemId), ++ MIN (PcdGetSize (PcdAcpiDefaultOemId), sizeof (Header->OemId)) ++ ); ++ ++ WriteUnaligned64 (&Header->OemTableId, PcdGet64 (PcdAcpiDefaultOemTableId)); ++ Header->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); ++ Header->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); ++ Header->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); ++ ++ // ++ // Register notify function to install HEST on ReadyToBoot Event. ++ // ++ Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_CALLBACK, ++ HestReadyToBootEventNotify, ++ NULL, ++ &gEfiEventReadyToBootGuid, ++ &mHestReadyToBootEvent ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ return Status; ++} +diff --git a/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.inf b/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.inf +new file mode 100644 +index 00000000..b3fc6e95 +--- /dev/null ++++ b/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.inf +@@ -0,0 +1,59 @@ ++## @file ++# This module install ACPI Hardware Error Source Table (HEST) ++# ++# Copyright (c) 2024, Ventana Micro Systems, Inc. ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++## ++ ++[Defines] ++ INF_VERSION = 0x00010005 ++ BASE_NAME = HardwareErrorSourceTableDxe ++ MODULE_UNI_FILE = HardwareErrorSourceTableDxe.uni ++ FILE_GUID = 79ecd602-f3b0-4780-9eed-d744229428e3 ++ MODULE_TYPE = UEFI_DRIVER ++ VERSION_STRING = 1.0 ++ ENTRY_POINT = HardwareErrorSourceDxeEntryPoint ++ ++# ++# The following information is for reference only and not required by the build tools. ++# ++# VALID_ARCHITECTURES = RISCV64 ++# ++ ++[Sources] ++ HardwareErrorSourceTableDxe.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ ++[LibraryClasses] ++ UefiDriverEntryPoint ++ BaseLib ++ BaseMemoryLib ++ MemoryAllocationLib ++ UefiLib ++ UefiBootServicesTableLib ++ DebugLib ++ PcdLib ++ SafeIntLib ++ RiscVSbiLib ++ DxeRiscvMpxyLib ++ DxeRiscvRasAgentClientLib ++ ++[Protocols] ++ gEfiAcpiTableProtocolGuid ## CONSUMES ++ ++[Pcd] ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES ++ ++[Guids] ++ gEfiEventReadyToBootGuid ## CONSUMES ## Event ++ ++[UserExtensions.TianoCore."ExtraFiles"] ++ HardwareErrorSourceTableDxeExtra.uni +diff --git a/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.uni b/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.uni +new file mode 100644 +index 00000000..e763c5e5 +--- /dev/null ++++ b/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.uni +@@ -0,0 +1,14 @@ ++// /** @file ++// This module install ACPI Hardware Error Source Table (HEST). ++// ++// Copyright (c) 2024, Ventana Micro Systems, Inc. ++// ++// SPDX-License-Identifier: BSD-2-Clause-Patent ++// ++// **/ ++ ++ ++#string STR_MODULE_ABSTRACT #language en-US "Installs ACPI Hardware Error Source Table (HEST)" ++ ++#string STR_MODULE_DESCRIPTION #language en-US "This module installs the ACPI Hardware Error Source Table (HEST)" ++ +diff --git a/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxeExtra.uni b/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxeExtra.uni +new file mode 100644 +index 00000000..aec90462 +--- /dev/null ++++ b/MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxeExtra.uni +@@ -0,0 +1,14 @@ ++// /** @file ++// HardwareErrorSourceTableDxe Localized Strings and Content ++// ++// Copyright (c) 2024, Ventana Micro Systems, Inc. ++// ++// SPDX-License-Identifier: BSD-2-Clause-Patent ++// ++// **/ ++ ++#string STR_PROPERTIES_MODULE_NAME ++#language en-US ++"ACPI Hardware Error Source Table DXE Driver" ++ ++ +diff --git a/MdePkg/Include/Library/BaseRiscVSbiLib.h b/MdePkg/Include/Library/BaseRiscVSbiLib.h +index 2244165a..a2786927 100644 +--- a/MdePkg/Include/Library/BaseRiscVSbiLib.h ++++ b/MdePkg/Include/Library/BaseRiscVSbiLib.h +@@ -25,6 +25,7 @@ + #define SBI_EXT_DBCN 0x4442434E + #define SBI_EXT_TIME 0x54494D45 + #define SBI_EXT_SRST 0x53525354 ++#define SBI_EXT_MPXY 0x4D505859 + + /* SBI function IDs for base extension */ + #define SBI_EXT_BASE_SPEC_VERSION 0x0 +@@ -46,6 +47,16 @@ + /* SBI function IDs for SRST extension */ + #define SBI_EXT_SRST_RESET 0x0 + ++/* SBI function IDs. for MPXY extension */ ++#define SBI_EXT_MPXY_GET_SHMEM_SIZE 0x0 ++#define SBI_EXT_MPXY_SET_SHMEM 0x1 ++#define SBI_EXT_MPXY_GET_CHANNEL_IDS 0x2 ++#define SBI_EXT_MPXY_READ_ATTRS 0x3 ++#define SBI_EXT_MPXY_WRITE_ATTRS 0x4 ++#define SBI_EXT_MPXY_SEND_MSG_WITH_RESP 0x5 ++#define SBI_EXT_MPXY_SEND_MSG_NO_RESP 0x6 ++#define SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS 0x7 ++ + #define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0 + #define SBI_SRST_RESET_TYPE_COLD_REBOOT 0x1 + #define SBI_SRST_RESET_TYPE_WARM_REBOOT 0x2 +@@ -108,6 +119,19 @@ SbiSystemReset ( + IN UINTN ResetType, + IN UINTN ResetReason + ); ++ ++ /** ++ Probe support for an extension in OpenSBI ++ ++ Check if the extension is supported by SBI ++ ++ @param Extension Extension ID to be probed ++**/ ++EFI_STATUS ++EFIAPI ++SbiProbeExtension( ++ IN UINTN Extension ++ ); + + /** + Get firmware context of the calling hart. +diff --git a/MdePkg/Include/Library/DxeRiscvMpxy.h b/MdePkg/Include/Library/DxeRiscvMpxy.h +new file mode 100644 +index 00000000..c1f4bb2d +--- /dev/null ++++ b/MdePkg/Include/Library/DxeRiscvMpxy.h +@@ -0,0 +1,123 @@ ++/** @file ++ This module implements functions to be used by MPXY client ++ ++ Copyright (c) 2024, Ventana Micro Systems, Inc. ++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#ifndef SBI_MPXY_H_ ++#define SBI_MPXY_H_ ++ ++enum { ++ MpxyChanAttrProtId, ++ MpxyChanAttrProtVersion, ++ MpxyChanAttrMsgDataMaxLen, ++ MpxyChanAttrMsgSendTimeout, ++ MpxyChanAttrMsgCompletionTimeout, ++ MpxyChanAttrChannelCapability, ++ MpxyChanAttrSseEventId, ++ MpxyChanAttrMsiControl, ++ MpxyChanAttrMsiAddrLow, ++ MpxyChanAttrMsiAddrHigh, ++ MpxyChanAttrMsiData, ++ MpxyChanAttrEventStateControl, ++ MpxyChanAttrMax ++}; ++ ++#define MPXY_MSG_PROTO_ATTR_START 0x80000000 ++#define MPXY_MSG_PROTO_ATTR_END 0xffffffff ++ ++/** ++ Get the list of channels available on MPXY. ++ ++ @param[in] StartIndex - Index to start reading from. Initially it will be zero, ++ after subsequent reads, it will be the last index read + 1. ++ @param[out] List of the channels available. ++ @param[out] Number of channels remaining. ++ @param[out] Number of channels retruned in this read. ++ ++ @retval EFI_SUCCESS If list of channels was obtained successfully. ++**/ ++EFI_STATUS ++EFIAPI ++SbiMpxyGetChannelList( ++ IN UINTN StartIndex, ++ OUT UINTN *ChannelList, ++ OUT UINTN *Remaining, ++ OUT UINTN *Returned ++ ); ++ ++/** ++ Read the attributes (both base and protocol specific) of a channel ++ ++ @param[in] Channel for which attributes are to be read ++ @param[in] The base attribute ID ++ @param[in] Number of attributes to be read ++ @param[out] Attributes read from channel from base attributes Id ++ ++ @retval EFI_SUCCESS If the attributes were read successfully ++**/ ++ ++EFI_STATUS ++EFIAPI ++SbiMpxyReadChannelAttrs( ++ IN UINTN ChannelId, ++ IN UINT32 BaseAttrId, ++ IN UINT32 NrAttrs, ++ OUT UINT32 *Attrs ++ ); ++ ++/** ++ Open specified MPXY channel for communication. It will allocate the shared ++ memory or resize the previous one if required. ++ ++ @param[in] ChannelId The channel to be initialized ++ @retval EFI_SUCCESS If the allocation or resize of shared memory was ++ successfully done. ++**/ ++EFI_STATUS ++EFIAPI ++SbiMpxyChannelOpen( ++ IN UINTN ChannelId ++ ); ++ ++/** ++ Close the specified MPXY channel. ++ ++ @param[in] ChannelId The channel to be uninitialized ++ @retval EFI_SUCCESS If the allocation or resize of shared memory was ++ successfully done. ++**/ ++EFI_STATUS ++EFIAPI ++SbiMpxyChannelClose( ++ IN UINTN ChannelId ++ ); ++ ++/** ++ Send a message with response over Mpxy. ++ ++ @param[in] ChannelId The Channel on which message would be sent ++ @param[in] MessageId Message protocol specific message identification ++ @param[in] MessageDataLen Length of the message to be sent ++ @param[in] Message Pointer to buffer containing message ++ @param[in] Response Pointer to buffer to which response should be written ++ @param[in] ResponseLen Pointer where the size of response should be written ++ ++ @retval EFI_SUCCESS The shared memory was disabled ++ @retval Other Some error occured during the operation ++**/ ++EFI_STATUS ++EFIAPI ++SbiMpxySendMessage( ++ IN UINTN ChannelId, ++ IN UINTN MessageId, ++ IN VOID *Message, ++ IN UINTN MessageDataLen, ++ OUT VOID *Response, ++ OUT UINTN *ResponseLen ++ ); ++ ++#endif ++ +diff --git a/MdePkg/Include/Library/DxeRiscvRasAgentClient.h b/MdePkg/Include/Library/DxeRiscvRasAgentClient.h +new file mode 100644 +index 00000000..42a409fc +--- /dev/null ++++ b/MdePkg/Include/Library/DxeRiscvRasAgentClient.h +@@ -0,0 +1,116 @@ ++/** @file ++ This module provides communication with RAS Agent over RPMI/MPXY ++ ++ Copyright (c) 2024, Ventana Micro Systems, Inc. ++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#ifndef _RAS_AGENT_CLIENT_H ++#define _RAS_AGENT_CLIENT_H ++ ++typedef enum { ++ DT_GHESV2, ++ NUM_ERR_DESC_TYPES ++} ErrorDescriptorType; ++ ++#define ERROR_DESCRIPTOR_TYPE_SHIFT 4 ++#define MAX_ERROR_DESCRIPTOR_TYPES (0x1UL << ERROR_DESCRIPTOR_TYPE_SHIFT) ++#define ERROR_DESCRIPTOR_TYPE_MASK (MAX_ERROR_DESCRIPTOR_TYPES - 1) ++ ++/** ++ Initialize the RAS agent client ++ ++ @retval EFI_SUCCESS If initialization is successful ++**/ ++EFI_STATUS ++EFIAPI ++RacInit ( ++ VOID ++ ); ++ ++/** ++ Get the number of hardware error sources from the RAS Agent ++ ++ @param NumErrorSources Pointer to an array of 32-bit integers which will ++ contain number of hardware error sources available. ++ ++ @retval EFI_SUCCESS If fetching the number of error sources succeeded. ++**/ ++EFI_STATUS ++EFIAPI ++RacGetNumberErrorSources( ++ OUT UINT32 *NumErrorSources ++ ); ++ ++/** ++ Get the list of hardware error source IDs from the RAS Agent ++ ++ @param ErrorSourceList Will contain pointer to error of 32-bit integers ++ containing the error source IDs. ++ @param NumSources Will contain the number of IDs in *ErrorSourceList ++ ++ @retval EFI_SUCCESS If fetching the error source IDs succeeded. ++**/ ++EFI_STATUS ++EFIAPI ++RacGetErrorSourceIDList( ++ OUT UINT32 **ErrorSourceList, ++ OUT UINT32 *NumSources ++ ); ++ ++/** ++ Get the hardware error source descriptor for a given error source ID. ++ ++ @param SourceID Error source ID for which descriptor is to be fetched ++ @param DescriptorType Type of error descritor (GHESv2 or platform specific) ++ @param ErrorDesciptor Pointer to buffer containing the descriptor. The caller ++ must free the buffer when done. ++ @param ErrorDescriptorSize Size of the error descriptor buffer in ErrorDescriptor ++ ++ @retval EFI_SUCCESS On success. ++**/ ++EFI_STATUS ++EFIAPI ++RacGetErrorSourceDescriptor( ++ IN UINT32 SourceID, ++ OUT UINTN *DescriptorType, ++ OUT VOID **ErrorDescriptor, ++ OUT UINT32 *ErrorDescriptorSize ++ ); ++ ++/** ++ Get the number of hardware error injection instructions ++ ++ @param NumInstructionEntries Pointer to which number of available instructions ++ are written ++ ++ @retval EFI_SUCCESS On success. ++**/ ++EFI_STATUS ++EFIAPI ++RacGetNumberErrorInjectionEntries( ++ UINT32 *NumInstructionEntries ++ ); ++ ++/** ++ Get an error injection entry ++ ++ @param EinjInstructionIndex Index of the instruction to be fetched. The index runs ++ from 0 to RacGetNumberErrorInjectionEntries()-1. ++ @param EinjInstruction Pointer to the instruction is returned in this pointer-to-pointer. ++ The returned pointer is owned by the callee and should not be freed. ++ @param EinjInstructionSize The size of the instruction returned in EinjInstruction ++ ++ @retval EFI_SUCCESS On success. ++**/ ++ ++EFI_STATUS ++EFIAPI ++RacGetEinjInstruction( ++ IN UINT32 EinjInstructionIndex, ++ OUT VOID **EinjInstruction, ++ OUT UINT32 *EinjInstructionSize ++ ); ++ ++#endif +diff --git a/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c b/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c +index 1141abfa..e5c61215 100644 +--- a/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c ++++ b/MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.c +@@ -168,6 +168,28 @@ SbiSystemReset ( + return TranslateError (Ret.Error); + } + ++/** ++ Probe support for an extension in OpenSBI ++ ++ Check if the extension is supported by SBI ++ ++ @param Extension Extension ID to be probed ++**/ ++EFI_STATUS ++EFIAPI ++SbiProbeExtension( ++ IN UINTN Extension) ++{ ++ SBI_RET Ret; ++ Ret = SbiCall ( ++ SBI_EXT_BASE, ++ SBI_EXT_BASE_PROBE_EXT, ++ 1, ++ Extension); ++ ++ return TranslateError (Ret.Error); ++} ++ + /** + Get firmware context of the calling hart. + +diff --git a/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.c b/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.c +new file mode 100644 +index 00000000..3a258183 +--- /dev/null ++++ b/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.c +@@ -0,0 +1,508 @@ ++/** @file ++ This module implements functions to be used by MPXY client ++ ++ Copyright (c) 2024, Ventana Micro Systems, Inc. ++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define INVAL_PHYS_ADDR (-1U) ++#define INVALID_CHAN -1 ++ ++#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ /* CPU(little-endian) */ ++#define LLE_TO_CPU(x) (SwapBytes64(x)) ++#define CPU_TO_LLE(x) (SwapBytes64(x)) ++#else ++#define LLE_TO_CPU(x) (x) ++#define CPU_TO_LLE(x) (x) ++#endif ++ ++STATIC VOID *gNonChanTempShmem = NULL; ++STATIC VOID * gShmemVirt = NULL; ++STATIC UINTN gNrShmemPages = 0; ++STATIC UINT64 gShmemPhysHi = INVAL_PHYS_ADDR; ++STATIC UINT64 gShmemPhysLo = INVAL_PHYS_ADDR; ++STATIC UINT64 gShmemSize = 0; ++STATIC UINT64 gShmemSet = 0; ++STATIC BOOLEAN gMpxyLibInitialized = FALSE; ++STATIC UINTN gShmemRefCount = 0; ++ ++STATIC ++EFI_STATUS ++EFIAPI ++SbiMpxyGetShmemSize( ++ OUT UINT64 *ShmemSize ++ ) ++{ ++ SBI_RET Ret; ++ ++ Ret = SbiCall ( ++ SBI_EXT_MPXY, ++ SBI_EXT_MPXY_GET_SHMEM_SIZE, ++ 0 ++ ); ++ ++ if (Ret.Error == SBI_SUCCESS) { ++ *ShmemSize = Ret.Value; ++ return EFI_SUCCESS; ++ } ++ ++ return TranslateError (Ret.Error); ++} ++ ++STATIC ++EFI_STATUS ++EFIAPI ++SbiMpxySetShmem( ++ IN UINT64 ShmemPhysHi, ++ IN UINT64 ShmemPhysLo, ++ OUT UINT64 *PrevShmemPhysHi, ++ OUT UINT64 *PrevShmemPhysLo, ++ BOOLEAN ReadBackOldShmem ++ ) ++{ ++ SBI_RET Ret; ++ UINT32 Flags = 0b00; ++ UINT64 *PrevMemDet; ++ ++ if (ReadBackOldShmem) { ++ Flags = 0b01; ++ } ++ ++ Ret = SbiCall ( ++ SBI_EXT_MPXY, ++ SBI_EXT_MPXY_SET_SHMEM, ++ 3, ++ CPU_TO_LLE(ShmemPhysLo), ++ CPU_TO_LLE(ShmemPhysHi), ++ Flags ++ ); ++ ++ if (Ret.Error == SBI_SUCCESS) { ++ if (ShmemPhysLo == INVAL_PHYS_ADDR && ShmemPhysHi == INVAL_PHYS_ADDR) { ++ gShmemPhysHi = INVAL_PHYS_ADDR; ++ gShmemPhysLo = INVAL_PHYS_ADDR; ++ gShmemSet = 0; ++ return EFI_SUCCESS; ++ } ++ ++ gShmemPhysLo = ShmemPhysLo; ++ gShmemPhysHi = ShmemPhysHi; ++ gShmemSet = 1; ++ ++ PrevMemDet = (UINT64 *)gShmemPhysLo; ++ ++ if (ReadBackOldShmem) { ++ *PrevShmemPhysLo = LLE_TO_CPU(PrevMemDet[0]); ++ *PrevShmemPhysHi = LLE_TO_CPU(PrevMemDet[1]); ++ } ++ } ++ ++ return TranslateError (Ret.Error); ++} ++ ++STATIC ++EFI_STATUS ++EFIAPI ++SbiMpxyDisableShmem( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ ++ if (!gShmemSet) ++ return EFI_SUCCESS; ++ ++ Status = SbiMpxySetShmem(INVAL_PHYS_ADDR, ++ INVAL_PHYS_ADDR, ++ NULL, ++ NULL, ++ FALSE ++ ); ++ ++ return Status; ++} ++ ++BOOLEAN ++SbiMpxyShmemInitialized( ++ VOID ++ ) ++{ ++ return (gMpxyLibInitialized); ++} ++ ++STATIC ++BOOLEAN ++SbiMpxyShmemIsSet( ++ VOID ++ ) ++{ ++ return (gShmemSet); ++} ++ ++EFI_STATUS ++EFIAPI ++SbiMpxyGetChannelList( ++ IN UINTN StartIndex, ++ OUT UINTN *ChannelList, ++ OUT UINTN *Remaining, ++ OUT UINTN *Returned ++ ) ++{ ++ UINT64 OPhysHi, OPhysLo; ++ EFI_STATUS Status; ++ SBI_RET Ret; ++ UINT32 *Shmem = gNonChanTempShmem; ++ UINTN i; ++ ++ if (!gMpxyLibInitialized) { ++ return (EFI_DEVICE_ERROR); ++ } ++ ++ /* Set the shared memory to memory allocated for non-channel specific reads */ ++ Status = SbiMpxySetShmem(0, ++ (UINT64)gNonChanTempShmem, ++ &OPhysHi, ++ &OPhysLo, ++ TRUE /* Read back the old address */ ++ ); ++ ++ if (EFI_ERROR(Status)) { ++ return (EFI_DEVICE_ERROR); ++ } ++ ++ Ret = SbiCall (SBI_EXT_MPXY, ++ SBI_EXT_MPXY_GET_CHANNEL_IDS, ++ 1, ++ StartIndex ++ ); ++ ++ if (Ret.Error != SBI_SUCCESS) { ++ return TranslateError (Ret.Error); ++ } ++ ++ /* Index 0 contains number of channels pending to be read */ ++ if (Shmem[0] == 0) ++ *Remaining = 0; ++ ++ /* Number of channels returned */ ++ if (Shmem[1] > 0) { ++ for (i = 0; i < Shmem[1]; i++) { ++ ChannelList[i] = Shmem[i+2]; ++ } ++ } ++ *Returned = Shmem[1]; ++ ++ /* Switch back to old shared memory */ ++ Status = SbiMpxySetShmem(OPhysHi, ++ OPhysLo, ++ NULL, ++ NULL, ++ FALSE /* Read back the old address */ ++ ); ++ ++ if (EFI_ERROR(Status)) { ++ return Status; ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++SbiMpxyReadChannelAttrs( ++ IN UINTN ChannelId, ++ IN UINT32 BaseAttrId, ++ IN UINT32 NrAttrs, ++ OUT UINT32 *Attrs ++ ) ++{ ++ UINT64 OPhysHi, OPhysLo; ++ EFI_STATUS Status; ++ SBI_RET Ret; ++ ++ if (!gMpxyLibInitialized) { ++ return (EFI_DEVICE_ERROR); ++ } ++ ++ /* Set the shared memory to memory allocated for non-channel specific reads */ ++ Status = SbiMpxySetShmem(0, ++ (UINT64)gNonChanTempShmem, ++ &OPhysHi, ++ &OPhysLo, ++ TRUE /* Read back the old address */ ++ ); ++ ++ if (EFI_ERROR(Status)) { ++ return (EFI_DEVICE_ERROR); ++ } ++ ++ Ret = SbiCall ( ++ SBI_EXT_MPXY, ++ SBI_EXT_MPXY_READ_ATTRS, ++ 3, ++ ChannelId, ++ BaseAttrId, /* Base attribute Id */ ++ NrAttrs /* Number of attributes */ ++ ); ++ ++ if (Ret.Error != SBI_SUCCESS) { ++ return TranslateError (Ret.Error); ++ } ++ ++ CopyMem(Attrs, ++ gNonChanTempShmem, ++ sizeof(UINT32) * NrAttrs ++ ); ++ ++ /* Switch back to old shared memory */ ++ Status = SbiMpxySetShmem(OPhysHi, ++ OPhysLo, ++ NULL, ++ NULL, ++ FALSE /* Read back the old address */ ++ ); ++ ++ if (EFI_ERROR(Status)) { ++ return Status; ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++SbiMpxyChannelOpen( ++ IN UINTN ChannelId ++ ) ++{ ++ UINT32 Attributes[MpxyChanAttrMsgDataMaxLen]; // space to read id and version ++ UINT32 ChanDataLen; ++ VOID *SbiShmem; ++ UINTN NrEfiPages; ++ EFI_STATUS Status; ++ ++ if (SbiMpxyShmemInitialized() == FALSE) { ++ return (EFI_UNSUPPORTED); ++ } ++ ++ Status = SbiMpxyReadChannelAttrs(ChannelId, ++ 0, ++ MpxyChanAttrMax, ++ &Attributes[0] ++ ); ++ ++ if (EFI_ERROR(Status)) { ++ return Status; ++ } ++ ++ ChanDataLen = Attributes[MpxyChanAttrMsgDataMaxLen]; ++ NrEfiPages = EFI_SIZE_TO_PAGES(ChanDataLen); ++ ++ /* ++ * If shared memory is already set and if this channel's memory requirement ++ * is more than the current then reallocate memory. ++ */ ++ if (SbiMpxyShmemIsSet()) { ++ /* Does this channel needs bigger shared memory? */ ++ if (ChanDataLen > gShmemSize) { ++ SbiShmem = AllocateAlignedPages (NrEfiPages, ++ EFI_PAGE_SIZE // Align ++ ); ++ ++ if (SbiShmem == NULL) { ++ return (EFI_OUT_OF_RESOURCES); ++ } ++ ++ /* Set the new shared memory */ ++ Status = SbiMpxySetShmem (0, ++ (UINT64)SbiShmem, ++ NULL, ++ NULL, ++ FALSE /* Not interested in old memory */ ++ ); ++ ++ if (EFI_ERROR(Status)) { ++ FreeAlignedPages(SbiShmem, NrEfiPages); ++ return (EFI_DEVICE_ERROR); ++ } ++ ++ /* Free the previous memory */ ++ FreeAlignedPages(gShmemVirt, gNrShmemPages); ++ /* Save the new shared memory */ ++ gShmemVirt = SbiShmem; ++ gNrShmemPages = NrEfiPages; ++ } ++ } else { ++ /* No shared memory yet. Allocate a new one. */ ++ SbiShmem = AllocateAlignedPages (NrEfiPages, ++ EFI_PAGE_SIZE ++ ); ++ ++ if (SbiShmem == NULL) { ++ return (EFI_OUT_OF_RESOURCES); ++ } ++ ++ Status = SbiMpxySetShmem (0, ++ (UINT64)SbiShmem, ++ NULL, ++ NULL, ++ FALSE ++ ); ++ ++ if (EFI_ERROR(Status)) { ++ FreeAlignedPages(SbiShmem, NrEfiPages); ++ return (EFI_DEVICE_ERROR); ++ } ++ /* Save the new shared memory */ ++ gShmemVirt = SbiShmem; ++ gNrShmemPages = NrEfiPages; ++ } ++ ++ /* Increase the reference count */ ++ gShmemRefCount++; ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++SbiMpxyChannelClose( ++ IN UINTN ChannelId ++ ) ++{ ++ EFI_STATUS Status; ++ ++ if (--gShmemRefCount == 0) { ++ /* Ref count is zero. Release the memory */ ++ Status = SbiMpxyDisableShmem(); ++ if (EFI_ERROR(Status)) { ++ return (EFI_DEVICE_ERROR); ++ } ++ ++ FreeAlignedPages(gShmemVirt, gNrShmemPages); ++ } ++ ++ return (EFI_SUCCESS); ++} ++ ++EFI_STATUS ++EFIAPI ++SbiMpxySendMessage( ++ IN UINTN ChannelId, ++ IN UINTN MessageId, ++ IN VOID *Message, ++ IN UINTN MessageDataLen, ++ OUT VOID *Response, ++ OUT UINTN *ResponseLen ++ ) ++{ ++ SBI_RET Ret; ++ UINT64 Phys = gShmemPhysLo; ++ ++ if (!gShmemSet) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ if (MessageDataLen >= gShmemSize) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ /* Copy message to Hart's shared memory */ ++ CopyMem ( ++ (VOID *)Phys, ++ Message, ++ MessageDataLen ++ ); ++ ++ Ret = SbiCall ( ++ SBI_EXT_MPXY, ++ SBI_EXT_MPXY_SEND_MSG_WITH_RESP, ++ 3, ++ ChannelId, ++ MessageId, ++ MessageDataLen ++ ); ++ ++ if (Ret.Error == SBI_SUCCESS && Response) { ++ /* Copy the response to out buffer */ ++ CopyMem ( ++ Response, ++ (const VOID *)Phys, ++ Ret.Value ++ ); ++ } ++ ++ return TranslateError (Ret.Error); ++} ++ ++/** ++ Constructor allocates the global memory to store the registered guid and Handler list. ++ ++ @param ImageHandle The firmware allocated handle for the EFI image. ++ @param SystemTable A pointer to the EFI System Table. ++ ++ @retval RETURN_SUCCESS Allocated the global memory space to store guid and function tables. ++ @retval RETURN_OUT_OF_RESOURCES Not enough memory to allocate. ++**/ ++RETURN_STATUS ++EFIAPI ++SbiMpxyLibConstructor ( ++ IN EFI_HANDLE ImageHandle, ++ IN EFI_SYSTEM_TABLE *SystemTable ++ ) ++{ ++ EFI_STATUS Status; ++ UINT64 ShmemSize; ++ Status = SbiProbeExtension(SBI_EXT_MPXY); ++ ++ ASSERT_EFI_ERROR (Status); ++ ++ Status = SbiMpxyGetShmemSize(&ShmemSize); ++ if (EFI_ERROR(Status)) { ++ DEBUG (( ++ DEBUG_WARN, ++ "%a: Failed to get the shared memory size\n", ++ __func__ ++ )); ++ return 0; ++ } ++ ++ DEBUG (( ++ DEBUG_WARN, ++ "%a: Shared memory size to be allocated: %lu bytes\n", ++ __func__, ShmemSize ++ )); ++ ++ // ++ // Allocate memory to be shared with OpenSBI for initial MPXY communications ++ // untils channels are initialized by their respective drivers. ++ // ++ gNonChanTempShmem = AllocateAlignedPages (EFI_SIZE_TO_PAGES(ShmemSize), ++ ShmemSize // Align ++ ); ++ ++ gShmemSize = ShmemSize; ++ ++ if (gNonChanTempShmem == NULL) { ++ return (0); ++ } ++ ++ gMpxyLibInitialized = TRUE; ++ ++ DEBUG((DEBUG_WARN, "%a: initialization done\n", __func__)); ++ ++ return (0); ++} +diff --git a/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.inf b/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.inf +new file mode 100644 +index 00000000..67e3923b +--- /dev/null ++++ b/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.inf +@@ -0,0 +1,30 @@ ++# @file ++# Provides implementation of the library to communicate over SBI MPXY on RISCV architecture ++# ++# @copyright ++# Copyright (c) Ventana Micro Systems, Inc. All rights reserved. ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++## ++ ++[Defines] ++ INF_VERSION = 1.27 ++ BASE_NAME = DxeRiscvMpxyLib ++ MODULE_UNI_FILE = DxeRiscvMpxy.uni ++ FILE_GUID = 8e992db5-4383-4023-a24e-7c99955bde80 ++ MODULE_TYPE = DXE_DRIVER ++ VERSION_STRING = 1.0 ++ LIBRARY_CLASS = DxeRiscvMpxyLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER ++ CONSTRUCTOR = SbiMpxyLibConstructor ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ ++[Sources] ++ DxeRiscvMpxy.c ++ ++[LibraryClasses] ++ DebugLib ++ UefiBootServicesTableLib ++ RiscVSbiLib ++ SafeIntLib +diff --git a/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.uni b/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.uni +new file mode 100644 +index 00000000..a6652cdf +--- /dev/null ++++ b/MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.uni +@@ -0,0 +1,15 @@ ++// @file ++// Instance of SBI MPXY library for RISC-V architecutre. ++// ++// MpxyLib. ++// ++// Copyright (c) Ventana Micro Systems, Inc. ++// ++// SPDX-License-Identifier: BSD-2-Clause-Patent ++// ++ ++ ++#string STR_MODULE_ABSTRACT #language en-US "Instance of SbiMpxy Library" ++ ++#string STR_MODULE_DESCRIPTION #language en-US "Library that provides implementation of SBI Mpxy on RISC-V architecture" ++ +diff --git a/MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClient.c b/MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClient.c +new file mode 100644 +index 00000000..c07dc79f +--- /dev/null ++++ b/MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClient.c +@@ -0,0 +1,421 @@ ++/** @file ++ This module provides communication with RAS Agent over RPMI/MPXY ++ ++ Copyright (c) 2024, Ventana Micro Systems, Inc. ++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_SOURCES 512 ++#define MAX_DESC_SIZE 1024 ++ ++/* RAS Agent Services on MPXY/RPMI */ ++#define RAS_GET_NUM_ERR_SRCS 0x1 ++#define RAS_GET_ERR_SRCS_ID_LIST 0x2 ++#define RAS_GET_ERR_SRC_DESC 0x3 ++#define RAS_EINJ_GET_NUM_INSTRUCTIONS 0x4 ++#define RAS_EINJ_GET_INSTRUCTION 0x5 ++#define RAS_EINJ_EXECUTE_OPERATION 0x6 ++#define RAS_EINJ_TRIGGER_ERROR 0x7 ++ ++#define __packed32 __attribute__((packed,aligned(__alignof__(UINT32)))) ++ ++int RacInitialized = 0; ++ ++typedef struct __packed32 { ++ UINT32 status; ++ UINT32 flags; ++ UINT32 remaining; ++ UINT32 returned; ++} RasRpmiRespHeader; ++ ++typedef struct __packed32 { ++ RasRpmiRespHeader RespHdr; ++ UINT32 ErrSourceList[MAX_SOURCES]; ++} ErrorSourceListResp; ++ ++typedef struct __packed32 { ++ RasRpmiRespHeader RspHdr; ++ UINT8 desc[MAX_DESC_SIZE]; ++} ErrDescResp; ++ ++static ErrorSourceListResp gErrorSourceListResp; ++static ErrDescResp gErrDescResp; ++UINT32 gMpxyChannelId = 0; ++ ++#if CHANNEL_FROM_FDT ++STATIC ++EFI_STATUS ++EFIAPI ++GetRasAgentMpxyChannelIdFromFDT( ++ OUT UINT32 *ChannelId ++ ) ++{ ++ EFI_STATUS Status; ++ FDT_CLIENT_PROTOCOL *FdtClient; ++ INT32 Node; ++ CONST UINT64 *Reg; ++ UINT32 RegSize; ++ UINT32 RegBase; ++ ++ Status = gBS->LocateProtocol ( ++ &gFdtClientProtocolGuid, ++ NULL, ++ (VOID **)&FdtClient ++ ); ++ ++ ASSERT_EFI_ERROR (Status); ++ ++ Status = FdtClient->FindCompatibleNode (FdtClient, "riscv,sbi-mpxy-ras-agent", &Node); ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG (( ++ DEBUG_WARN, ++ "%a: No 'riscv,sbi-mpxy-ras-agent' compatible DT node found\n", ++ __func__ ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ Status = FdtClient->GetNodeProperty ( ++ FdtClient, ++ Node, ++ "riscv,sbi-mpxy-channel-id", ++ (CONST VOID **)&Reg, ++ &RegSize ++ ); ++ if (EFI_ERROR (Status)) { ++ DEBUG (( ++ DEBUG_WARN, ++ "%a: No 'riscv,sbi-mpxy-channel-id' compatible DT node found\n", ++ __func__ ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ ASSERT (RegSize == 4); ++ ++ RegBase = SwapBytes32 (Reg[0]); ++ ++ *ChannelId = RegBase; ++ ++ return EFI_SUCCESS; ++} ++#endif ++ ++STATIC ++EFI_STATUS ++EFIAPI ++ProbeRasAgentMpxyChannelId( ++ OUT UINT32 *ChannelId ++ ) ++{ ++#define MAX_MPXY_CHANNELS 64 ++ UINTN ChannelList[MAX_MPXY_CHANNELS]; ++ UINTN Returned, Remaining, StartIndex = 0; ++ EFI_STATUS Status; ++ BOOLEAN Found = FALSE, ParsingDone = FALSE; ++ UINTN i, Id; ++ UINT32 RasSrvGroup; ++ ++ while (!ParsingDone) { ++ Status = SbiMpxyGetChannelList( ++ StartIndex, /* Start index */ ++ &ChannelList[0], ++ &Remaining, ++ &Returned ++ ); ++ ++ if (Status != EFI_SUCCESS) ++ return Status; ++ ++ /* This read has returned zero and we still haven't got what we need */ ++ if (Returned == 0) ++ return EFI_UNSUPPORTED; ++ ++ for (i = 0; i < Returned; i++) { ++ Id = ChannelList[0]; ++ Status = SbiMpxyReadChannelAttrs( ++ Id, ++ MPXY_MSG_PROTO_ATTR_START, /* Base attribute Id */ ++ 1, /* Number of attributes to be read */ ++ &RasSrvGroup ++ ); ++ ++ if (Status != EFI_SUCCESS) ++ continue; ++ ++ if (RasSrvGroup == 0xC) { ++ Found = TRUE; ++ ParsingDone = TRUE; ++ break; ++ } ++ } ++ ++ /* Read if some more to be read else we are done parsing */ ++ if (Remaining) { ++ StartIndex = Returned; ++ continue; ++ } else { ++ ParsingDone = TRUE; ++ } ++ } ++ ++ if (Found == TRUE) { ++ *ChannelId = Id; ++ DEBUG((DEBUG_INFO, ++ "Found RAS MPXY channel: %x\n", Id)); ++ } ++ ++ return Status; ++} ++ ++EFI_STATUS ++EFIAPI ++GetRasAgentMpxyChannelId( ++ OUT UINT32 *ChannelId ++ ) ++{ ++#if CHANNEL_FROM_FDT ++ return GetRasAgentMpxyChannelIdFromFDT(ChannelId); ++#else ++ return ProbeRasAgentMpxyChannelId(ChannelId); ++#endif ++} ++ ++EFI_STATUS ++EFIAPI ++RacInit ( ++ VOID ++ ) ++{ ++ if (RacInitialized == 0) { ++ if (GetRasAgentMpxyChannelId (&gMpxyChannelId) != EFI_SUCCESS) ++ return EFI_NOT_READY; ++ ++ if (SbiMpxyChannelOpen (gMpxyChannelId) != EFI_SUCCESS) ++ return EFI_NOT_READY; ++ ++ DEBUG((DEBUG_ERROR, "Rac Init Done\n")); ++ RacInitialized = 1; ++ } else { ++ DEBUG((DEBUG_ERROR, "Rac already initilized: MpxyChannel: %u\n", gMpxyChannelId)); ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++RacGetNumberErrorSources( ++ UINT32 *NumErrorSources ++ ) ++{ ++ struct __packed32 _NumErrSrc { ++ RasRpmiRespHeader RespHdr; ++ UINT32 NumErrorSources; ++ } RasMsgBuf; ++ ++ EFI_STATUS Status; ++ RasRpmiRespHeader *RespHdr = &RasMsgBuf.RespHdr; ++ UINTN RespLen = sizeof(RasMsgBuf); ++ ++ ZeroMem (&RasMsgBuf, sizeof(RasMsgBuf)); ++ ++ Status = SbiMpxySendMessage (gMpxyChannelId, ++ RAS_GET_NUM_ERR_SRCS, ++ &RasMsgBuf, ++ sizeof(UINT32), ++ (VOID *)&RasMsgBuf, ++ &RespLen ++ ); ++ if (Status != EFI_SUCCESS) ++ return Status; ++ ++ if (RespHdr->status != 0) ++ return EFI_DEVICE_ERROR; ++ ++ *NumErrorSources = RasMsgBuf.NumErrorSources; ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++RacGetErrorSourceIDList( ++ OUT UINT32 **ErrorSourceList, ++ OUT UINT32 *NumSources ++ ) ++{ ++ UINT32 *RespData = &gErrorSourceListResp.ErrSourceList[0]; ++ RasRpmiRespHeader *RespHdr = &gErrorSourceListResp.RespHdr; ++ EFI_STATUS Status; ++ UINTN RespLen = sizeof(gErrorSourceListResp); ++ ++ ZeroMem(&gErrorSourceListResp, sizeof(gErrorSourceListResp)); ++ ++ if (!ErrorSourceList) ++ return EFI_INVALID_PARAMETER; ++ ++ Status = SbiMpxySendMessage(gMpxyChannelId, ++ RAS_GET_ERR_SRCS_ID_LIST, ++ &gErrorSourceListResp, ++ sizeof(gErrorSourceListResp), ++ &gErrorSourceListResp, ++ &RespLen); ++ ++ if (Status != EFI_SUCCESS) ++ return Status; ++ ++ if (RespHdr->status != 0) ++ return EFI_DEVICE_ERROR; ++ ++ *NumSources = RespHdr->returned; ++ *ErrorSourceList = RespData; ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++RacGetErrorSourceDescriptor( ++ IN UINT32 SourceID, ++ OUT UINTN *DescriptorType, ++ OUT VOID **ErrorDescriptor, ++ OUT UINT32 *ErrorDescriptorSize ++ ) ++{ ++ UINTN RespLen = sizeof(gErrDescResp); ++ EFI_STATUS Status; ++ RasRpmiRespHeader *RspHdr = &gErrDescResp.RspHdr; ++ UINT8 *desc = &gErrDescResp.desc[0]; ++ UINT32 *EID = (UINT32 *)&gErrDescResp; ++ ++ ZeroMem(&gErrDescResp, sizeof(gErrDescResp)); ++ ++ *EID = SourceID; ++ ++ Status = SbiMpxySendMessage(gMpxyChannelId, ++ RAS_GET_ERR_SRC_DESC, ++ &gErrDescResp, ++ sizeof(gErrDescResp), ++ &gErrDescResp, ++ &RespLen); ++ ++ if (Status != EFI_SUCCESS) ++ return Status; ++ ++ if (RspHdr->status != 0) ++ return EFI_DEVICE_ERROR; ++ ++ if (RspHdr->remaining != 0) ++ return EFI_DEVICE_ERROR; ++ ++ *DescriptorType = RspHdr->flags & ERROR_DESCRIPTOR_TYPE_MASK; ++ ++ ASSERT(*DescriptorType < MAX_ERROR_DESCRIPTOR_TYPES); ++ ++ *ErrorDescriptor = (VOID *)desc; ++ *ErrorDescriptorSize = RspHdr->returned; ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++RacGetNumberErrorInjectionEntries( ++ UINT32 *NumInstructionEntries ++ ) ++{ ++ struct __packed32 _NumInst { ++ RasRpmiRespHeader RespHdr; ++ UINT32 NumInstructions; ++ } RasMsgBuf; ++ ++ EFI_STATUS Status; ++ RasRpmiRespHeader *RespHdr = &RasMsgBuf.RespHdr; ++ UINTN RespLen = sizeof(RasMsgBuf); ++ ++ ZeroMem (&RasMsgBuf, sizeof(RasMsgBuf)); ++ ++ Status = SbiMpxySendMessage (gMpxyChannelId, ++ RAS_EINJ_GET_NUM_INSTRUCTIONS, ++ &RasMsgBuf, ++ sizeof(UINT32), ++ (VOID *)&RasMsgBuf, ++ &RespLen ++ ); ++ if (Status != EFI_SUCCESS) { ++ return Status; ++ } ++ ++ if (RespHdr->status != 0) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ *NumInstructionEntries = RasMsgBuf.NumInstructions; ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++RacGetEinjInstruction( ++ IN UINT32 EinjInstructionIndex, ++ OUT VOID **EinjInstruction, ++ OUT UINT32 *EinjInstructionSize ++ ) ++{ ++ UINTN RespLen = sizeof(gErrDescResp); ++ EFI_STATUS Status; ++ RasRpmiRespHeader *RspHdr = &gErrDescResp.RspHdr; ++ UINT8 *Instruction = &gErrDescResp.desc[0]; ++ UINT32 *IID= (UINT32 *)&gErrDescResp.desc[0]; ++ ++ ZeroMem(&gErrDescResp, sizeof(gErrDescResp)); ++ ++ *IID = EinjInstructionIndex; ++ Status = SbiMpxySendMessage(gMpxyChannelId, ++ RAS_EINJ_GET_INSTRUCTION, ++ &gErrDescResp, ++ sizeof(gErrDescResp), ++ &gErrDescResp, ++ &RespLen); ++ ++ if (Status != EFI_SUCCESS) ++ return Status; ++ ++ if (RspHdr->status != 0) ++ return EFI_DEVICE_ERROR; ++ ++ if (RspHdr->remaining != 0) ++ return EFI_DEVICE_ERROR; ++ ++ *EinjInstruction = (VOID *)Instruction; ++ *EinjInstructionSize = RspHdr->returned; ++ ++ return EFI_SUCCESS; ++} +diff --git a/MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClientLib.inf b/MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClientLib.inf +new file mode 100644 +index 00000000..23bf2a37 +--- /dev/null ++++ b/MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClientLib.inf +@@ -0,0 +1,38 @@ ++# @file ++# Provides implementation of the library class RasAgentClient for RAS on RISC-V architecture ++# ++# @copyright ++# Copyright (c) Ventana Micro Systems, Inc. ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++## ++ ++[Defines] ++ INF_VERSION = 1.27 ++ BASE_NAME = DxeRiscvRasAgentClientLib ++ MODULE_UNI_FILE = DxeRiscvRasAgentClient.uni ++ FILE_GUID = d1342a6d-43fb-41e4-a998-2227461c1901 ++ MODULE_TYPE = DXE_DRIVER ++ VERSION_STRING = 1.0 ++ LIBRARY_CLASS = DxeRiscvRasAgentClientLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ EmbeddedPkg/EmbeddedPkg.dec ++ ++[Sources] ++ DxeRiscvRasAgentClient.c ++ ++[LibraryClasses] ++ DebugLib ++ UefiBootServicesTableLib ++ RiscVSbiLib ++ SafeIntLib ++ DxeRiscvMpxyLib ++ ++[Protocols] ++ gFdtClientProtocolGuid ## CONSUMES ++ ++[Depex] ++ gFdtClientProtocolGuid ++ +diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc +index 34b20378..cd9fce95 100644 +--- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc ++++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc +@@ -83,6 +83,8 @@ + QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf + QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf + QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf ++ DxeRiscvMpxyLib|MdePkg/Library/DxeRiscvMpxyLib/DxeRiscvMpxy.inf ++ DxeRiscvRasAgentClientLib|MdePkg/Library/DxeRiscvRasAgentClientLib/DxeRiscvRasAgentClientLib.inf + + TimerLib|UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/BaseRiscV64CpuTimerLib.inf + VirtNorFlashPlatformLib|OvmfPkg/RiscVVirt/Library/VirtNorFlashPlatformLib/VirtNorFlashDeviceTreeLib.inf +@@ -500,6 +502,8 @@ + # + OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf + MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf ++ MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.inf ++ MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.inf + OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf { + + NULL|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf +diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf b/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf +index 40d12e0f..afe41100 100644 +--- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf ++++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf +@@ -179,6 +179,8 @@ INF OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf + INF OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf + INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf ++INF MdeModulePkg/Universal/Acpi/AcpiHardwareErrorTableDxe/HardwareErrorSourceTableDxe.inf ++INF MdeModulePkg/Universal/Acpi/AcpiErrorInjectionTableDxe/ErrorInjectionTableDxe.inf + INF OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf + + # +-- +2.27.0 + diff --git a/edk2.spec b/edk2.spec index 022bbffb7aaea5ef4a403bb550c2e5a53019038a..a2287abc5ed33c4b4b85a167946e77fcbc64b1b7 100644 --- a/edk2.spec +++ b/edk2.spec @@ -7,7 +7,7 @@ Name: edk2 Version: %{stable_date} -Release: 29 +Release: 30 Summary: EFI Development Kit II License: BSD-2-Clause-Patent and OpenSSL and MIT URL: https://github.com/tianocore/edk2 @@ -198,6 +198,10 @@ Patch122: 0122-OvmfPkg-OvmfPkgX64-Set-default-value-of-CC_MEASUREME.patch # Fix CVE-2025-9230 Patch123: 0123-kek_unwrap_key-Fix-incorrect-check-of-unwrapped-key-.patch +#Add AcpiErrorInjectionTableDxe and AcpiHardwareErrorTableDxe for OS RAS SSE validation +patch124: 0124-Backport-Add-AcpiErrorInjectionTableDxe-and-AcpiHardwareErrorTableDxe-Support-for-OS-RAS-SSE-Validation.patch + + BuildRequires: acpica-tools gcc gcc-c++ libuuid-devel python3 bc nasm python3-unversioned-command isl %ifarch x86_64 @@ -509,6 +513,9 @@ chmod +x %{buildroot}%{_bindir}/Rsa2048Sha256GenerateKeys %endif %changelog +* Mon Nov 11 2025 liuqingtao - 202308-30 +- Add AcpiErrorInjectionTableDxe and AcpiHardwareErrorTableDxe Support for OS RAS SSE validation + * Thu Nov 6 2025 zhangpengrui - 202308-29 - Fix Patch Name Build Error