edk2/OvmfPkg/MemDebugLogPei/MemDebugLog.c
Aaron Young 57844e4997 OvmfPkg: Add OVMF Memory Debug Logging MemDebugLogPei PEIM
Add the OvmfPkg MemDebugLogPei PEI Module which
is responsible for allocating and initializing the main
memory log buffer.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Aaron Young <aaron.young@oracle.com>
2025-06-13 22:19:39 +00:00

151 lines
4.2 KiB
C

/** @file
Memory Debug Log PEIM
Copyright (C) 2025, Oracle and/or its affiliates.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PcdLib.h>
#include <Library/MemDebugLogLib.h>
EFI_STATUS
EFIAPI
MemDebugLogMemAvailCB (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
);
CONST EFI_PEI_NOTIFY_DESCRIPTOR mMemAvailNotifyList[] = {
{
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiMemoryDiscoveredPpiGuid,
MemDebugLogMemAvailCB
}
};
EFI_STATUS
EFIAPI
MemDebugLogMemAvailCB (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
UINT32 MemDebugLogBufPages;
EFI_PHYSICAL_ADDRESS MemDebugLogBufAddr;
EFI_HOB_GUID_TYPE *GuidHob;
MEM_DEBUG_LOG_HOB_DATA *HobData;
EFI_STATUS Status;
MemDebugLogBufPages = MemDebugLogPages ();
//
// Buffer size of 0 disables memory debug logging.
//
if (!MemDebugLogBufPages) {
MemDebugLogBufAddr = 0;
Status = EFI_SUCCESS;
goto done;
}
//
// Allocate the memory debug log buffer.
// NOTE: We allocate the buffer as type EfiRuntimeServicesData
// as this seems to allow the buffer to persist and be
// accessible/modifiable throughout runtime (i.e. and avoid
// being locked down by the MemoryAttributesTable code).
//
Status = PeiServicesAllocatePages (
EfiRuntimeServicesData,
MemDebugLogBufPages,
&MemDebugLogBufAddr
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to allocate Memory Debug Log buffer: %r. Logging disabled\n", __func__, Status));
MemDebugLogBufAddr = 0;
goto done;
}
//
// Init the debug log buffer
//
Status = MemDebugLogInit (MemDebugLogBufAddr, (UINT32)EFI_PAGES_TO_SIZE ((UINTN)MemDebugLogBufPages));
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to init Memory Debug Log buffer: %r. Logging disabled\n", __func__, Status));
PeiServicesFreePages (MemDebugLogBufAddr, MemDebugLogBufPages);
MemDebugLogBufAddr = 0;
goto done;
}
//
// Copy over the messages from the Early Debug Log buffer.
//
if (FixedPcdGet32 (PcdOvmfEarlyMemDebugLogBase) != 0) {
MemDebugLogCopy (MemDebugLogBufAddr, (EFI_PHYSICAL_ADDRESS)(UINTN)FixedPcdGet32 (PcdOvmfEarlyMemDebugLogBase));
}
done:
//
// Zero the early buffer if we successfully
// created the main memory log buffer.
//
if ((Status == EFI_SUCCESS) && (FixedPcdGet32 (PcdOvmfEarlyMemDebugLogBase) != 0)) {
ZeroMem (
(VOID *)(UINTN)FixedPcdGet32 (PcdOvmfEarlyMemDebugLogBase),
(UINT32)FixedPcdGet32 (PcdOvmfEarlyMemDebugLogSize)
);
}
//
// Create HOB to pass mem debug log buffer addr
//
Status = PeiServicesCreateHob (
EFI_HOB_TYPE_GUID_EXTENSION,
(UINT16)(sizeof (EFI_HOB_GUID_TYPE) + sizeof (MEM_DEBUG_LOG_HOB_DATA)),
(VOID **)&GuidHob
);
if (EFI_ERROR (Status)) {
if (MemDebugLogBufAddr) {
PeiServicesFreePages (MemDebugLogBufAddr, MemDebugLogBufPages);
}
} else {
//
// Populate the HOB
//
CopyGuid (&GuidHob->Name, &gMemDebugLogHobGuid);
HobData = (MEM_DEBUG_LOG_HOB_DATA *)GET_GUID_HOB_DATA (GuidHob);
HobData->MemDebugLogBufAddr = MemDebugLogBufAddr;
}
return Status;
}
EFI_STATUS
EFIAPI
MemDebugLogEntry (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
//
// Setup callback for memory available notification
//
Status = PeiServicesNotifyPpi (mMemAvailNotifyList);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to create MemDebugLog PEIM Callback: %r. Logging disabled\n", __func__, Status));
}
return Status;
}