summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Library/EdkMemoryStatusCodeLib
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
commit878ddf1fc3540a715f63594ed22b6929e881afb4 (patch)
treec56c44dac138137b510e1fba7c3efe5e4d84bea2 /EdkModulePkg/Library/EdkMemoryStatusCodeLib
downloadedk2-platforms-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.xz
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Library/EdkMemoryStatusCodeLib')
-rw-r--r--EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.mbd30
-rw-r--r--EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.msa63
-rw-r--r--EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.c498
-rw-r--r--EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.h94
-rw-r--r--EdkModulePkg/Library/EdkMemoryStatusCodeLib/build.xml47
5 files changed, 732 insertions, 0 deletions
diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.mbd b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.mbd
new file mode 100644
index 0000000000..01e0cb2e4a
--- /dev/null
+++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.mbd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<LibraryModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdLibHeader>
+ <BaseName>EdkMemoryStatusCodeLib</BaseName>
+ <Guid>e2368d1d-4c94-4e62-be2f-7817bbd78293</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:19</Modified>
+ </MbdLibHeader>
+</LibraryModuleBuildDescription>
diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.msa b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.msa
new file mode 100644
index 0000000000..6ad58a20e4
--- /dev/null
+++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.msa
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<LibraryModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaLibHeader>
+ <BaseName>EdkMemoryStatusCodeLib</BaseName>
+ <ModuleType>PEIM</ModuleType>
+ <ComponentType>LIBRARY</ComponentType>
+ <Guid>e2368d1d-4c94-4e62-be2f-7817bbd78293</Guid>
+ <Version>0</Version>
+ <Abstract>Memory Status Code Library for UEFI drivers</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:19</Updated>
+ </MsaLibHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_PRODUCED">EdkMemoryStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeiServicesTablePointerLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>MemoryStatusCode.c</Filename>
+ <Filename>MemoryStatusCode.h</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Hobs>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
+ <Name>StatusCodeMemoryPpi</Name>
+ <C_Name>gPeiStatusCodeMemoryPpiGuid</C_Name>
+ <Guid>0x26f8ab01, 0xd3cd, 0x489c, 0x98, 0x4f, 0xdf, 0xde, 0xf7, 0x68, 0x39, 0x5b</Guid>
+ </Hob>
+ </Hobs>
+ <PPIs>
+ <Ppi Usage="SOMETIMES_PRODUCED">StatusCodeMemory</Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">StatusCode</Ppi>
+ <PpiNotify Usage="SOMETIMES_CONSUMED">FvFileLoader</PpiNotify>
+ </PPIs>
+</LibraryModuleSurfaceArea>
diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.c b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.c
new file mode 100644
index 0000000000..1661d7753c
--- /dev/null
+++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.c
@@ -0,0 +1,498 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MemoryStatusCode.c
+
+Abstract:
+
+ Lib to provide memory journal status code reporting Routines.
+
+--*/
+#include "MemoryStatusCode.h"
+
+//
+// Global variable. Not accessible while running from flash.
+// After we relocate ourselves into memory, we update this
+// and use it to determine if we are running from flash or memory.
+//
+
+//
+// Global variable used to replace the PPI once we start running from memory.
+//
+PEI_STATUS_CODE_MEMORY_PPI mStatusCodeMemoryPpi = { 0, 0, 0, 0 };
+
+//
+// PPI descriptor for the MonoStatusCode PEIM, see MonoStatusCode.c
+//
+extern EFI_PEI_PPI_DESCRIPTOR mPpiListStatusCode;
+
+EFI_STATUS
+EFIAPI
+MemoryStatusCodeInitialize (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+
+Routine Description:
+
+ Initialization routine.
+ Allocates heap space for storing Status Codes.
+ Installs a PPI to point to that heap space.
+ Installs a callback to switch to memory.
+ Installs a callback to
+
+Arguments:
+
+ FfsHeader - FV this PEIM was loaded from.
+ PeiServices - General purpose services available to every PEIM.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ MEMORY_STATUS_CODE_INSTANCE *PrivateData;
+ PEI_STATUS_CODE_MEMORY_PPI *StatusCodeMemoryPpi;
+ EFI_PEI_PROGRESS_CODE_PPI *ReportStatusCodePpi;
+ EFI_PHYSICAL_ADDRESS Buffer;
+ VOID *StartPointer;
+ UINTN Length;
+ UINTN LastEntry;
+ EFI_PEI_PPI_DESCRIPTOR *ReportStatusCodeDescriptor;
+ EFI_PEI_PPI_DESCRIPTOR *StatusCodeMemoryDescriptor;
+
+ //
+ // Determine if we are being called after relocation into memory.
+ //
+ if (!gRunningFromMemory) {
+ //
+ // If we are not running from memory, we need to allocate some heap and
+ // install the PPI
+ //
+ //
+ // Allocate heap storage for the journal
+ //
+ Status = (*PeiServices)->AllocatePool (
+ PeiServices,
+ PEI_STATUS_CODE_HEAP_LENGTH,
+ &StartPointer
+ );
+
+ //
+ // This is not a required feature to boot.
+ //
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate heap storage for private data
+ // The private data contains the FFS header for this PEIM,
+ // a PPI containing information about the status code journal, and
+ // a notification for the LoadFile service, to relocate the PEIM into
+ // memory.
+ //
+ Status = (*PeiServices)->AllocatePool (
+ PeiServices,
+ sizeof (MEMORY_STATUS_CODE_INSTANCE),
+ (VOID **) &PrivateData
+ );
+
+ //
+ // This is not a required feature to boot.
+ //
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Update the contents of the private data.
+ //
+ PrivateData->Signature = MEMORY_STATUS_CODE_SIGNATURE;
+ PrivateData->This = PrivateData;
+ PrivateData->FfsHeader = FfsHeader;
+ PrivateData->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid;
+ PrivateData->PpiDescriptor.Ppi = &PrivateData->StatusCodeMemoryPpi;
+ PrivateData->StatusCodeMemoryPpi.FirstEntry = 0;
+ PrivateData->StatusCodeMemoryPpi.LastEntry = 0;
+ PrivateData->StatusCodeMemoryPpi.Address = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPointer;
+ PrivateData->StatusCodeMemoryPpi.Length = PEI_STATUS_CODE_HEAP_LENGTH;
+ PrivateData->NotifyDescriptor.Flags =
+ (
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
+ );
+ PrivateData->NotifyDescriptor.Guid = &gEfiPeiFvFileLoaderPpiGuid;
+ PrivateData->NotifyDescriptor.Notify = LoadImageCallback;
+
+ //
+ // Publish the PPI
+ //
+ Status = (*PeiServices)->InstallPpi (PeiServices, &PrivateData->PpiDescriptor);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Post a callback to relocate to memory
+ //
+ Status = (**PeiServices).NotifyPpi (PeiServices, &PrivateData->NotifyDescriptor);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ //
+ // If we are running from memory, we need to copy from the heap to a RT
+ // memory buffer.
+ //
+ //
+ // Locate Journal
+ //
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gPeiStatusCodeMemoryPpiGuid,
+ 0,
+ &StatusCodeMemoryDescriptor,
+ (VOID **) &StatusCodeMemoryPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get private data
+ //
+ PrivateData = _CR (StatusCodeMemoryDescriptor, MEMORY_STATUS_CODE_INSTANCE, PpiDescriptor);
+ //
+ // At this point, we need to fix up any addresses that we have as the heap
+ // has moved.
+ //
+ PrivateData->PpiDescriptor.Ppi = &PrivateData->StatusCodeMemoryPpi;
+ PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid;
+ PrivateData->StatusCodeMemoryPpi.Address = PrivateData->StatusCodeMemoryPpi.Address +
+ (UINTN) PrivateData - (UINTN) PrivateData->This;
+ PrivateData->NotifyDescriptor.Guid = &gEfiPeiFvFileLoaderPpiGuid;
+ PrivateData->NotifyDescriptor.Notify = LoadImageCallback;
+ PrivateData->This = PrivateData;
+
+ //
+ // Allocate RT memory.
+ //
+ Status = (*PeiServices)->AllocatePages (
+ PeiServices,
+ EfiRuntimeServicesData,
+ PEI_STATUS_CODE_RT_PAGES,
+ &Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG_CODE (
+ ZeroMem ((VOID *) (UINTN) Buffer, PEI_STATUS_CODE_RT_LENGTH);
+ );
+
+ //
+ // Copy the heap to the allocated memory.
+ // Unwind the rolling queue to start at 0 in the new space. We need to do
+ // this because the new queue is much bigger than the heap allocation.
+ //
+ if (PEI_STATUS_CODE_RT_LENGTH <= PEI_STATUS_CODE_HEAP_LENGTH) {
+ return Status;
+ }
+
+ if (StatusCodeMemoryPpi->LastEntry >= StatusCodeMemoryPpi->FirstEntry) {
+ LastEntry = StatusCodeMemoryPpi->LastEntry - StatusCodeMemoryPpi->FirstEntry;
+ StartPointer = (VOID *) ((UINTN) StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY)));
+ Length = (StatusCodeMemoryPpi->LastEntry - StatusCodeMemoryPpi->FirstEntry) * sizeof (EFI_STATUS_CODE_ENTRY);
+ (*PeiServices)->CopyMem ((VOID *) (UINTN) Buffer, StartPointer, Length);
+ } else {
+ //
+ // The last entry will be the new last entry after moving heap to buffer
+ //
+ LastEntry = (PEI_STATUS_CODE_MAX_HEAP_ENTRY - StatusCodeMemoryPpi->FirstEntry) + StatusCodeMemoryPpi->LastEntry;
+ //
+ // Copy from the first entry to the end of the heap
+ //
+ StartPointer = (VOID *) ((UINTN) StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY)));
+ Length = PEI_STATUS_CODE_HEAP_LENGTH - (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY));
+ (*PeiServices)->CopyMem ((VOID *) (UINTN) Buffer, StartPointer, Length);
+ //
+ // Copy from the start to the heap to the last entry
+ //
+ StartPointer = (VOID *) (UINTN) StatusCodeMemoryPpi->Address;
+ (*PeiServices)->CopyMem (
+ (VOID *) (UINTN) (Buffer + Length),
+ StartPointer,
+ (StatusCodeMemoryPpi->LastEntry * sizeof (EFI_STATUS_CODE_ENTRY))
+ );
+ };
+
+ //
+ // Update the PPI to NULL, so it will not be used.
+ //
+ StatusCodeMemoryPpi->FirstEntry = 0;
+ StatusCodeMemoryPpi->LastEntry = 0;
+ StatusCodeMemoryPpi->Address = 0;
+ StatusCodeMemoryPpi->Length = 0;
+
+ //
+ // Update in memory version of PPI that will be used.
+ //
+ mStatusCodeMemoryPpi.FirstEntry = 0;
+ mStatusCodeMemoryPpi.LastEntry = LastEntry;
+ mStatusCodeMemoryPpi.Address = (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer;
+ mStatusCodeMemoryPpi.Length = PEI_STATUS_CODE_RT_LENGTH;
+
+ //
+ // Reinstall the report status code function
+ //
+ //
+ // Locate status code PPI
+ //
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gEfiPeiStatusCodePpiGuid,
+ 0,
+ &ReportStatusCodeDescriptor,
+ (VOID **) &ReportStatusCodePpi
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Reinstall the ReportStatusCode interface using the memory-based
+ // descriptor
+ //
+ Status = (*PeiServices)->ReInstallPpi (
+ PeiServices,
+ ReportStatusCodeDescriptor,
+ &mPpiListStatusCode
+ );
+ if (EFI_ERROR (Status)) {
+ CpuBreakpoint ();
+ return Status;
+ }
+ //
+ // Publish a GUIDed HOB that contains a pointer to the status code PPI
+ // structure. This is a bit of a short cut as I just used the PPI GUID to
+ // identify the HOB. This HOB is caught by the DXE status code memory
+ // listener and used to find the journal.
+ //
+ StatusCodeMemoryPpi = &mStatusCodeMemoryPpi;
+
+ BuildGuidDataHob (
+ &gPeiStatusCodeMemoryPpiGuid,
+ &StatusCodeMemoryPpi,
+ sizeof (VOID *)
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MemoryReportStatusCode (
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN UINT32 Instance,
+ IN EFI_GUID * CallerId,
+ IN EFI_STATUS_CODE_DATA * Data OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Provide a memory status code
+
+Arguments:
+
+ Same as ReportStatusCode PPI
+
+Returns:
+
+ EFI_SUCCESS This function always returns success
+
+--*/
+{
+ EFI_STATUS Status;
+ PEI_STATUS_CODE_MEMORY_PPI *StatusCodeMemoryPpi;
+ EFI_STATUS_CODE_ENTRY *CurrentEntry;
+ UINTN LastEntry;
+ MEMORY_STATUS_CODE_INSTANCE *PrivateData;
+ EFI_PEI_PPI_DESCRIPTOR *StatusCodeMemoryDescriptor;
+ EFI_PEI_SERVICES **PeiServices;
+
+ PeiServices = GetPeiServicesTablePointer ();
+ //
+ // We don't care to log debug codes.
+ //
+ if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
+ return EFI_SUCCESS;
+ }
+
+ if (!gRunningFromMemory) {
+ //
+ // If we are called from DXE and have not been reinstalled into memory, we
+ // can no longer locate the journal, so we can no longer log status codes.
+ //
+ if (!PeiServices) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Locate Journal
+ //
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gPeiStatusCodeMemoryPpiGuid,
+ 0,
+ &StatusCodeMemoryDescriptor,
+ (VOID **) &StatusCodeMemoryPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Determine the last entry in the journal.
+ // This is needed to properly implement the rolling queue.
+ //
+ LastEntry = PEI_STATUS_CODE_MAX_HEAP_ENTRY;
+
+ //
+ // Get private data
+ //
+ PrivateData = _CR (StatusCodeMemoryDescriptor, MEMORY_STATUS_CODE_INSTANCE, PpiDescriptor);
+
+ //
+ // Once memory gets installed, heap gets moved to real memory.
+ // We need to fix up the pointers to match the move.
+ //
+ PrivateData->PpiDescriptor.Ppi = &PrivateData->StatusCodeMemoryPpi;
+ PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid;
+ PrivateData->StatusCodeMemoryPpi.Address = PrivateData->StatusCodeMemoryPpi.Address +
+ (UINTN) PrivateData - (UINTN) PrivateData->This;
+ PrivateData->NotifyDescriptor.Guid = &gEfiPeiFvFileLoaderPpiGuid;
+ PrivateData->NotifyDescriptor.Notify = LoadImageCallback;
+ PrivateData->This = PrivateData;
+
+ StatusCodeMemoryPpi = PrivateData->PpiDescriptor.Ppi;
+ } else {
+ //
+ // Use global/memory copy of the PPI
+ //
+ StatusCodeMemoryPpi = &mStatusCodeMemoryPpi;
+
+ //
+ // Determine the last entry in the journal.
+ // This is needed to properly implement the rolling queue.
+ //
+ LastEntry = PEI_STATUS_CODE_MAX_RT_ENTRY;
+ }
+ //
+ // Return if we are using a cleared PPI somehow
+ //
+ if (!StatusCodeMemoryPpi->Address || !StatusCodeMemoryPpi->Length) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Update the latest entry in the journal (may actually be first due to rolling
+ // queue).
+ //
+ CurrentEntry = (EFI_STATUS_CODE_ENTRY *) (UINTN) (StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->LastEntry * sizeof (EFI_STATUS_CODE_ENTRY)));
+
+ StatusCodeMemoryPpi->LastEntry = (StatusCodeMemoryPpi->LastEntry + 1) % LastEntry;
+ if (StatusCodeMemoryPpi->LastEntry == StatusCodeMemoryPpi->FirstEntry) {
+ StatusCodeMemoryPpi->FirstEntry = (StatusCodeMemoryPpi->FirstEntry + 1) % LastEntry;
+ }
+
+ CurrentEntry->Type = CodeType;
+ CurrentEntry->Value = Value;
+ CurrentEntry->Instance = Instance;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+LoadImageCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+/*++
+
+Routine Description:
+
+ Relocate the PEIM into memory.
+
+ Once load protocol becomes available, relocate our PEIM into memory.
+ The primary benefit is to eliminate the blackout window that we would have in
+ the memory log between the end of PEI and the status code DXE driver taking
+ control. If we don't do this, we cannot determine where our memory journal
+ is located and cannot function.
+
+ A second benefit is speed optimization throughout DXE.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ NotifyDescriptor - Information about the notify event.
+ Ppi - Context
+
+Returns:
+
+ EFI_SUCCESS This function always returns success.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS ImageAddress;
+ EFI_PHYSICAL_ADDRESS EntryPoint;
+ UINT64 ImageSize;
+ MEMORY_STATUS_CODE_INSTANCE *PrivateData;
+
+ //
+ // Relocate to memory
+ //
+ if (!gRunningFromMemory) {
+ //
+ // Use the callback descriptor to get the FfsHeader
+ //
+ PrivateData = _CR (NotifyDescriptor, MEMORY_STATUS_CODE_INSTANCE, NotifyDescriptor);
+
+ Status = ((EFI_PEI_FV_FILE_LOADER_PPI *) Ppi)->FvLoadFile (
+ Ppi,
+ PrivateData->FfsHeader,
+ &ImageAddress,
+ &ImageSize,
+ &EntryPoint
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Set the flag in the loaded image that indicates the PEIM is executing
+ // from memory.
+ //
+#ifdef EFI_NT_EMULATOR
+ gRunningFromMemory = TRUE;
+#else
+ * (BOOLEAN *) ((UINTN) &gRunningFromMemory + (UINTN) EntryPoint - (UINTN) InstallMonoStatusCode) = TRUE;
+#endif
+ Status = ((EFI_PEIM_ENTRY_POINT )(UINTN) EntryPoint) (PrivateData->FfsHeader, PeiServices);
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.h b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.h
new file mode 100644
index 0000000000..3580083efa
--- /dev/null
+++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.h
@@ -0,0 +1,94 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MemoryStatusCode.h
+
+Abstract:
+
+ Lib to provide status code reporting via memory.
+
+--*/
+
+#ifndef _PEI_MEMORY_STATUS_CODE_H_
+#define _PEI_MEMORY_STATUS_CODE_H_
+
+//
+// Publicly exported function
+//
+EFI_STATUS
+EFIAPI
+InstallMonoStatusCode (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+;
+//
+// Publicly exported data
+//
+extern BOOLEAN gRunningFromMemory;
+//
+// Private data
+//
+//
+// Define the amount of heap to use before memory is allocated
+//
+#define PEI_STATUS_CODE_HEAP_LENGTH 512
+#define PEI_STATUS_CODE_MAX_HEAP_ENTRY (PEI_STATUS_CODE_HEAP_LENGTH / sizeof (EFI_STATUS_CODE_ENTRY))
+
+//
+// Define the number of 4K pages of BS memory to allocate (1MB)
+//
+#define PEI_STATUS_CODE_RT_PAGES (128)
+#define PEI_STATUS_CODE_RT_LENGTH (PEI_STATUS_CODE_RT_PAGES * 1024 * 4)
+#define PEI_STATUS_CODE_MAX_RT_ENTRY (PEI_STATUS_CODE_RT_LENGTH / sizeof (EFI_STATUS_CODE_ENTRY))
+
+//
+// Define a private data structure
+//
+#define MEMORY_STATUS_CODE_SIGNATURE EFI_SIGNATURE_32 ('M', 'S', 'C', 'S')
+
+typedef struct _MEMORY_STATUS_CODE_INSTANCE {
+ UINT32 Signature;
+ struct _MEMORY_STATUS_CODE_INSTANCE *This;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ PEI_STATUS_CODE_MEMORY_PPI StatusCodeMemoryPpi;
+ EFI_PEI_NOTIFY_DESCRIPTOR NotifyDescriptor;
+} MEMORY_STATUS_CODE_INSTANCE;
+
+#define MEMORY_STATUS_CODE_FROM_DESCRIPTOR_THIS(a) \
+ PEI_CR (a, \
+ MEMORY_STATUS_CODE_INSTANCE, \
+ PpiDescriptor, \
+ MEMORY_STATUS_CODE_SIGNATURE \
+ )
+#define MEMORY_STATUS_CODE_FROM_NOTIFY_THIS(a) \
+ PEI_CR (a, \
+ MEMORY_STATUS_CODE_INSTANCE, \
+ NotifyDescriptor, \
+ MEMORY_STATUS_CODE_SIGNATURE \
+ )
+
+//
+// Private function declarations
+//
+EFI_STATUS
+EFIAPI
+LoadImageCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+;
+
+#endif
diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/build.xml b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/build.xml
new file mode 100644
index 0000000000..40db09a722
--- /dev/null
+++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="EdkMemoryStatusCodeLib"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Library\EdkMemoryStatusCodeLib"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="EdkMemoryStatusCodeLib">
+ <GenBuild baseName="EdkMemoryStatusCodeLib" mbdFilename="${MODULE_DIR}\EdkMemoryStatusCodeLib.mbd" msaFilename="${MODULE_DIR}\EdkMemoryStatusCodeLib.msa"/>
+ </target>
+ <target depends="EdkMemoryStatusCodeLib_clean" name="clean"/>
+ <target depends="EdkMemoryStatusCodeLib_cleanall" name="cleanall"/>
+ <target name="EdkMemoryStatusCodeLib_clean">
+ <OutputDirSetup baseName="EdkMemoryStatusCodeLib" mbdFilename="${MODULE_DIR}\EdkMemoryStatusCodeLib.mbd" msaFilename="${MODULE_DIR}\EdkMemoryStatusCodeLib.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\EdkMemoryStatusCodeLib_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\EdkMemoryStatusCodeLib_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="EdkMemoryStatusCodeLib_cleanall">
+ <OutputDirSetup baseName="EdkMemoryStatusCodeLib" mbdFilename="${MODULE_DIR}\EdkMemoryStatusCodeLib.mbd" msaFilename="${MODULE_DIR}\EdkMemoryStatusCodeLib.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\EdkMemoryStatusCodeLib_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\EdkMemoryStatusCodeLib_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**EdkMemoryStatusCodeLib*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file