Initial import.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
bbahnsen
2006-04-21 22:54:32 +00:00
commit 878ddf1fc3
2651 changed files with 624620 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
/*++
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:
DebugImageInfo.h
Abstract:
Support functions for managing debug image info table when loading and unloading
images.
--*/
#ifndef __DEBUG_IMAGE_INFO_H__
#define __DEBUG_IMAGE_INFO_H__
#define FOUR_MEG_PAGES 0x400
#define FOUR_MEG_MASK ((FOUR_MEG_PAGES * EFI_PAGE_SIZE) - 1)
#define EFI_DEBUG_TABLE_ENTRY_SIZE (sizeof (VOID *))
VOID
CoreInitializeDebugImageInfoTable (
VOID
)
/*++
Routine Description:
Creates and initializes the DebugImageInfo Table. Also creates the configuration
table and registers it into the system table.
Arguments:
None
Returns:
NA
Notes:
This function allocates memory, frees it, and then allocates memory at an
address within the initial allocation. Since this function is called early
in DXE core initialization (before drivers are dispatched), this should not
be a problem.
--*/
;
VOID
CoreUpdateDebugTableCrc32 (
VOID
)
/*++
Routine Description:
Update the CRC32 in the Debug Table.
Since the CRC32 service is made available by the Runtime driver, we have to
wait for the Runtime Driver to be installed before the CRC32 can be computed.
This function is called elsewhere by the core when the runtime architectural
protocol is produced.
Arguments:
None
Returns:
NA
--*/
;
VOID
CoreNewDebugImageInfoEntry (
UINTN ImageInfoType,
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates
the table if it's not large enough to accomidate another entry.
Arguments:
ImageInfoType - type of debug image information
LoadedImage - pointer to the loaded image protocol for the image being loaded
ImageHandle - image handle for the image being loaded
Returns:
NA
--*/
;
VOID
CoreRemoveDebugImageInfoEntry (
EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Removes and frees an entry from the DebugImageInfo Table.
Arguments:
ImageHandle - image handle for the image being unloaded
Returns:
NA
--*/
;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,450 @@
/*++
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:
dependency.c
Abstract:
DXE Dispatcher Dependency Evaluator
This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine
if a driver can be scheduled for execution. The criteria for
schedulability is that the dependency expression is satisfied.
--*/
#include <DxeMain.h>
//
// Global stack used to evaluate dependency expressions
//
BOOLEAN *mDepexEvaluationStack = NULL;
BOOLEAN *mDepexEvaluationStackEnd = NULL;
BOOLEAN *mDepexEvaluationStackPointer = NULL;
//
// Worker functions
//
STATIC
EFI_STATUS
GrowDepexStack (
VOID
)
/*++
Routine Description:
Grow size of the Depex stack
Arguments:
Stack - Old stack on the way in and new stack on the way out
StackSize - New size of the stack
Returns:
EFI_SUCCESS - Stack successfully growed.
EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack.
--*/
{
BOOLEAN *NewStack;
UINTN Size;
Size = DEPEX_STACK_SIZE_INCREMENT;
if (mDepexEvaluationStack != NULL) {
Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack);
}
NewStack = CoreAllocateBootServicesPool (Size * sizeof (BOOLEAN));
if (NewStack == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (mDepexEvaluationStack != NULL) {
//
// Copy to Old Stack to the New Stack
//
CopyMem (
NewStack,
mDepexEvaluationStack,
(mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (BOOLEAN)
);
//
// Free The Old Stack
//
CoreFreePool (mDepexEvaluationStack);
}
//
// Make the Stack pointer point to the old data in the new stack
//
mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack);
mDepexEvaluationStack = NewStack;
mDepexEvaluationStackEnd = NewStack + Size;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
PushBool (
IN BOOLEAN Value
)
/*++
Routine Description:
Push an element onto the Boolean Stack
Arguments:
Value - BOOLEAN to push.
Returns:
EFI_SUCCESS - The value was pushed onto the stack.
EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack.
--*/
{
EFI_STATUS Status;
//
// Check for a stack overflow condition
//
if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) {
//
// Grow the stack
//
Status = GrowDepexStack ();
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Push the item onto the stack
//
*mDepexEvaluationStackPointer = Value;
mDepexEvaluationStackPointer++;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
PopBool (
OUT BOOLEAN *Value
)
/*++
Routine Description:
Pop an element from the Boolean stack.
Arguments:
Value - BOOLEAN to pop.
Returns:
EFI_SUCCESS - The value was popped onto the stack.
EFI_ACCESS_DENIED - The pop operation underflowed the stack
--*/
{
//
// Check for a stack underflow condition
//
if (mDepexEvaluationStackPointer == mDepexEvaluationStack) {
return EFI_ACCESS_DENIED;
}
//
// Pop the item off the stack
//
mDepexEvaluationStackPointer--;
*Value = *mDepexEvaluationStackPointer;
return EFI_SUCCESS;
}
EFI_STATUS
CorePreProcessDepex (
IN EFI_CORE_DRIVER_ENTRY *DriverEntry
)
/*++
Routine Description:
Preprocess dependency expression and update DriverEntry to reflect the
state of Before, After, and SOR dependencies. If DriverEntry->Before
or DriverEntry->After is set it will never be cleared. If SOR is set
it will be cleared by CoreSchedule(), and then the driver can be
dispatched.
Arguments:
DriverEntry - DriverEntry element to update
Returns:
EFI_SUCCESS - It always works.
--*/
{
UINT8 *Iterator;
Iterator = DriverEntry->Depex;
if (*Iterator == EFI_DEP_SOR) {
DriverEntry->Unrequested = TRUE;
} else {
DriverEntry->Dependent = TRUE;
}
if (*Iterator == EFI_DEP_BEFORE) {
DriverEntry->Before = TRUE;
} else if (*Iterator == EFI_DEP_AFTER) {
DriverEntry->After = TRUE;
}
if (DriverEntry->Before || DriverEntry->After) {
CopyMem (&DriverEntry->BeforeAfterGuid, Iterator + 1, sizeof (EFI_GUID));
}
return EFI_SUCCESS;
}
BOOLEAN
CoreIsSchedulable (
IN EFI_CORE_DRIVER_ENTRY *DriverEntry
)
/*++
Routine Description:
This is the POSTFIX version of the dependency evaluator. This code does
not need to handle Before or After, as it is not valid to call this
routine in this case. The SOR is just ignored and is a nop in the grammer.
POSTFIX means all the math is done on top of the stack.
Arguments:
DriverEntry - DriverEntry element to update
Returns:
TRUE - If driver is ready to run.
FALSE - If driver is not ready to run or some fatal error was found.
--*/
{
EFI_STATUS Status;
UINT8 *Iterator;
BOOLEAN Operator;
BOOLEAN Operator2;
EFI_GUID DriverGuid;
VOID *Interface;
if (DriverEntry->After || DriverEntry->Before) {
//
// If Before or After Depex skip as CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter ()
// processes them.
//
return FALSE;
}
if (DriverEntry->Depex == NULL) {
//
// A NULL Depex means treat the driver like an EFI 1.0 thing.
//
Status = CoreAllEfiServicesAvailable ();
if (EFI_ERROR (Status)) {
return FALSE;
}
return TRUE;
}
//
// Clean out memory leaks in Depex Boolean stack. Leaks are only caused by
// incorrectly formed DEPEX expressions
//
mDepexEvaluationStackPointer = mDepexEvaluationStack;
Iterator = DriverEntry->Depex;
while (TRUE) {
//
// Check to see if we are attempting to fetch dependency expression instructions
// past the end of the dependency expression.
//
if (((UINTN)Iterator - (UINTN)DriverEntry->Depex) > DriverEntry->DepexSize) {
return FALSE;
}
//
// Look at the opcode of the dependency expression instruction.
//
switch (*Iterator) {
case EFI_DEP_BEFORE:
case EFI_DEP_AFTER:
//
// For a well-formed Dependency Expression, the code should never get here.
// The BEFORE and AFTER are processed prior to this routine's invocation.
// If the code flow arrives at this point, there was a BEFORE or AFTER
// that were not the first opcodes.
//
ASSERT (FALSE);
case EFI_DEP_SOR:
//
// These opcodes can only appear once as the first opcode. If it is found
// at any other location, then the dependency expression evaluates to FALSE
//
if (Iterator != DriverEntry->Depex) {
return FALSE;
}
//
// Otherwise, it is the first opcode and should be treated as a NOP.
//
break;
case EFI_DEP_PUSH:
//
// Push operator is followed by a GUID. Test to see if the GUID protocol
// is installed and push the boolean result on the stack.
//
CopyMem (&DriverGuid, Iterator + 1, sizeof (EFI_GUID));
Status = CoreLocateProtocol (&DriverGuid, NULL, &Interface);
if (EFI_ERROR (Status)) {
Status = PushBool (FALSE);
} else {
*Iterator = EFI_DEP_REPLACE_TRUE;
Status = PushBool (TRUE);
}
if (EFI_ERROR (Status)) {
return FALSE;
}
Iterator += sizeof (EFI_GUID);
break;
case EFI_DEP_AND:
Status = PopBool (&Operator);
if (EFI_ERROR (Status)) {
return FALSE;
}
Status = PopBool (&Operator2);
if (EFI_ERROR (Status)) {
return FALSE;
}
Status = PushBool ((BOOLEAN)(Operator && Operator2));
if (EFI_ERROR (Status)) {
return FALSE;
}
break;
case EFI_DEP_OR:
Status = PopBool (&Operator);
if (EFI_ERROR (Status)) {
return FALSE;
}
Status = PopBool (&Operator2);
if (EFI_ERROR (Status)) {
return FALSE;
}
Status = PushBool ((BOOLEAN)(Operator || Operator2));
if (EFI_ERROR (Status)) {
return FALSE;
}
break;
case EFI_DEP_NOT:
Status = PopBool (&Operator);
if (EFI_ERROR (Status)) {
return FALSE;
}
Status = PushBool ((BOOLEAN)(!Operator));
if (EFI_ERROR (Status)) {
return FALSE;
}
break;
case EFI_DEP_TRUE:
Status = PushBool (TRUE);
if (EFI_ERROR (Status)) {
return FALSE;
}
break;
case EFI_DEP_FALSE:
Status = PushBool (FALSE);
if (EFI_ERROR (Status)) {
return FALSE;
}
break;
case EFI_DEP_END:
Status = PopBool (&Operator);
if (EFI_ERROR (Status)) {
return FALSE;
}
return Operator;
case EFI_DEP_REPLACE_TRUE:
Status = PushBool (TRUE);
if (EFI_ERROR (Status)) {
return FALSE;
}
Iterator += sizeof (EFI_GUID);
break;
default:
return FALSE;
}
//
// Skip over the Dependency Op Code we just processed in the switch.
// The math is done out of order, but it should not matter. That is
// we may add in the sizeof (EFI_GUID) before we account for the OP Code.
// This is not an issue, since we just need the correct end result. You
// need to be careful using Iterator in the loop as it's intermediate value
// may be strange.
//
Iterator++;
}
return FALSE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
<?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.
-->
<ModuleBuildDescription 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">
<MbdHeader>
<BaseName>DxeMain</BaseName>
<Guid>D6A2CB7F-6A18-4e2f-B43B-9920A733700A</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:18</Modified>
</MbdHeader>
<Libraries>
<Library>BaseLib</Library>
<Library>BaseCacheMaintenanceLib</Library>
<Library>DxeReportStatusCodeLib</Library>
<Library>BaseDebugLibReportStatusCode</Library>
<Library>DxeCoreUefiDecompressLibFromHob</Library>
<Library>DxeCoreTianoDecompressLibFromHob</Library>
<Library>DxeCoreCustomDecompressLibFromHob</Library>
<Library>EdkDxePeCoffLoaderFromHobLib</Library>
<Library>DxeCoreHobLib</Library>
<Library>DxeCoreEntryPoint</Library>
<Library>BaseMemoryLib</Library>
<Library>UefiLib</Library>
<Library>BasePerformanceLibNull</Library>
</Libraries>
<BuildOptions ToolChain="MSFT">
<ImageEntryPoint>_ModuleEntryPoint</ImageEntryPoint>
<Option>C_PROJ_FLAGS = ${C_PROJ_FLAGS} /Ob0</Option>
</BuildOptions>
</ModuleBuildDescription>

View File

@@ -0,0 +1,164 @@
<?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.
-->
<ModuleSurfaceArea 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">
<MsaHeader>
<BaseName>DxeMain</BaseName>
<ModuleType>DXE_CORE</ModuleType>
<ComponentType>BS_DRIVER</ComponentType>
<Guid>D6A2CB7F-6A18-4e2f-B43B-9920A733700A</Guid>
<Version>0</Version>
<Abstract>Component description file for DxeMain.</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:18</Updated>
</MsaHeader>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">DxeCoreEntryPoint</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">TianoDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">CustomDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">EdkPeCoffLoaderLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">CacheMaintenanceLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>DxeMain\DxeMain.c</Filename>
<Filename>DxeMain\DxeProtocolNotify.c</Filename>
<Filename>Dispatcher\Dispatcher.c</Filename>
<Filename>Dispatcher\Dependency.c</Filename>
<Filename>Event\ExecData.c</Filename>
<Filename>Event\Event.c</Filename>
<Filename>Event\Timer.c</Filename>
<Filename>Event\Tpl.c</Filename>
<Filename>FwVol\FwVol.c</Filename>
<Filename>FwVol\Ffs.c</Filename>
<Filename>FwVol\FwVolAttrib.c</Filename>
<Filename>FwVol\FwVolRead.c</Filename>
<Filename>FwVol\FwVolWrite.c</Filename>
<Filename>FwVolBlock\FwVolBlock.c</Filename>
<Filename>Mem\MemData.c</Filename>
<Filename>Mem\Page.c</Filename>
<Filename>Mem\Pool.c</Filename>
<Filename>Gcd\Gcd.c</Filename>
<Filename>Hand\Handle.c</Filename>
<Filename>Hand\Locate.c</Filename>
<Filename>Hand\Notify.c</Filename>
<Filename>Hand\DriverSupport.c</Filename>
<Filename>Library\Library.c</Filename>
<Filename>Misc\InstallConfigurationTable.c</Filename>
<Filename>Misc\SetWatchdogTimer.c</Filename>
<Filename>Misc\Stall.c</Filename>
<Filename>Misc\DebugImageInfo.c</Filename>
<Filename>Image\Image.c</Filename>
<Filename>Image\ImageFile.c</Filename>
<Filename>SectionExtraction\CoreSectionExtraction.c</Filename>
<Filename>DebugImageInfo.h</Filename>
<Filename>DebugMask.h</Filename>
<Filename>DxeMain.h</Filename>
<Filename>Exec.h</Filename>
<Filename>FwVolBlock.h</Filename>
<Filename>FwVolDriver.h</Filename>
<Filename>Gcd.h</Filename>
<Filename>Hand.h</Filename>
<Filename>Image.h</Filename>
<Filename>Imem.h</Filename>
<Filename>Library.h</Filename>
</SourceFiles>
<Includes>
<PackageName>MdePkg</PackageName>
<PackageName>EdkModulePkg</PackageName>
</Includes>
<Protocols>
<Protocol Usage="SOMETIMES_CONSUMED">Ebc</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">LoadedImage</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">DevicePath</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">Cpu</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">FirmwareVolume</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">FirmwareVolumeDispatch</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">FirmwareVolumeBlock</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">SectionExtraction</Protocol>
<Protocol Usage="SOMETIMES_CONSUMED">DriverBinding</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">PlatformDriverOverride</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">BusSpecificDriverOverride</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">Timer</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">Metronome</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">MonotonicCounter</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">VariableWrite</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">Bds</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">Variable</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">Security</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">WatchdogTimer</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">Runtime</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">RealTimeClock</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">Reset</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">LoadFile</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">SimpleFileSystem</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">LoadPeImage</Protocol>
</Protocols>
<Guids>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>MemoryTypeInformation</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>DxeServicesTable</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>HobList</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>DebugImageInfoTable</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>Apriori</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>FirmwareFileSystem</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>FileInfo</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>HobMemoryAllocModule</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>PeiPeCoffLoader</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>LoadPeImage</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>EventExitBootServices</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>EventVirtualAddressChange</C_Name>
</GuidEntry>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>EventMemoryMapChange</C_Name>
</GuidEntry>
</Guids>
<Externs>
<Extern>
<ModuleEntryPoint>DxeMain</ModuleEntryPoint>
</Extern>
</Externs>
<BuildOptions>
<Option>BUILD_TYPE=DXE_CORE</Option>
</BuildOptions>
</ModuleSurfaceArea>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,266 @@
/*++
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:
DxeProtocolNotify.c
Abstract:
This file deals with Architecture Protocol (AP) registration in
the Dxe Core. The mArchProtocols[] array represents a list of
events that represent the Architectural Protocols.
--*/
#include <DxeMain.h>
//
// DXE Core Global Variables for all of the Architectural Protocols.
// If a protocol is installed mArchProtocols[].Present will be TRUE.
//
// CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
// and mArchProtocols[].Registration as it creates events for every array
// entry.
//
ARCHITECTURAL_PROTOCOL_ENTRY mArchProtocols[] = {
{ &gEfiSecurityArchProtocolGuid, (VOID **)&gSecurity, NULL, NULL, FALSE },
{ &gEfiCpuArchProtocolGuid, (VOID **)&gCpu, NULL, NULL, FALSE },
{ &gEfiMetronomeArchProtocolGuid, (VOID **)&gMetronome, NULL, NULL, FALSE },
{ &gEfiTimerArchProtocolGuid, (VOID **)&gTimer, NULL, NULL, FALSE },
{ &gEfiBdsArchProtocolGuid, (VOID **)&gBds, NULL, NULL, FALSE },
{ &gEfiWatchdogTimerArchProtocolGuid, (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
{ &gEfiRuntimeArchProtocolGuid, (VOID **)&gRuntime, NULL, NULL, FALSE },
{ &gEfiVariableArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
{ &gEfiVariableWriteArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
{ &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
{ &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
// { &gEfiStatusCodeRuntimeProtocolGuid, (VOID **)&gStatusCode, NULL, NULL, FALSE },
{ &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
{ NULL, (VOID **)NULL, NULL, NULL, FALSE }
};
EFI_STATUS
CoreAllEfiServicesAvailable (
VOID
)
/*++
Routine Description:
Return TRUE if all AP services are availible.
Arguments:
NONE
Returns:
EFI_SUCCESS - All AP services are available
EFI_NOT_FOUND - At least one AP service is not available
--*/
{
ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
if (!Entry->Present) {
return EFI_NOT_FOUND;
}
}
return EFI_SUCCESS;
}
VOID
EFIAPI
GenericArchProtocolNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
This notify function is registered for every architectural protocol. This handler
updates mArchProtocol[] array entry with protocol instance data and sets it's
present flag to TRUE. If any constructor is required it is executed. The EFI
System Table headers are updated.
Arguments:
Event - The Event that is being processed, not used.
Context - Event Context, not used.
Returns:
None
--*/
{
EFI_STATUS Status;
ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
VOID *Protocol;
BOOLEAN Found;
Found = FALSE;
for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol);
if (EFI_ERROR (Status)) {
continue;
}
Found = TRUE;
Entry->Present = TRUE;
//
// Update protocol global variable if one exists. Entry->Protocol points to a global variable
// if one exists in the DXE core for this Architectural Protocol
//
if (Entry->Protocol != NULL) {
*(Entry->Protocol) = Protocol;
}
if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
//
// Register the Core timer tick handler with the Timer AP
//
gTimer->RegisterHandler (gTimer, CoreTimerTick);
}
if (CompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
//
// When runtime architectural protocol is available, updates CRC32 in the Debug Table
//
CoreUpdateDebugTableCrc32 ();
}
}
//
// It's over kill to do them all every time, but it saves a lot of code.
//
if (Found) {
CalculateEfiHdrCrc (&gRT->Hdr);
CalculateEfiHdrCrc (&gBS->Hdr);
CalculateEfiHdrCrc (&gST->Hdr);
CalculateEfiHdrCrc (&gDS->Hdr);
}
}
VOID
CoreNotifyOnArchProtocolInstallation (
VOID
)
/*++
Routine Description:
Creates an event that is fired everytime a Protocol of a specific type is installed
Arguments:
NONE
Returns:
NONE
--*/
{
EFI_STATUS Status;
ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
//
// Create the event
//
Status = CoreCreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
EFI_TPL_CALLBACK,
GenericArchProtocolNotify,
NULL,
&Entry->Event
);
ASSERT_EFI_ERROR(Status);
//
// Register for protocol notifactions on this event
//
Status = CoreRegisterProtocolNotify (
Entry->ProtocolGuid,
Entry->Event,
&Entry->Registration
);
ASSERT_EFI_ERROR(Status);
}
}
//
// Following is needed to display missing architectural protocols in debug builds
//
typedef struct {
EFI_GUID *ProtocolGuid;
CHAR16 *GuidString;
} GUID_TO_STRING_PROTOCOL_ENTRY;
static const GUID_TO_STRING_PROTOCOL_ENTRY MissingProtocols[] = {
{ &gEfiSecurityArchProtocolGuid, (CHAR16 *)L"Security" },
{ &gEfiCpuArchProtocolGuid, (CHAR16 *)L"CPU" },
{ &gEfiMetronomeArchProtocolGuid, (CHAR16 *)L"Metronome" },
{ &gEfiTimerArchProtocolGuid, (CHAR16 *)L"Timer" },
{ &gEfiBdsArchProtocolGuid, (CHAR16 *)L"Bds" },
{ &gEfiWatchdogTimerArchProtocolGuid, (CHAR16 *)L"Watchdog Timer" },
{ &gEfiRuntimeArchProtocolGuid, (CHAR16 *)L"Runtime" },
{ &gEfiVariableArchProtocolGuid, (CHAR16 *)L"Variable" },
{ &gEfiVariableWriteArchProtocolGuid, (CHAR16 *)L"Variable Write" },
{ &gEfiMonotonicCounterArchProtocolGuid, (CHAR16 *)L"Monotonic Counter" },
{ &gEfiResetArchProtocolGuid, (CHAR16 *)L"Reset" },
// { &gEfiStatusCodeRuntimeProtocolGuid, (CHAR16 *)L"Status Code" },
{ &gEfiRealTimeClockArchProtocolGuid, (CHAR16 *)L"Real Time Clock" }
};
VOID
CoreDisplayMissingArchProtocols (
VOID
)
/*++
Routine Description:
Displays Architectural protocols that were not loaded and are required for DXE core to function
Only used in Debug Builds
Arguments:
NONE
Returns:
NONE
--*/
{
const GUID_TO_STRING_PROTOCOL_ENTRY *MissingEntry;
ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
if (!Entry->Present) {
MissingEntry = MissingProtocols;
for (MissingEntry = MissingProtocols; TRUE ; MissingEntry++) {
if (CompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
DEBUG ((EFI_D_ERROR, "\n%s Arch Protocol not present!!\n", MissingEntry->GuidString));
break;
}
}
}
}
}

View File

@@ -0,0 +1,862 @@
/*++
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:
event.c
Abstract:
EFI Event support
--*/
#include <DxeMain.h>
//
// Enumerate the valid types
//
UINT32 mEventTable[] = {
//
// 0x80000200 Timer event with a notification function that is
// queue when the event is signaled with SignalEvent()
//
EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
//
// 0x80000000 Timer event without a notification function. It can be
// signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent().
//
EFI_EVENT_TIMER,
//
// 0x00000100 Generic event with a notification function that
// can be waited on with CheckEvent() or WaitForEvent()
//
EFI_EVENT_NOTIFY_WAIT,
//
// 0x00000200 Generic event with a notification function that
// is queue when the event is signaled with SignalEvent()
//
EFI_EVENT_NOTIFY_SIGNAL,
//
// 0x00000201 ExitBootServicesEvent.
//
EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
//
// 0x60000202 SetVirtualAddressMapEvent.
//
EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
//
// 0x00000203 ReadyToBootEvent.
//
EFI_EVENT_SIGNAL_READY_TO_BOOT,
//
// 0x00000204 LegacyBootEvent.
//
EFI_EVENT_SIGNAL_LEGACY_BOOT,
//
// 0x00000603 Signal all ReadyToBootEvents.
//
EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_READY_TO_BOOT,
//
// 0x00000604 Signal all LegacyBootEvents.
//
EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_LEGACY_BOOT,
#endif
//
// 0x00000000 Generic event without a notification function.
// It can be signaled with SignalEvent() and checked with CheckEvent()
// or WaitForEvent().
//
0x00000000,
//
// 0x80000100 Timer event with a notification function that can be
// waited on with CheckEvent() or WaitForEvent()
//
EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_WAIT,
};
VOID
CoreAcquireEventLock (
VOID
)
/*++
Routine Description:
Enter critical section by acquiring the lock on gEventQueueLock.
Arguments:
None
Returns:
None
--*/
{
CoreAcquireLock (&gEventQueueLock);
}
VOID
CoreReleaseEventLock (
VOID
)
/*++
Routine Description:
Exit critical section by releasing the lock on gEventQueueLock.
Arguments:
None
Returns:
None
--*/
{
CoreReleaseLock (&gEventQueueLock);
}
EFI_STATUS
CoreInitializeEventServices (
VOID
)
/*++
Routine Description:
Initializes "event" support and populates parts of the System and Runtime Table.
Arguments:
None
Returns:
EFI_SUCCESS - Always return success
--*/
{
UINTN Index;
for (Index=0; Index <= EFI_TPL_HIGH_LEVEL; Index++) {
InitializeListHead (&gEventQueue[Index]);
}
CoreInitializeTimer ();
return EFI_SUCCESS;
}
EFI_STATUS
CoreShutdownEventServices (
VOID
)
/*++
Routine Description:
Register all runtime events to make sure they are still available after ExitBootService.
Arguments:
None
Returns:
EFI_SUCCESS - Always return success.
--*/
{
LIST_ENTRY *Link;
IEVENT *Event;
//
// The Runtime AP is required for the core to function!
//
ASSERT (gRuntime != NULL);
for (Link = mRuntimeEventList.ForwardLink; Link != &mRuntimeEventList; Link = Link->ForwardLink) {
Event = CR (Link, IEVENT, RuntimeLink, EVENT_SIGNATURE);
gRuntime->RegisterEvent (
gRuntime,
Event->Type,
Event->NotifyTpl,
Event->NotifyFunction,
Event->NotifyContext,
(VOID **)Event
);
}
return EFI_SUCCESS;
}
VOID
CoreDispatchEventNotifies (
IN EFI_TPL Priority
)
/*++
Routine Description:
Dispatches all pending events.
Arguments:
Priority - The task priority level of event notifications to dispatch
Returns:
None
--*/
{
IEVENT *Event;
LIST_ENTRY *Head;
CoreAcquireEventLock ();
ASSERT (gEventQueueLock.OwnerTpl == Priority);
Head = &gEventQueue[Priority];
//
// Dispatch all the pending notifications
//
while (!IsListEmpty (Head)) {
Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);
RemoveEntryList (&Event->NotifyLink);
Event->NotifyLink.ForwardLink = NULL;
//
// Only clear the SIGNAL status if it is a SIGNAL type event.
// WAIT type events are only cleared in CheckEvent()
//
if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
Event->SignalCount = 0;
}
CoreReleaseEventLock ();
//
// Notify this event
//
ASSERT (Event->NotifyFunction != NULL);
Event->NotifyFunction (Event, Event->NotifyContext);
//
// Check for next pending event
//
CoreAcquireEventLock ();
}
gEventPending &= ~(1 << Priority);
CoreReleaseEventLock ();
}
VOID
STATIC
CoreNotifyEvent (
IN IEVENT *Event
)
/*++
Routine Description:
Queues the event's notification function to fire
Arguments:
Event - The Event to notify
Returns:
None
--*/
{
//
// Event database must be locked
//
ASSERT_LOCKED (&gEventQueueLock);
//
// If the event is queued somewhere, remove it
//
if (Event->NotifyLink.ForwardLink != NULL) {
RemoveEntryList (&Event->NotifyLink);
Event->NotifyLink.ForwardLink = NULL;
}
//
// Queue the event to the pending notification list
//
InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);
gEventPending |= (UINTN)(1 << Event->NotifyTpl);
}
VOID
CoreNotifySignalList (
IN EFI_GUID *EventGroup
)
/*++
Routine Description:
Signals all events in the EventGroup
Arguments:
EventGroup - The list to signal
Returns:
None
--*/
{
LIST_ENTRY *Link;
LIST_ENTRY *Head;
IEVENT *Event;
CoreAcquireEventLock ();
Head = &gEventSignalQueue;
for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);
if (CompareGuid (&Event->EventGroup, EventGroup)) {
CoreNotifyEvent (Event);
}
}
CoreReleaseEventLock ();
}
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
static
VOID
EFIAPI
EventNofitySignalAllNullEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
//
// This null event is a size efficent way to enusre that
// EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly.
// EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into
// CreateEventEx() and this function is used to make the
// old error checking in CreateEvent() for Tiano extensions
// function.
//
return;
}
#endif
EFI_STATUS
EFIAPI
CoreCreateEvent (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL
IN VOID *NotifyContext, OPTIONAL
OUT EFI_EVENT *Event
)
/*++
Routine Description:
Creates a general-purpose event structure
Arguments:
Type - The type of event to create and its mode and attributes
NotifyTpl - The task priority level of event notifications
NotifyFunction - Pointer to the events notification function
NotifyContext - Pointer to the notification functions context; corresponds to
parameter "Context" in the notification function
Event - Pointer to the newly created event if the call succeeds; undefined otherwise
Returns:
EFI_SUCCESS - The event structure was created
EFI_INVALID_PARAMETER - One of the parameters has an invalid value
EFI_OUT_OF_RESOURCES - The event could not be allocated
--*/
{
EFI_GUID *GuidPtr;
EFI_EVENT_NOTIFY Function;
GuidPtr = NULL;
Function = NotifyFunction;
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
//
// Clear EFI_EVENT_NOFITY_SIGNAL_ALL (Tiano extension) as all events in the
// EventGroup now have this property. So we need to filter it out.
//
if (Type & EFI_EVENT_NOTIFY_SIGNAL_ALL) {
Type &= ~EFI_EVENT_NOTIFY_SIGNAL_ALL;
Function = EventNofitySignalAllNullEvent;
}
//
// Map the Tiano extensions Events to CreateEventEx form
//
if (Type == EFI_EVENT_SIGNAL_READY_TO_BOOT) {
GuidPtr = &gEfiEventReadToBootGuid;
} else if (Type == EFI_EVENT_SIGNAL_LEGACY_BOOT) {
GuidPtr = &gEfiEventLegacyBootGuid
}
#endif
//
// Convert EFI 1.10 Events to thier UEFI 2.0 CreateEventEx mapping
//
if (Type == EVENT_SIGNAL_EXIT_BOOT_SERVICES) {
GuidPtr = &gEfiEventExitBootServicesGuid;
} else if (Type == EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
GuidPtr = &gEfiEventVirtualAddressChangeGuid;
}
return CoreCreateEventEx (Type, NotifyTpl, Function, NotifyContext, GuidPtr, Event);
}
EFI_STATUS
EFIAPI
CoreCreateEventEx (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL
IN CONST VOID *NotifyContext, OPTIONAL
IN CONST EFI_GUID *EventGroup, OPTIONAL
OUT EFI_EVENT *Event
)
/*++
Routine Description:
Creates a general-purpose event structure
Arguments:
Type - The type of event to create and its mode and attributes
NotifyTpl - The task priority level of event notifications
NotifyFunction - Pointer to the events notification function
NotifyContext - Pointer to the notification functions context; corresponds to
parameter "Context" in the notification function
EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent().
Event - Pointer to the newly created event if the call succeeds; undefined otherwise
Returns:
EFI_SUCCESS - The event structure was created
EFI_INVALID_PARAMETER - One of the parameters has an invalid value
EFI_OUT_OF_RESOURCES - The event could not be allocated
--*/
{
EFI_STATUS Status;
IEVENT *IEvent;
INTN Index;
if ((Event == NULL) || (NotifyTpl == EFI_TPL_APPLICATION)) {
return EFI_INVALID_PARAMETER;
}
//
// Check to make sure no reserved flags are set
//
Status = EFI_INVALID_PARAMETER;
for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {
if (Type == mEventTable[Index]) {
Status = EFI_SUCCESS;
break;
}
}
if(EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
//
// If it's a notify type of event, check its parameters
//
if ((Type & (EFI_EVENT_NOTIFY_WAIT | EFI_EVENT_NOTIFY_SIGNAL))) {
//
// Check for an invalid NotifyFunction or NotifyTpl
//
if ((NotifyFunction == NULL) ||
(NotifyTpl < EFI_TPL_APPLICATION) ||
(NotifyTpl >= EFI_TPL_HIGH_LEVEL)) {
return EFI_INVALID_PARAMETER;
}
} else {
//
// No notification needed, zero ignored values
//
NotifyTpl = 0;
NotifyFunction = NULL;
NotifyContext = NULL;
}
//
// Allcoate and initialize a new event structure.
//
Status = CoreAllocatePool (
(Type & EFI_EVENT_RUNTIME) ? EfiRuntimeServicesData: EfiBootServicesData,
sizeof (IEVENT),
(VOID **)&IEvent
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
SetMem (IEvent, sizeof (IEVENT), 0);
IEvent->Signature = EVENT_SIGNATURE;
IEvent->Type = Type;
IEvent->NotifyTpl = NotifyTpl;
IEvent->NotifyFunction = NotifyFunction;
IEvent->NotifyContext = (VOID *)NotifyContext;
if (EventGroup != NULL) {
CopyGuid (&IEvent->EventGroup, EventGroup);
IEvent->ExFlag = TRUE;
}
*Event = IEvent;
if (Type & EFI_EVENT_RUNTIME) {
//
// Keep a list of all RT events so we can tell the RT AP.
//
InsertTailList (&mRuntimeEventList, &IEvent->RuntimeLink);
}
CoreAcquireEventLock ();
if ((Type & EFI_EVENT_NOTIFY_SIGNAL) != 0x00000000) {
//
// The Event's NotifyFunction must be queued whenever the event is signaled
//
InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);
}
CoreReleaseEventLock ();
//
// Done
//
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
CoreSignalEvent (
IN EFI_EVENT UserEvent
)
/*++
Routine Description:
Signals the event. Queues the event to be notified if needed
Arguments:
UserEvent - The event to signal
Returns:
EFI_INVALID_PARAMETER - Parameters are not valid.
EFI_SUCCESS - The event was signaled.
--*/
{
IEVENT *Event;
Event = UserEvent;
if (Event == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Event->Signature != EVENT_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
CoreAcquireEventLock ();
//
// If the event is not already signalled, do so
//
if (Event->SignalCount == 0x00000000) {
Event->SignalCount++;
//
// If signalling type is a notify function, queue it
//
if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
if (Event->ExFlag) {
//
// The CreateEventEx() style requires all members of the Event Group
// to be signaled.
//
CoreReleaseEventLock ();
CoreNotifySignalList (&Event->EventGroup);
CoreAcquireEventLock ();
} else {
CoreNotifyEvent (Event);
}
}
}
CoreReleaseEventLock ();
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
CoreCheckEvent (
IN EFI_EVENT UserEvent
)
/*++
Routine Description:
Check the status of an event
Arguments:
UserEvent - The event to check
Returns:
EFI_SUCCESS - The event is in the signaled state
EFI_NOT_READY - The event is not in the signaled state
EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL
--*/
{
IEVENT *Event;
EFI_STATUS Status;
Event = UserEvent;
if (Event == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Event->Signature != EVENT_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
return EFI_INVALID_PARAMETER;
}
Status = EFI_NOT_READY;
if (!Event->SignalCount && (Event->Type & EFI_EVENT_NOTIFY_WAIT)) {
//
// Queue the wait notify function
//
CoreAcquireEventLock ();
if (!Event->SignalCount) {
CoreNotifyEvent (Event);
}
CoreReleaseEventLock ();
}
//
// If the even looks signalled, get the lock and clear it
//
if (Event->SignalCount) {
CoreAcquireEventLock ();
if (Event->SignalCount) {
Event->SignalCount = 0;
Status = EFI_SUCCESS;
}
CoreReleaseEventLock ();
}
return Status;
}
EFI_STATUS
EFIAPI
CoreWaitForEvent (
IN UINTN NumberOfEvents,
IN EFI_EVENT *UserEvents,
OUT UINTN *UserIndex
)
/*++
Routine Description:
Stops execution until an event is signaled.
Arguments:
NumberOfEvents - The number of events in the UserEvents array
UserEvents - An array of EFI_EVENT
UserIndex - Pointer to the index of the event which satisfied the wait condition
Returns:
EFI_SUCCESS - The event indicated by Index was signaled.
EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or
Event was not a valid type
EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION
--*/
{
EFI_STATUS Status;
UINTN Index;
//
// Can only WaitForEvent at TPL_APPLICATION
//
if (gEfiCurrentTpl != EFI_TPL_APPLICATION) {
return EFI_UNSUPPORTED;
}
for(;;) {
for(Index = 0; Index < NumberOfEvents; Index++) {
Status = CoreCheckEvent (UserEvents[Index]);
//
// provide index of event that caused problem
//
if (Status != EFI_NOT_READY) {
*UserIndex = Index;
return Status;
}
}
//
// This was the location of the Idle loop callback in EFI 1.x reference
// code. We don't have that concept in this base at this point.
//
}
}
EFI_STATUS
EFIAPI
CoreCloseEvent (
IN EFI_EVENT UserEvent
)
/*++
Routine Description:
Closes an event and frees the event structure.
Arguments:
UserEvent - Event to close
Returns:
EFI_INVALID_PARAMETER - Parameters are not valid.
EFI_SUCCESS - The event has been closed
--*/
{
EFI_STATUS Status;
IEVENT *Event;
Event = UserEvent;
if (Event == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Event->Signature != EVENT_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
//
// If it's a timer event, make sure it's not pending
//
if (Event->Type & EFI_EVENT_TIMER) {
CoreSetTimer (Event, TimerCancel, 0);
}
CoreAcquireEventLock ();
//
// If the event is queued somewhere, remove it
//
if (Event->RuntimeLink.ForwardLink != NULL) {
RemoveEntryList (&Event->RuntimeLink);
}
if (Event->NotifyLink.ForwardLink != NULL) {
RemoveEntryList (&Event->NotifyLink);
}
if (Event->SignalLink.ForwardLink != NULL) {
RemoveEntryList (&Event->SignalLink);
}
CoreReleaseEventLock ();
//
// If the event is registered on a protocol notify, then remove it from the protocol database
//
CoreUnregisterProtocolNotify (Event);
Status = CoreFreePool (Event);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@@ -0,0 +1,55 @@
/*++
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:
execdata.c
Abstract:
Revision History
--*/
#include <DxeMain.h>
//
// gTpl - Task priority level
//
EFI_TPL gEfiCurrentTpl = EFI_TPL_APPLICATION;
//
// gEventQueueLock - Protects the event queus
//
EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
//
// gEventQueue - A list of event's to notify for each priority level
// gEventPending - A bitmask of the EventQueues that are pending
//
LIST_ENTRY gEventQueue[EFI_TPL_HIGH_LEVEL + 1];
UINTN gEventPending = 0;
//
// gEventSignalQueue - A list of events to signal based on EventGroup type
//
LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue);
//
// LIST of runtime events that need to be fired by RT AP.
//
LIST_ENTRY mRuntimeEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRuntimeEventList);

View File

@@ -0,0 +1,386 @@
/*++
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:
timer.c
Abstract:
EFI Event support
Revision History
--*/
#include <DxeMain.h>
//
// Internal prototypes
//
STATIC
UINT64
CoreCurrentSystemTime (
VOID
);
VOID
EFIAPI
CoreCheckTimers (
IN EFI_EVENT Event,
IN VOID *Context
);
STATIC
VOID
CoreInsertEventTimer (
IN IEVENT *Event
);
//
// Internal data
//
static LIST_ENTRY mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList);
static EFI_LOCK mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL - 1);
static EFI_EVENT mEfiCheckTimerEvent;
static EFI_LOCK mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
static UINT64 mEfiSystemTime = 0;
//
// Timer functions
//
VOID
CoreInitializeTimer (
VOID
)
/*++
Routine Description:
Initializes timer support
Arguments:
None
Returns:
None
--*/
{
EFI_STATUS Status;
Status = CoreCreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
EFI_TPL_HIGH_LEVEL - 1,
CoreCheckTimers,
NULL,
&mEfiCheckTimerEvent
);
ASSERT_EFI_ERROR (Status);
}
STATIC
UINT64
CoreCurrentSystemTime (
VOID
)
/*++
Routine Description:
Returns the current system time
Arguments:
None
Returns:
Returns the current system time
--*/
{
UINT64 SystemTime;
CoreAcquireLock (&mEfiSystemTimeLock);
SystemTime = mEfiSystemTime;
CoreReleaseLock (&mEfiSystemTimeLock);
return SystemTime;
}
VOID
EFIAPI
CoreTimerTick (
IN UINT64 Duration
)
/*++
Routine Description:
Called by the platform code to process a tick.
Arguments:
Duration - The number of 100ns elasped since the last call to TimerTick
Returns:
None
--*/
{
IEVENT *Event;
//
// Check runtiem flag in case there are ticks while exiting boot services
//
CoreAcquireLock (&mEfiSystemTimeLock);
//
// Update the system time
//
mEfiSystemTime += Duration;
//
// If the head of the list is expired, fire the timer event
// to process it
//
if (!IsListEmpty (&mEfiTimerList)) {
Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
if (Event->u.Timer.TriggerTime <= mEfiSystemTime) {
CoreSignalEvent (mEfiCheckTimerEvent);
}
}
CoreReleaseLock (&mEfiSystemTimeLock);
}
VOID
EFIAPI
CoreCheckTimers (
IN EFI_EVENT CheckEvent,
IN VOID *Context
)
/*++
Routine Description:
Checks the sorted timer list against the current system time.
Signals any expired event timer.
Arguments:
CheckEvent - Not used
Context - Not used
Returns:
None
--*/
{
UINT64 SystemTime;
IEVENT *Event;
//
// Check the timer database for expired timers
//
CoreAcquireLock (&mEfiTimerLock);
SystemTime = CoreCurrentSystemTime ();
while (!IsListEmpty (&mEfiTimerList)) {
Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
//
// If this timer is not expired, then we're done
//
if (Event->u.Timer.TriggerTime > SystemTime) {
break;
}
//
// Remove this timer from the timer queue
//
RemoveEntryList (&Event->u.Timer.Link);
Event->u.Timer.Link.ForwardLink = NULL;
//
// Signal it
//
CoreSignalEvent (Event);
//
// If this is a periodic timer, set it
//
if (Event->u.Timer.Period) {
//
// Compute the timers new trigger time
//
Event->u.Timer.TriggerTime = Event->u.Timer.TriggerTime + Event->u.Timer.Period;
//
// If that's before now, then reset the timer to start from now
//
if (Event->u.Timer.TriggerTime <= SystemTime) {
Event->u.Timer.TriggerTime = SystemTime;
CoreSignalEvent (mEfiCheckTimerEvent);
}
//
// Add the timer
//
CoreInsertEventTimer (Event);
}
}
CoreReleaseLock (&mEfiTimerLock);
}
STATIC
VOID
CoreInsertEventTimer (
IN IEVENT *Event
)
/*++
Routine Description:
Inserts the timer event
Arguments:
Event - Points to the internal structure of timer event to be installed
Returns:
None
--*/
{
UINT64 TriggerTime;
LIST_ENTRY *Link;
IEVENT *Event2;
ASSERT_LOCKED (&mEfiTimerLock);
//
// Get the timer's trigger time
//
TriggerTime = Event->u.Timer.TriggerTime;
//
// Insert the timer into the timer database in assending sorted order
//
for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) {
Event2 = CR (Link, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
if (Event2->u.Timer.TriggerTime > TriggerTime) {
break;
}
}
InsertTailList (Link, &Event->u.Timer.Link);
}
EFI_STATUS
EFIAPI
CoreSetTimer (
IN EFI_EVENT UserEvent,
IN EFI_TIMER_DELAY Type,
IN UINT64 TriggerTime
)
/*++
Routine Description:
Sets the type of timer and the trigger time for a timer event.
Arguments:
UserEvent - The timer event that is to be signaled at the specified time
Type - The type of time that is specified in TriggerTime
TriggerTime - The number of 100ns units until the timer expires
Returns:
EFI_SUCCESS - The event has been set to be signaled at the requested time
EFI_INVALID_PARAMETER - Event or Type is not valid
--*/
{
IEVENT *Event;
Event = UserEvent;
if (Event == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Event->Signature != EVENT_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
if (Type < 0 || Type > TimerRelative || !(Event->Type & EFI_EVENT_TIMER)) {
return EFI_INVALID_PARAMETER;
}
CoreAcquireLock (&mEfiTimerLock);
//
// If the timer is queued to the timer database, remove it
//
if (Event->u.Timer.Link.ForwardLink != NULL) {
RemoveEntryList (&Event->u.Timer.Link);
Event->u.Timer.Link.ForwardLink = NULL;
}
Event->u.Timer.TriggerTime = 0;
Event->u.Timer.Period = 0;
if (Type != TimerCancel) {
if (Type == TimerPeriodic) {
Event->u.Timer.Period = TriggerTime;
}
Event->u.Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;
CoreInsertEventTimer (Event);
if (TriggerTime == 0) {
CoreSignalEvent (mEfiCheckTimerEvent);
}
}
CoreReleaseLock (&mEfiTimerLock);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,198 @@
/*++
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:
tpl.c
Abstract:
Task priority function
--*/
#include <DxeMain.h>
STATIC
VOID
CoreSetInterruptState (
IN BOOLEAN Enable
)
/*++
Routine Description:
Set Interrupt State
Arguments:
Enable - The state of enable or disable interrupt
Returns:
None
--*/
{
if (gCpu != NULL) {
if (Enable) {
gCpu->EnableInterrupt(gCpu);
} else {
gCpu->DisableInterrupt(gCpu);
}
}
}
//
// Return the highest set bit
//
UINTN
CoreHighestSetBit (
IN UINTN Number
)
/*++
Routine Description:
Return the highest set bit
Arguments:
Number - The value to check
Returns:
Bit position of the highest set bit
--*/
{
UINTN msb;
msb = 31;
while ((msb > 0) && ((Number & (UINTN)(1 << msb)) == 0)) {
msb--;
}
return msb;
}
EFI_TPL
EFIAPI
CoreRaiseTpl (
IN EFI_TPL NewTpl
)
/*++
Routine Description:
Raise the task priority level to the new level.
High level is implemented by disabling processor interrupts.
Arguments:
NewTpl - New task priority level
Returns:
The previous task priority level
--*/
{
EFI_TPL OldTpl;
OldTpl = gEfiCurrentTpl;
ASSERT (OldTpl <= NewTpl);
ASSERT (VALID_TPL (NewTpl));
//
// If raising to high level, disable interrupts
//
if (NewTpl >= EFI_TPL_HIGH_LEVEL && OldTpl < EFI_TPL_HIGH_LEVEL) {
CoreSetInterruptState (FALSE);
}
//
// Set the new value
//
gEfiCurrentTpl = NewTpl;
return OldTpl;
}
VOID
EFIAPI
CoreRestoreTpl (
IN EFI_TPL NewTpl
)
/*++
Routine Description:
Lowers the task priority to the previous value. If the new
priority unmasks events at a higher priority, they are dispatched.
Arguments:
NewTpl - New, lower, task priority
Returns:
None
--*/
{
EFI_TPL OldTpl;
OldTpl = gEfiCurrentTpl;
ASSERT (NewTpl <= OldTpl);
ASSERT (VALID_TPL (NewTpl));
//
// If lowering below HIGH_LEVEL, make sure
// interrupts are enabled
//
if (OldTpl >= EFI_TPL_HIGH_LEVEL && NewTpl < EFI_TPL_HIGH_LEVEL) {
gEfiCurrentTpl = EFI_TPL_HIGH_LEVEL;
}
//
// Dispatch any pending events
//
while ((-2 << NewTpl) & gEventPending) {
gEfiCurrentTpl = CoreHighestSetBit (gEventPending);
if (gEfiCurrentTpl < EFI_TPL_HIGH_LEVEL) {
CoreSetInterruptState (TRUE);
}
CoreDispatchEventNotifies (gEfiCurrentTpl);
}
//
// Set the new value
//
gEfiCurrentTpl = NewTpl;
//
// If lowering below HIGH_LEVEL, make sure
// interrupts are enabled
//
if (gEfiCurrentTpl < EFI_TPL_HIGH_LEVEL) {
CoreSetInterruptState (TRUE);
}
}

View File

@@ -0,0 +1,266 @@
/*++
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:
Ffs.c
Abstract:
FFS file access utilities.
--*/
#include <DxeMain.h>
#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *)((UINTN)(Address)))
EFI_FFS_FILE_STATE
GetFileState (
IN UINT8 ErasePolarity,
IN EFI_FFS_FILE_HEADER *FfsHeader
)
/*++
Routine Description:
Get the FFS file state by checking the highest bit set in the header's state field
Arguments:
ErasePolarity - Erase polarity attribute of the firmware volume
FfsHeader - Points to the FFS file header
Returns:
FFS File state
--*/
{
EFI_FFS_FILE_STATE FileState;
UINT8 HighestBit;
FileState = FfsHeader->State;
if (ErasePolarity != 0) {
FileState = (EFI_FFS_FILE_STATE)~FileState;
}
HighestBit = 0x80;
while (HighestBit != 0 && ((HighestBit & FileState) == 0)) {
HighestBit >>= 1;
}
return (EFI_FFS_FILE_STATE)HighestBit;
}
BOOLEAN
IsBufferErased (
IN UINT8 ErasePolarity,
IN VOID *InBuffer,
IN UINTN BufferSize
)
/*++
Routine Description:
Check if a block of buffer is erased
Arguments:
ErasePolarity - Erase polarity attribute of the firmware volume
InBuffer - The buffer to be checked
BufferSize - Size of the buffer in bytes
Returns:
TRUE - The block of buffer is erased
FALSE - The block of buffer is not erased
--*/
{
UINTN Count;
UINT8 EraseByte;
UINT8 *Buffer;
if(ErasePolarity == 1) {
EraseByte = 0xFF;
} else {
EraseByte = 0;
}
Buffer = InBuffer;
for (Count = 0; Count < BufferSize; Count++) {
if (Buffer[Count] != EraseByte) {
return FALSE;
}
}
return TRUE;
}
BOOLEAN
VerifyFvHeaderChecksum (
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
)
/*++
Routine Description:
Verify checksum of the firmware volume header
Arguments:
FvHeader - Points to the firmware volume header to be checked
Returns:
TRUE - Checksum verification passed
FALSE - Checksum verification failed
--*/
{
UINT32 Index;
UINT32 HeaderLength;
UINT16 Checksum;
UINT16 *ptr;
HeaderLength = FvHeader->HeaderLength;
ptr = (UINT16 *)FvHeader;
Checksum = 0;
for (Index = 0; Index < HeaderLength / sizeof (UINT16); Index++) {
Checksum = (UINT16)(Checksum + ptr[Index]);
}
if (Checksum == 0) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
VerifyHeaderChecksum (
IN EFI_FFS_FILE_HEADER *FfsHeader
)
/*++
Routine Description:
Verify checksum of the FFS file header
Arguments:
FfsHeader - Points to the FFS file header to be checked
Returns:
TRUE - Checksum verification passed
FALSE - Checksum verification failed
--*/
{
UINT32 Index;
UINT8 *ptr;
UINT8 HeaderChecksum;
ptr = (UINT8 *)FfsHeader;
HeaderChecksum = 0;
for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {
HeaderChecksum = (UINT8)(HeaderChecksum + ptr[Index]);
}
HeaderChecksum = HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File;
if (HeaderChecksum == 0) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
IsValidFfsHeader (
IN UINT8 ErasePolarity,
IN EFI_FFS_FILE_HEADER *FfsHeader,
OUT EFI_FFS_FILE_STATE *FileState
)
/*++
Routine Description:
Check if it's a valid FFS file header
Arguments:
ErasePolarity - Erase polarity attribute of the firmware volume
FfsHeader - Points to the FFS file header to be checked
FileState - FFS file state to be returned
Returns:
TRUE - Valid FFS file header
FALSE - Invalid FFS file header
--*/
{
*FileState = GetFileState (ErasePolarity, FfsHeader);
switch (*FileState) {
case EFI_FILE_HEADER_VALID:
case EFI_FILE_DATA_VALID:
case EFI_FILE_MARKED_FOR_UPDATE:
case EFI_FILE_DELETED:
//
// Here we need to verify header checksum
//
return VerifyHeaderChecksum (FfsHeader);
case EFI_FILE_HEADER_CONSTRUCTION:
case EFI_FILE_HEADER_INVALID:
default:
return FALSE;
}
}
BOOLEAN
IsValidFfsFile (
IN UINT8 ErasePolarity,
IN EFI_FFS_FILE_HEADER *FfsHeader
)
/*++
Routine Description:
Check if it's a valid FFS file.
Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
Arguments:
ErasePolarity - Erase polarity attribute of the firmware volume
FfsHeader - Points to the FFS file to be checked
Returns:
TRUE - Valid FFS file
FALSE - Invalid FFS file
--*/
{
EFI_FFS_FILE_STATE FileState;
FileState = GetFileState (ErasePolarity, FfsHeader);
switch (FileState) {
case EFI_FILE_DELETED:
case EFI_FILE_DATA_VALID:
case EFI_FILE_MARKED_FOR_UPDATE:
//
// Some other vliadation like file content checksum might be done here.
// For performance issue, Tiano only do FileState check.
//
return TRUE;
default:
return FALSE;
}
}

View File

@@ -0,0 +1,553 @@
/*++
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:
FwVol.c
Abstract:
Firmware File System driver that produce Firmware Volume protocol.
Layers on top of Firmware Block protocol to produce a file abstraction
of FV based files.
--*/
#include <DxeMain.h>
#define KEYSIZE sizeof (UINTN)
//
// Protocol notify related globals
//
VOID *gEfiFwVolBlockNotifyReg;
EFI_EVENT gEfiFwVolBlockEvent;
FV_DEVICE mFvDevice = {
FV_DEVICE_SIGNATURE,
NULL,
NULL,
{
FvGetVolumeAttributes,
FvSetVolumeAttributes,
FvReadFile,
FvReadFileSection,
FvWriteFile,
FvGetNextFile,
KEYSIZE
},
NULL,
NULL,
NULL,
NULL,
{ NULL, NULL },
0
};
//
// FFS helper functions
//
EFI_STATUS
GetFwVolHeader (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
)
/*++
Routine Description:
given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
copy the volume header into it.
Arguments:
Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume
header
FwVolHeader - Pointer to pointer to allocated buffer in which the volume
header is returned.
Returns:
EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
EFI_SUCCESS - Successfully read volume header to the allocated buffer.
--*/
{
EFI_STATUS Status;
EFI_FIRMWARE_VOLUME_HEADER TempFvh;
UINTN FvhLength;
UINT8 *Buffer;
//
//Determine the real length of FV header
//
FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
Status = Fvb->Read (Fvb, 0, 0, &FvhLength, (UINT8 *)&TempFvh);
//
// Allocate a buffer for the caller
//
*FwVolHeader = CoreAllocateBootServicesPool (TempFvh.HeaderLength);
if (*FwVolHeader == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Copy the standard header into the buffer
//
CopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
//
// Read the rest of the header
//
FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER);
Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER);
Status = Fvb->Read (Fvb, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvhLength, Buffer);
if (EFI_ERROR (Status)) {
//
// Read failed so free buffer
//
CoreFreePool (*FwVolHeader);
}
return Status;
}
STATIC
VOID
FreeFvDeviceResource (
IN FV_DEVICE *FvDevice
)
/*++
Routine Description:
Free FvDevice resource when error happens
Arguments:
FvDevice - pointer to the FvDevice to be freed.
Returns:
None.
--*/
{
FFS_FILE_LIST_ENTRY *FfsFileEntry;
LIST_ENTRY *NextEntry;
//
// Free File List Entry
//
FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink;
while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {
NextEntry = (&FfsFileEntry->Link)->ForwardLink;
if (FfsFileEntry->StreamHandle != 0) {
//
// Close stream and free resources from SEP
//
FfsFileEntry->Sep->CloseSectionStream (FfsFileEntry->Sep, FfsFileEntry->StreamHandle);
}
CoreFreePool (FfsFileEntry);
FfsFileEntry = (FFS_FILE_LIST_ENTRY *)NextEntry;
}
//
// Free the cache
//
CoreFreePool (FvDevice->CachedFv);
//
// Free Volume Header
//
CoreFreePool (FvDevice->FwVolHeader);
return;
}
EFI_STATUS
FvCheck (
IN OUT FV_DEVICE *FvDevice
)
/*++
Routine Description:
Check if a FV is consistent and allocate cache
Arguments:
FvDevice - pointer to the FvDevice to be checked.
Returns:
EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
EFI_SUCCESS - FV is consistent and cache is allocated.
EFI_VOLUME_CORRUPTED - File system is corrupted.
--*/
{
EFI_STATUS Status;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
EFI_FVB_ATTRIBUTES FvbAttributes;
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
FFS_FILE_LIST_ENTRY *FfsFileEntry;
EFI_FFS_FILE_HEADER *FfsHeader;
UINT8 *CacheLocation;
UINTN LbaOffset;
UINTN Index;
EFI_LBA LbaIndex;
UINTN Size;
UINTN FileLength;
EFI_FFS_FILE_STATE FileState;
UINT8 *TopFvAddress;
UINTN TestLength;
Fvb = FvDevice->Fvb;
FwVolHeader = FvDevice->FwVolHeader;
Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Size is the size of the FV minus the head. We have already allocated
// the header to check to make sure the volume is valid
//
Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength);
FvDevice->CachedFv = CoreAllocateZeroBootServicesPool (Size);
if (FvDevice->CachedFv == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Remember a pointer to the end fo the CachedFv
//
FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;
//
// Copy FV minus header into memory using the block map we have all ready
// read into memory.
//
BlockMap = FwVolHeader->FvBlockMap;
CacheLocation = FvDevice->CachedFv;
LbaIndex = 0;
LbaOffset = FwVolHeader->HeaderLength;
while ((BlockMap->NumBlocks != 0) || (BlockMap->BlockLength != 0)) {
for (Index = 0; Index < BlockMap->NumBlocks; Index ++) {
Size = BlockMap->BlockLength;
if (Index == 0) {
//
// Cache does not include FV Header
//
Size -= LbaOffset;
}
Status = Fvb->Read (Fvb,
LbaIndex,
LbaOffset,
&Size,
CacheLocation
);
//
// Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->BlockLength
//
if (EFI_ERROR (Status)) {
goto Done;
}
//
// After we skip Fv Header always read from start of block
//
LbaOffset = 0;
LbaIndex++;
CacheLocation += Size;
}
BlockMap++;
}
//
// Scan to check the free space & File list
//
if (FvbAttributes & EFI_FVB_ERASE_POLARITY) {
FvDevice->ErasePolarity = 1;
} else {
FvDevice->ErasePolarity = 0;
}
//
// go through the whole FV cache, check the consistence of the FV.
// Make a linked list off all the Ffs file headers
//
Status = EFI_SUCCESS;
InitializeListHead (&FvDevice->FfsFileListHeader);
//
// Build FFS list
//
FfsHeader = (EFI_FFS_FILE_HEADER *)FvDevice->CachedFv;
TopFvAddress = FvDevice->EndOfCachedFv;
while ((UINT8 *)FfsHeader < TopFvAddress) {
TestLength = TopFvAddress - ((UINT8 *)FfsHeader);
if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
TestLength = sizeof (EFI_FFS_FILE_HEADER);
}
if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) {
//
// We have found the free space so we are done!
//
goto Done;
}
if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) {
if ((FileState == EFI_FILE_HEADER_INVALID) ||
(FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
FfsHeader++;
continue;
} else {
//
// File system is corrputed
//
Status = EFI_VOLUME_CORRUPTED;
goto Done;
}
}
if (!IsValidFfsFile (FvDevice->ErasePolarity, FfsHeader)) {
//
// File system is corrupted
//
Status = EFI_VOLUME_CORRUPTED;
goto Done;
}
//
// Size[3] is a three byte array, read 4 bytes and throw one away
//
FileLength = *(UINT32 *)&FfsHeader->Size[0] & 0x00FFFFFF;
FileState = GetFileState (FvDevice->ErasePolarity, FfsHeader);
//
// check for non-deleted file
//
if (FileState != EFI_FILE_DELETED) {
//
// Create a FFS list entry for each non-deleted file
//
FfsFileEntry = CoreAllocateZeroBootServicesPool (sizeof (FFS_FILE_LIST_ENTRY));
if (FfsFileEntry == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
FfsFileEntry->FfsHeader = FfsHeader;
InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
}
FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FfsHeader) + FileLength);
//
// Adjust pointer to the next 8-byte aligned boundry.
//
FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07);
}
Done:
if (EFI_ERROR (Status)) {
FreeFvDeviceResource (FvDevice);
}
return Status;
}
STATIC
VOID
EFIAPI
NotifyFwVolBlock (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
This notification function is invoked when an instance of the
EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the
EFI_FIRMWARE_VOLUME_PROTOCOL on the same handle. This is the function where
the actual initialization of the EFI_FIRMWARE_VOLUME_PROTOCOL is done.
Arguments:
Event - The event that occured
Context - For EFI compatiblity. Not used.
Returns:
None.
--*/
{
EFI_HANDLE Handle;
EFI_STATUS Status;
UINTN BufferSize;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
FV_DEVICE *FvDevice;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
//
// Examine all new handles
//
for (;;) {
//
// Get the next handle
//
BufferSize = sizeof (Handle);
Status = CoreLocateHandle (
ByRegisterNotify,
NULL,
gEfiFwVolBlockNotifyReg,
&BufferSize,
&Handle
);
//
// If not found, we're done
//
if (EFI_NOT_FOUND == Status) {
break;
}
if (EFI_ERROR (Status)) {
continue;
}
//
// Get the FirmwareVolumeBlock protocol on that handle
//
Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
ASSERT_EFI_ERROR (Status);
//
// Make sure the Fv Header is O.K.
//
Status = GetFwVolHeader (Fvb, &FwVolHeader);
if (EFI_ERROR (Status)) {
return;
}
if (!VerifyFvHeaderChecksum (FwVolHeader)) {
CoreFreePool (FwVolHeader);
continue;
}
//
// Check to see that the file system is indeed formatted in a way we can
// understand it...
//
if (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystemGuid)) {
continue;
}
//
// Check if there is an FV protocol already installed in that handle
//
Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Fv);
if (!EFI_ERROR (Status)) {
//
// Update Fv to use a new Fvb
//
FvDevice = _CR (Fv, FV_DEVICE, Fv);
if (FvDevice->Signature == FV_DEVICE_SIGNATURE) {
//
// Only write into our device structure if it's our device structure
//
FvDevice->Fvb = Fvb;
}
} else {
//
// No FwVol protocol on the handle so create a new one
//
FvDevice = CoreAllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);
if (FvDevice == NULL) {
return;
}
FvDevice->Fvb = Fvb;
FvDevice->Handle = Handle;
FvDevice->FwVolHeader = FwVolHeader;
FvDevice->Fv.ParentHandle = Fvb->ParentHandle;
//
// Install an New FV protocol on the existing handle
//
Status = CoreInstallProtocolInterface (
&Handle,
&gEfiFirmwareVolumeProtocolGuid,
EFI_NATIVE_INTERFACE,
&FvDevice->Fv
);
ASSERT_EFI_ERROR (Status);
}
}
return;
}
EFI_STATUS
EFIAPI
FwVolDriverInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
This routine is the driver initialization entry point. It initializes the
libraries, and registers two notification functions. These notification
functions are responsible for building the FV stack dynamically.
Arguments:
ImageHandle - The image handle.
SystemTable - The system table.
Returns:
EFI_SUCCESS - Function successfully returned.
--*/
{
gEfiFwVolBlockEvent = CoreCreateProtocolNotifyEvent (
&gEfiFirmwareVolumeBlockProtocolGuid,
EFI_TPL_CALLBACK,
NotifyFwVolBlock,
NULL,
&gEfiFwVolBlockNotifyReg,
TRUE
);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,99 @@
/*++
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:
FwVolAttrib.c
Abstract:
Implements get/set firmware volume attributes
--*/
#include <DxeMain.h>
EFI_STATUS
EFIAPI
FvGetVolumeAttributes (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
OUT EFI_FV_ATTRIBUTES *Attributes
)
/*++
Routine Description:
Retrieves attributes, insures positive polarity of attribute bits, returns
resulting attributes in output parameter
Arguments:
This - Calling context
Attributes - output buffer which contains attributes
Returns:
EFI_SUCCESS - Successfully got volume attributes
--*/
{
EFI_STATUS Status;
FV_DEVICE *FvDevice;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
EFI_FVB_ATTRIBUTES FvbAttributes;
FvDevice = FV_DEVICE_FROM_THIS (This);
Fvb = FvDevice->Fvb;
if (FvDevice->CachedFv == NULL) {
Status = FvCheck (FvDevice);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// First get the Firmware Volume Block Attributes
//
Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes);
//
// Mask out Fvb bits that are not defined in FV
//
FvbAttributes &= 0xfffff0ff;
*Attributes = (EFI_FV_ATTRIBUTES)FvbAttributes;
return Status;
}
EFI_STATUS
EFIAPI
FvSetVolumeAttributes (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN OUT EFI_FV_ATTRIBUTES *Attributes
)
/*++
Routine Description:
Sets current attributes for volume
Arguments:
This - Calling context
Attributes - At input, contains attributes to be set. At output contains
new value of FV
Returns:
EFI_UNSUPPORTED - Could not be set.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,516 @@
/*++
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:
FwVolRead.c
Abstract:
Implements read firmware file
--*/
#include <DxeMain.h>
/*++
Required Alignment Alignment Value in FFS Alignment Value in
(bytes) Attributes Field Firmware Volume Interfaces
1 0 0
2 0 1
4 0 2
8 0 3
16 1 4
128 2 7
512 3 9
1 KB 4 10
4 KB 5 12
32 KB 6 15
64 KB 7 16
--*/
UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16};
STATIC
EFI_FV_FILE_ATTRIBUTES
FfsAttributes2FvFileAttributes (
IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
)
/*++
Routine Description:
Convert the FFS File Attributes to FV File Attributes
Arguments:
FfsAttributes - The attributes of UINT8 type.
Returns:
The attributes of EFI_FV_FILE_ATTRIBUTES
--*/
{
FfsAttributes = (EFI_FFS_FILE_ATTRIBUTES)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
ASSERT (FfsAttributes < 8);
return (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[FfsAttributes];
}
EFI_STATUS
EFIAPI
FvGetNextFile (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN OUT VOID *Key,
IN OUT EFI_FV_FILETYPE *FileType,
OUT EFI_GUID *NameGuid,
OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
OUT UINTN *Size
)
/*++
Routine Description:
Given the input key, search for the next matching file in the volume.
Arguments:
This - Indicates the calling context.
FileType - FileType is a pointer to a caller allocated
EFI_FV_FILETYPE. The GetNextFile() API can filter it's
search for files based on the value of *FileType input.
A *FileType input of 0 causes GetNextFile() to search for
files of all types. If a file is found, the file's type
is returned in *FileType. *FileType is not modified if
no file is found.
Key - Key is a pointer to a caller allocated buffer that
contains implementation specific data that is used to
track where to begin the search for the next file.
The size of the buffer must be at least This->KeySize
bytes long. To reinitialize the search and begin from
the beginning of the firmware volume, the entire buffer
must be cleared to zero. Other than clearing the buffer
to initiate a new search, the caller must not modify the
data in the buffer between calls to GetNextFile().
NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
If a file is found, the file's name is returned in
*NameGuid. *NameGuid is not modified if no file is
found.
Attributes - Attributes is a pointer to a caller allocated
EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
attributes are returned in *Attributes. *Attributes is
not modified if no file is found.
Size - Size is a pointer to a caller allocated UINTN.
If a file is found, the file's size is returned in *Size.
*Size is not modified if no file is found.
Returns:
EFI_SUCCESS - Successfully find the file.
EFI_DEVICE_ERROR - Device error.
EFI_ACCESS_DENIED - Fv could not read.
EFI_NOT_FOUND - No matching file found.
EFI_INVALID_PARAMETER - Invalid parameter
--*/
{
EFI_STATUS Status;
FV_DEVICE *FvDevice;
EFI_FV_ATTRIBUTES FvAttributes;
EFI_FFS_FILE_HEADER *FfsFileHeader;
UINTN *KeyValue;
LIST_ENTRY *Link;
FFS_FILE_LIST_ENTRY *FfsFileEntry;
UINTN FileLength;
FvDevice = FV_DEVICE_FROM_THIS (This);
Status = FvGetVolumeAttributes (This, &FvAttributes);
if (EFI_ERROR (Status)){
return Status;
}
//
// Check if read operation is enabled
//
if ((FvAttributes & EFI_FV_READ_STATUS) == 0) {
return EFI_ACCESS_DENIED;
}
if (*FileType > EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
//
// File type needs to be in 0 - 0x0B
//
return EFI_INVALID_PARAMETER;
}
KeyValue = (UINTN *)Key;
for (;;) {
if (*KeyValue == 0) {
//
// Search for 1st matching file
//
Link = &FvDevice->FfsFileListHeader;
} else {
//
// Key is pointer to FFsFileEntry, so get next one
//
Link = (LIST_ENTRY *)(*KeyValue);
}
if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
//
// Next is end of list so we did not find data
//
return EFI_NOT_FOUND;
}
FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink;
FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader;
//
// remember the key
//
*KeyValue = (UINTN)FfsFileEntry;
if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
//
// we ignore pad files
//
continue;
}
if (*FileType == 0) {
//
// Process all file types so we have a match
//
break;
}
if (*FileType == FfsFileHeader->Type) {
//
// Found a matching file type
//
break;
}
}
//
// Return FileType, NameGuid, and Attributes
//
*FileType = FfsFileHeader->Type;
CopyMem (NameGuid, &FfsFileHeader->Name, sizeof (EFI_GUID));
*Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);
//
// Read four bytes out of the 3 byte array and throw out extra data
//
FileLength = *(UINT32 *)&FfsFileHeader->Size[0] & 0x00FFFFFF;
//
// we need to substract the header size
//
*Size = FileLength - sizeof(EFI_FFS_FILE_HEADER);
if (FfsFileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
//
// If tail is present substract it's size;
//
*Size -= sizeof(EFI_FFS_FILE_TAIL);
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
FvReadFile (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN EFI_GUID *NameGuid,
IN OUT VOID **Buffer,
IN OUT UINTN *BufferSize,
OUT EFI_FV_FILETYPE *FoundType,
OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
OUT UINT32 *AuthenticationStatus
)
/*++
Routine Description:
Locates a file in the firmware volume and
copies it to the supplied buffer.
Arguments:
This - Indicates the calling context.
NameGuid - Pointer to an EFI_GUID, which is the filename.
Buffer - Buffer is a pointer to pointer to a buffer in
which the file or section contents or are returned.
BufferSize - BufferSize is a pointer to caller allocated
UINTN. On input *BufferSize indicates the size
in bytes of the memory region pointed to by
Buffer. On output, *BufferSize contains the number
of bytes required to read the file.
FoundType - FoundType is a pointer to a caller allocated
EFI_FV_FILETYPE that on successful return from Read()
contains the type of file read. This output reflects
the file type irrespective of the value of the
SectionType input.
FileAttributes - FileAttributes is a pointer to a caller allocated
EFI_FV_FILE_ATTRIBUTES. On successful return from
Read(), *FileAttributes contains the attributes of
the file read.
AuthenticationStatus - AuthenticationStatus is a pointer to a caller
allocated UINTN in which the authentication status
is returned.
Returns:
EFI_SUCCESS - Successfully read to memory buffer.
EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
EFI_NOT_FOUND - Not found.
EFI_DEVICE_ERROR - Device error.
EFI_ACCESS_DENIED - Could not read.
EFI_INVALID_PARAMETER - Invalid parameter.
EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
--*/
{
EFI_STATUS Status;
FV_DEVICE *FvDevice;
EFI_GUID SearchNameGuid;
EFI_FV_FILETYPE LocalFoundType;
EFI_FV_FILE_ATTRIBUTES LocalAttributes;
UINTN FileSize;
UINT8 *SrcPtr;
EFI_FFS_FILE_HEADER *FfsHeader;
UINTN InputBufferSize;
if (NULL == NameGuid) {
return EFI_INVALID_PARAMETER;
}
FvDevice = FV_DEVICE_FROM_THIS (This);
//
// Keep looking until we find the matching NameGuid.
// The Key is really an FfsFileEntry
//
FvDevice->LastKey = 0;
do {
LocalFoundType = 0;
Status = FvGetNextFile (
This,
&FvDevice->LastKey,
&LocalFoundType,
&SearchNameGuid,
&LocalAttributes,
&FileSize
);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
} while (!CompareGuid (&SearchNameGuid, NameGuid));
//
// Get a pointer to the header
//
FfsHeader = FvDevice->LastKey->FfsHeader;
//
// Remember callers buffer size
//
InputBufferSize = *BufferSize;
//
// Calculate return values
//
*FoundType = FfsHeader->Type;
*FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);
*AuthenticationStatus = 0;
*BufferSize = FileSize;
if (Buffer == NULL) {
//
// If Buffer is NULL, we only want to get the information colected so far
//
return EFI_SUCCESS;
}
//
// Skip over file header
//
SrcPtr = ((UINT8 *)FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);
Status = EFI_SUCCESS;
if (*Buffer == NULL) {
//
// Caller passed in a pointer so allocate buffer for them
//
*Buffer = CoreAllocateBootServicesPool (FileSize);
if (*Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
} else if (FileSize > InputBufferSize) {
//
// Callers buffer was not big enough
//
Status = EFI_WARN_BUFFER_TOO_SMALL;
FileSize = InputBufferSize;
}
//
// Copy data into callers buffer
//
CopyMem (*Buffer, SrcPtr, FileSize);
return Status;
}
EFI_STATUS
EFIAPI
FvReadFileSection (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN EFI_GUID *NameGuid,
IN EFI_SECTION_TYPE SectionType,
IN UINTN SectionInstance,
IN OUT VOID **Buffer,
IN OUT UINTN *BufferSize,
OUT UINT32 *AuthenticationStatus
)
/*++
Routine Description:
Locates a section in a given FFS File and
copies it to the supplied buffer (not including section header).
Arguments:
This - Indicates the calling context.
NameGuid - Pointer to an EFI_GUID, which is the filename.
SectionType - Indicates the section type to return.
SectionInstance - Indicates which instance of sections with a type of
SectionType to return.
Buffer - Buffer is a pointer to pointer to a buffer in which
the file or section contents or are returned.
BufferSize - BufferSize is a pointer to caller allocated UINTN.
AuthenticationStatus -AuthenticationStatus is a pointer to a caller
allocated UINT32 in which the authentication status
is returned.
Returns:
EFI_SUCCESS - Successfully read the file section into buffer.
EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
EFI_NOT_FOUND - Section not found.
EFI_DEVICE_ERROR - Device error.
EFI_ACCESS_DENIED - Could not read.
EFI_INVALID_PARAMETER - Invalid parameter.
--*/
{
EFI_STATUS Status;
FV_DEVICE *FvDevice;
EFI_FV_FILETYPE FileType;
EFI_FV_FILE_ATTRIBUTES FileAttributes;
UINTN FileSize;
UINT8 *FileBuffer;
EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
FFS_FILE_LIST_ENTRY *FfsEntry;
if (NULL == NameGuid || Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
FvDevice = FV_DEVICE_FROM_THIS (This);
//
// Read the whole file into buffer
//
FileBuffer = NULL;
Status = FvReadFile (
This,
NameGuid,
(VOID **)&FileBuffer,
&FileSize,
&FileType,
&FileAttributes,
AuthenticationStatus
);
//
// Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.
//
FfsEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->LastKey;
if (EFI_ERROR (Status)) {
return Status;
}
//
// Check to see that the file actually HAS sections before we go any further.
//
if (FileType == EFI_FV_FILETYPE_RAW) {
Status = EFI_NOT_FOUND;
goto Done;
}
//
// Use FfsEntry to cache Section Extraction Protocol Inforomation
//
if (FfsEntry->StreamHandle == 0) {
//
// Located the protocol
//
Status = CoreLocateProtocol (&gEfiSectionExtractionProtocolGuid, NULL, (VOID **)&Sep);
//
// Section Extraction Protocol is part of Dxe Core so this should never fail
//
ASSERT_EFI_ERROR (Status);
Status = Sep->OpenSectionStream (
Sep,
FileSize,
FileBuffer,
&FfsEntry->StreamHandle
);
if (EFI_ERROR (Status)) {
goto Done;
}
FfsEntry->Sep = Sep;
} else {
//
// Get cached copy of Sep
//
Sep = FfsEntry->Sep;
}
//
// If SectionType == 0 We need the whole section stream
//
Status = Sep->GetSection (
Sep,
FfsEntry->StreamHandle,
(SectionType == 0) ? NULL : &SectionType,
NULL,
(SectionType == 0) ? 0 : SectionInstance,
Buffer,
BufferSize,
AuthenticationStatus
);
//
// Close of stream defered to close of FfsHeader list to allow SEP to cache data
//
Done:
CoreFreePool (FileBuffer);
return Status;
}

View File

@@ -0,0 +1,60 @@
/*++
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:
FwVolWrite.c
Abstract:
Implements write firmware file
--*/
#include <DxeMain.h>
EFI_STATUS
EFIAPI
FvWriteFile (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN UINT32 NumberOfFiles,
IN EFI_FV_WRITE_POLICY WritePolicy,
IN EFI_FV_WRITE_FILE_DATA *FileData
)
/*++
Routine Description:
Writes one or more files to the firmware volume.
Arguments:
This - Indicates the calling context.
NumberOfFiles - Number of files.
WritePolicy - WritePolicy indicates the level of reliability for
the write in the event of a power failure or other
system failure during the write operation.
FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA.
Each element of FileData[] represents a file to be written.
Returns:
EFI_SUCCESS - Files successfully written to firmware volume
EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
EFI_DEVICE_ERROR - Device error.
EFI_WRITE_PROTECTED - Write protected.
EFI_NOT_FOUND - Not found.
EFI_INVALID_PARAMETER - Invalid parameter.
EFI_UNSUPPORTED - This function not supported.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,324 @@
/*++
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:
FwVolBlock.h
Abstract:
Firmware Volume Block protocol.. Consumes FV hobs and creates
appropriate block protocols.
Also consumes NT_NON_MM_FV envinronment variable and produces appropriate
block protocols fro them also... (this is TBD)
--*/
#ifndef _FWVOL_BLOCK_H_
#define _FWVOL_BLOCK_H_
#define FVB_DEVICE_SIGNATURE EFI_SIGNATURE_32('_','F','V','B')
typedef struct {
UINTN Base;
UINTN Length;
} LBA_CACHE;
typedef struct {
MEMMAP_DEVICE_PATH MemMapDevPath;
EFI_DEVICE_PATH_PROTOCOL EndDevPath;
} FV_DEVICE_PATH;
typedef struct {
UINTN Signature;
EFI_HANDLE Handle;
FV_DEVICE_PATH DevicePath;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance;
UINTN NumBlocks;
LBA_CACHE *LbaCache;
UINT32 FvbAttributes;
EFI_PHYSICAL_ADDRESS BaseAddress;
} EFI_FW_VOL_BLOCK_DEVICE;
#define FVB_DEVICE_FROM_THIS(a) \
CR(a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)
EFI_STATUS
EFIAPI
FwVolBlockDriverInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
This routine is the driver initialization entry point. It initializes the
libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
Arguments:
ImageHandle - The image handle.
SystemTable - The system table.
Returns:
EFI_SUCCESS - Successfully initialized firmware volume block driver.
--*/
;
EFI_STATUS
EFIAPI
FwVolBlockGetAttributes (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
OUT EFI_FVB_ATTRIBUTES *Attributes
)
/*++
Routine Description:
Retrieves Volume attributes. No polarity translations are done.
Arguments:
This - Calling context
Attributes - output buffer which contains attributes
Returns:
EFI_SUCCESS - The firmware volume attributes were returned.
--*/
;
EFI_STATUS
EFIAPI
FwVolBlockSetAttributes (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
OUT EFI_FVB_ATTRIBUTES *Attributes
)
/*++
Routine Description:
Modifies the current settings of the firmware volume according to the input parameter.
Arguments:
This - Calling context
Attributes - input buffer which contains attributes
Returns:
EFI_SUCCESS - The firmware volume attributes were returned.
EFI_INVALID_PARAMETER - The attributes requested are in conflict with the capabilities as
declared in the firmware volume header.
EFI_UNSUPPORTED - Not supported.
--*/
;
EFI_STATUS
EFIAPI
FwVolBlockEraseBlock (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
...
)
/*++
Routine Description:
The EraseBlock() function erases one or more blocks as denoted by the
variable argument list. The entire parameter list of blocks must be verified
prior to 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 EraseBlock() function must return
EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
Arguments:
This - Calling context
... - Starting LBA followed by Number of Lba to erase. a -1 to terminate
the list.
Returns:
EFI_SUCCESS - The erase request was successfully completed.
EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
EFI_DEVICE_ERROR - The block device is not functioning correctly and could not be
written. The firmware device may have been partially erased.
EFI_INVALID_PARAMETER - One or more of the LBAs listed in the variable argument list do
EFI_UNSUPPORTED - Not supported.
--*/
;
EFI_STATUS
EFIAPI
FwVolBlockReadBlock (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer
)
/*++
Routine Description:
Read the specified number of bytes from the block to the input buffer.
Arguments:
This - Indicates the calling context.
Lba - The starting logical block index to read.
Offset - Offset into the block at which to begin reading.
NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
total size of the buffer. At exit, *NumBytes contains the
total number of bytes actually read.
Buffer - Pinter to a caller-allocated buffer that contains the destine
for the read.
Returns:
EFI_SUCCESS - The firmware volume was read successfully.
EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary.
EFI_ACCESS_DENIED - Access denied.
EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read.
--*/
;
EFI_STATUS
EFIAPI
FwVolBlockWriteBlock (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer
)
/*++
Routine Description:
Writes the specified number of bytes from the input buffer to the block.
Arguments:
This - Indicates the calling context.
Lba - The starting logical block index to write to.
Offset - Offset into the block at which to begin writing.
NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
total size of the buffer. At exit, *NumBytes contains the
total number of bytes actually written.
Buffer - Pinter to a caller-allocated buffer that contains the source
for the write.
Returns:
EFI_SUCCESS - The firmware volume was written successfully.
EFI_BAD_BUFFER_SIZE - The write was attempted across an LBA boundary. On output,
NumBytes contains the total number of bytes actually written.
EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
EFI_DEVICE_ERROR - The block device is malfunctioning and could not be written.
EFI_UNSUPPORTED - Not supported.
--*/
;
EFI_STATUS
EFIAPI
FwVolBlockGetPhysicalAddress (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
OUT EFI_PHYSICAL_ADDRESS *Address
)
/*++
Routine Description:
Get Fvb's base address.
Arguments:
This - Indicates the calling context.
Address - Fvb device base address.
Returns:
EFI_SUCCESS - Successfully got Fvb's base address.
EFI_UNSUPPORTED - Not supported.
--*/
;
EFI_STATUS
EFIAPI
FwVolBlockGetBlockSize (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
IN EFI_LBA Lba,
OUT UINTN *BlockSize,
OUT UINTN *NumberOfBlocks
)
/*++
Routine Description:
Retrieves the size in bytes of a specific block within a firmware volume.
Arguments:
This - Indicates the calling context.
Lba - Indicates the block for which to return the size.
BlockSize - Pointer to a caller-allocated UINTN in which the size of the
block is returned.
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.
Returns:
EFI_SUCCESS - The firmware volume base address is returned.
EFI_INVALID_PARAMETER - The requested LBA is out of range.
--*/
;
EFI_STATUS
FwVolBlockDriverInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
This routine is the driver initialization entry point. It initializes the
libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
Arguments:
ImageHandle - The image handle.
SystemTable - The system table.
Returns:
Status code
--*/
;
EFI_STATUS
ProduceFVBProtocolOnBuffer (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN EFI_HANDLE ParentHandle,
OUT EFI_HANDLE *FvProtocolHandle OPTIONAL
)
/*++
Routine Description:
This routine produces a firmware volume block protocol on a given
buffer.
Arguments:
BaseAddress - base address of the firmware volume image
Length - length of the firmware volume image
ParentHandle - handle of parent firmware volume, if this
image came from an FV image file in another
firmware volume (ala capsules)
FvProtocolHandle - Firmware volume block protocol produced.
Returns:
EFI_VOLUME_CORRUPTED - Volume corrupted.
EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
EFI_SUCCESS - Successfully produced a FVB protocol on given buffer.
--*/
;
#endif

View File

@@ -0,0 +1,598 @@
/*++
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:
FwVolBlock.c
Abstract:
Firmware Volume Block protocol.. Consumes FV hobs and creates
appropriate block protocols.
Also consumes NT_NON_MM_FV envinronment variable and produces appropriate
block protocols fro them also... (this is TBD)
--*/
#include <DxeMain.h>
EFI_FW_VOL_BLOCK_DEVICE mFwVolBlock = {
FVB_DEVICE_SIGNATURE,
NULL,
{
{
{
HARDWARE_DEVICE_PATH,
HW_MEMMAP_DP,
{ (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) }
},
EfiMemoryMappedIO,
(EFI_PHYSICAL_ADDRESS)0,
(EFI_PHYSICAL_ADDRESS)0,
},
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
{ END_DEVICE_PATH_LENGTH, 0 }
},
},
{
FwVolBlockGetAttributes,
(EFI_FVB_SET_ATTRIBUTES)FwVolBlockSetAttributes,
FwVolBlockGetPhysicalAddress,
FwVolBlockGetBlockSize,
FwVolBlockReadBlock,
(EFI_FVB_WRITE)FwVolBlockWriteBlock,
(EFI_FVB_ERASE_BLOCKS)FwVolBlockEraseBlock,
NULL
},
0,
NULL,
0,
0
};
EFI_STATUS
EFIAPI
FwVolBlockGetAttributes (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
OUT EFI_FVB_ATTRIBUTES *Attributes
)
/*++
Routine Description:
Retrieves Volume attributes. No polarity translations are done.
Arguments:
This - Calling context
Attributes - output buffer which contains attributes
Returns:
EFI_SUCCESS - The firmware volume attributes were returned.
--*/
{
EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
FvbDevice = FVB_DEVICE_FROM_THIS (This);
//
// Since we are read only, it's safe to get attributes data from our in-memory copy.
//
*Attributes = FvbDevice->FvbAttributes;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
FwVolBlockSetAttributes (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
IN EFI_FVB_ATTRIBUTES *Attributes
)
/*++
Routine Description:
Modifies the current settings of the firmware volume according to the input parameter.
Arguments:
This - Calling context
Attributes - input buffer which contains attributes
Returns:
EFI_SUCCESS - The firmware volume attributes were returned.
EFI_INVALID_PARAMETER - The attributes requested are in conflict with the capabilities as
declared in the firmware volume header.
EFI_UNSUPPORTED - Not supported.
--*/
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
FwVolBlockEraseBlock (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
...
)
/*++
Routine Description:
The EraseBlock() function erases one or more blocks as denoted by the
variable argument list. The entire parameter list of blocks must be verified
prior to 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 EraseBlock() function must return
EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
Arguments:
This - Calling context
... - Starting LBA followed by Number of Lba to erase. a -1 to terminate
the list.
Returns:
EFI_SUCCESS - The erase request was successfully completed.
EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
EFI_DEVICE_ERROR - The block device is not functioning correctly and could not be
written. The firmware device may have been partially erased.
EFI_INVALID_PARAMETER - One or more of the LBAs listed in the variable argument list do
EFI_UNSUPPORTED - Not supported.
--*/
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
FwVolBlockReadBlock (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer
)
/*++
Routine Description:
Read the specified number of bytes from the block to the input buffer.
Arguments:
This - Indicates the calling context.
Lba - The starting logical block index to read.
Offset - Offset into the block at which to begin reading.
NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
total size of the buffer. At exit, *NumBytes contains the
total number of bytes actually read.
Buffer - Pinter to a caller-allocated buffer that contains the destine
for the read.
Returns:
EFI_SUCCESS - The firmware volume was read successfully.
EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary.
EFI_ACCESS_DENIED - Access denied.
EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read.
--*/
{
EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
UINT8 *LbaOffset;
UINTN LbaStart;
UINTN NumOfBytesRead;
UINTN LbaIndex;
FvbDevice = FVB_DEVICE_FROM_THIS (This);
//
// Check if This FW can be read
//
if ((FvbDevice->FvbAttributes & EFI_FVB_READ_STATUS) == 0) {
return EFI_ACCESS_DENIED;
}
LbaIndex = (UINTN)Lba;
if (LbaIndex >= FvbDevice->NumBlocks) {
//
// Invalid Lba, read nothing.
//
*NumBytes = 0;
return EFI_BAD_BUFFER_SIZE;
}
if (Offset > FvbDevice->LbaCache[LbaIndex].Length) {
//
// all exceed boundry, read nothing.
//
*NumBytes = 0;
return EFI_BAD_BUFFER_SIZE;
}
NumOfBytesRead = *NumBytes;
if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) {
//
// partial exceed boundry, read data from current postion to end.
//
NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset;
}
LbaStart = FvbDevice->LbaCache[LbaIndex].Base;
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset;
//
// Perform read operation
//
CopyMem (Buffer, LbaOffset, NumOfBytesRead);
if (NumOfBytesRead == *NumBytes) {
return EFI_SUCCESS;
}
*NumBytes = NumOfBytesRead;
return EFI_BAD_BUFFER_SIZE;
}
EFI_STATUS
EFIAPI
FwVolBlockWriteBlock (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer
)
/*++
Routine Description:
Writes the specified number of bytes from the input buffer to the block.
Arguments:
This - Indicates the calling context.
Lba - The starting logical block index to write to.
Offset - Offset into the block at which to begin writing.
NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
total size of the buffer. At exit, *NumBytes contains the
total number of bytes actually written.
Buffer - Pinter to a caller-allocated buffer that contains the source
for the write.
Returns:
EFI_SUCCESS - The firmware volume was written successfully.
EFI_BAD_BUFFER_SIZE - The write was attempted across an LBA boundary. On output,
NumBytes contains the total number of bytes actually written.
EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
EFI_DEVICE_ERROR - The block device is malfunctioning and could not be written.
EFI_UNSUPPORTED - Not supported.
--*/
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
FwVolBlockGetPhysicalAddress (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
OUT EFI_PHYSICAL_ADDRESS *Address
)
/*++
Routine Description:
Get Fvb's base address.
Arguments:
This - Indicates the calling context.
Address - Fvb device base address.
Returns:
EFI_SUCCESS - Successfully got Fvb's base address.
EFI_UNSUPPORTED - Not supported.
--*/
{
EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
FvbDevice = FVB_DEVICE_FROM_THIS (This);
if (FvbDevice->FvbAttributes & EFI_FVB_MEMORY_MAPPED) {
*Address = FvbDevice->BaseAddress;
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
FwVolBlockGetBlockSize (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
IN EFI_LBA Lba,
OUT UINTN *BlockSize,
OUT UINTN *NumberOfBlocks
)
/*++
Routine Description:
Retrieves the size in bytes of a specific block within a firmware volume.
Arguments:
This - Indicates the calling context.
Lba - Indicates the block for which to return the size.
BlockSize - Pointer to a caller-allocated UINTN in which the size of the
block is returned.
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.
Returns:
EFI_SUCCESS - The firmware volume base address is returned.
EFI_INVALID_PARAMETER - The requested LBA is out of range.
--*/
{
UINTN TotalBlocks;
EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
FvbDevice = FVB_DEVICE_FROM_THIS (This);
//
// Do parameter checking
//
if (Lba >= FvbDevice->NumBlocks) {
return EFI_INVALID_PARAMETER;
}
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
PtrBlockMapEntry = FwVolHeader->FvBlockMap;
//
// Search the block map for the given block
//
TotalBlocks = 0;
while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->BlockLength !=0 )) {
TotalBlocks += PtrBlockMapEntry->NumBlocks;
if (Lba < TotalBlocks) {
//
// We find the range
//
break;
}
PtrBlockMapEntry++;
}
*BlockSize = PtrBlockMapEntry->BlockLength;
*NumberOfBlocks = TotalBlocks - (UINTN)Lba;
return EFI_SUCCESS;
}
EFI_STATUS
ProduceFVBProtocolOnBuffer (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN EFI_HANDLE ParentHandle,
OUT EFI_HANDLE *FvProtocol OPTIONAL
)
/*++
Routine Description:
This routine produces a firmware volume block protocol on a given
buffer.
Arguments:
BaseAddress - base address of the firmware volume image
Length - length of the firmware volume image
ParentHandle - handle of parent firmware volume, if this
image came from an FV image file in another
firmware volume (ala capsules)
FvProtocol - Firmware volume block protocol produced.
Returns:
EFI_VOLUME_CORRUPTED - Volume corrupted.
EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
EFI_SUCCESS - Successfully produced a FVB protocol on given buffer.
--*/
{
EFI_STATUS Status;
EFI_FW_VOL_BLOCK_DEVICE *FvbDev;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
UINTN BlockIndex;
UINTN BlockIndex2;
UINTN LinearOffset;
EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
//
// Validate FV Header, if not as expected, return
//
if (FwVolHeader->Signature != EFI_FVH_SIGNATURE) {
return EFI_VOLUME_CORRUPTED;
}
//
// Allocate EFI_FW_VOL_BLOCK_DEVICE
//
FvbDev = CoreAllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock);
if (FvbDev == NULL) {
return EFI_OUT_OF_RESOURCES;
}
FvbDev->BaseAddress = BaseAddress;
FvbDev->FvbAttributes = FwVolHeader->Attributes;
FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle;
//
// Init the block caching fields of the device
// First, count the number of blocks
//
FvbDev->NumBlocks = 0;
for (PtrBlockMapEntry = FwVolHeader->FvBlockMap;
PtrBlockMapEntry->NumBlocks != 0;
PtrBlockMapEntry++) {
FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks;
}
//
// Second, allocate the cache
//
FvbDev->LbaCache = CoreAllocateBootServicesPool (FvbDev->NumBlocks * sizeof (LBA_CACHE));
if (FvbDev->LbaCache == NULL) {
CoreFreePool (FvbDev);
return EFI_OUT_OF_RESOURCES;
}
//
// Last, fill in the cache with the linear address of the blocks
//
BlockIndex = 0;
LinearOffset = 0;
for (PtrBlockMapEntry = FwVolHeader->FvBlockMap;
PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
FvbDev->LbaCache[BlockIndex].Base = LinearOffset;
FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->BlockLength;
LinearOffset += PtrBlockMapEntry->BlockLength;
BlockIndex++;
}
}
//
// Set up the devicepath
//
FvbDev->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;
FvbDev->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1;
//
//
// Attach FvVolBlock Protocol to new handle
//
Status = CoreInstallMultipleProtocolInterfaces (
&FvbDev->Handle,
&gEfiFirmwareVolumeBlockProtocolGuid, &FvbDev->FwVolBlockInstance,
&gEfiDevicePathProtocolGuid, &FvbDev->DevicePath,
&gEfiFirmwareVolumeDispatchProtocolGuid, NULL,
NULL
);
//
// If they want the handle back, set it.
//
if (FvProtocol != NULL) {
*FvProtocol = FvbDev->Handle;
}
return Status;
}
EFI_STATUS
EFIAPI
FwVolBlockDriverInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
This routine is the driver initialization entry point. It initializes the
libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
Arguments:
ImageHandle - The image handle.
SystemTable - The system table.
Returns:
EFI_SUCCESS - Successfully initialized firmware volume block driver.
--*/
{
EFI_PEI_HOB_POINTERS FvHob;
//
// Core Needs Firmware Volumes to function
//
FvHob.Raw = GetHobList ();
while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) {
//
// Produce an FVB protocol for it
//
ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, NULL);
FvHob.Raw = GET_NEXT_HOB (FvHob);
}
return EFI_SUCCESS;
}
EFI_STATUS
CoreProcessFirmwareVolume (
IN VOID *FvHeader,
IN UINTN Size,
OUT EFI_HANDLE *FVProtocolHandle
)
/*++
Routine Description:
This DXE service routine is used to process a firmware volume. In
particular, it can be called by BDS to process a single firmware
volume found in a capsule.
Arguments:
FvHeader - pointer to a firmware volume header
Size - the size of the buffer pointed to by FvHeader
FVProtocolHandle - the handle on which a firmware volume protocol
was produced for the firmware volume passed in.
Returns:
EFI_OUT_OF_RESOURCES - if an FVB could not be produced due to lack of
system resources
EFI_VOLUME_CORRUPTED - if the volume was corrupted
EFI_SUCCESS - a firmware volume protocol was produced for the
firmware volume
--*/
{
VOID *Ptr;
EFI_STATUS Status;
*FVProtocolHandle = NULL;
Status = ProduceFVBProtocolOnBuffer (
(EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
(UINT64)Size,
NULL,
FVProtocolHandle
);
//
// Since in our implementation we use register-protocol-notify to put a
// FV protocol on the FVB protocol handle, we can't directly verify that
// the FV protocol was produced. Therefore here we will check the handle
// and make sure an FV protocol is on it. This indicates that all went
// well. Otherwise we have to assume that the volume was corrupted
// somehow.
//
if (!EFI_ERROR(Status)) {
Ptr = NULL;
Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Ptr);
if (EFI_ERROR(Status) || (Ptr == NULL)) {
return EFI_VOLUME_CORRUPTED;
}
return EFI_SUCCESS;
}
return Status;
}

View File

@@ -0,0 +1,466 @@
/*++
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:
FwVolDriver.h
Abstract:
Firmware File System protocol. Layers on top of Firmware
Block protocol to produce a file abstraction of FV based files.
--*/
#ifndef __FWVOL_H
#define __FWVOL_H
//
// Used to track all non-deleted files
//
typedef struct {
LIST_ENTRY Link;
EFI_FFS_FILE_HEADER *FfsHeader;
UINTN StreamHandle;
EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
} FFS_FILE_LIST_ENTRY;
typedef struct {
UINTN Signature;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
EFI_HANDLE Handle;
EFI_FIRMWARE_VOLUME_PROTOCOL Fv;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
UINT8 *CachedFv;
UINT8 *EndOfCachedFv;
FFS_FILE_LIST_ENTRY *LastKey;
LIST_ENTRY FfsFileListHeader;
UINT8 ErasePolarity;
} FV_DEVICE;
#define FV_DEVICE_FROM_THIS(a) CR(a, FV_DEVICE, Fv, FV_DEVICE_SIGNATURE)
EFI_STATUS
EFIAPI
FvGetVolumeAttributes (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
OUT EFI_FV_ATTRIBUTES *Attributes
)
/*++
Routine Description:
Retrieves attributes, insures positive polarity of attribute bits, returns
resulting attributes in output parameter
Arguments:
This - Calling context
Attributes - output buffer which contains attributes
Returns:
EFI_SUCCESS - Successfully got volume attributes
--*/
;
EFI_STATUS
EFIAPI
FvSetVolumeAttributes (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN OUT EFI_FV_ATTRIBUTES *Attributes
)
/*++
Routine Description:
Sets current attributes for volume
Arguments:
This - Calling context
Attributes - At input, contains attributes to be set. At output contains
new value of FV
Returns:
EFI_UNSUPPORTED - Could not be set.
--*/
;
EFI_STATUS
EFIAPI
FvGetNextFile (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN OUT VOID *Key,
IN OUT EFI_FV_FILETYPE *FileType,
OUT EFI_GUID *NameGuid,
OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
OUT UINTN *Size
)
/*++
Routine Description:
Given the input key, search for the next matching file in the volume.
Arguments:
This - Indicates the calling context.
FileType - FileType is a pointer to a caller allocated
EFI_FV_FILETYPE. The GetNextFile() API can filter it's
search for files based on the value of *FileType input.
A *FileType input of 0 causes GetNextFile() to search for
files of all types. If a file is found, the file's type
is returned in *FileType. *FileType is not modified if
no file is found.
Key - Key is a pointer to a caller allocated buffer that
contains implementation specific data that is used to
track where to begin the search for the next file.
The size of the buffer must be at least This->KeySize
bytes long. To reinitialize the search and begin from
the beginning of the firmware volume, the entire buffer
must be cleared to zero. Other than clearing the buffer
to initiate a new search, the caller must not modify the
data in the buffer between calls to GetNextFile().
NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
If a file is found, the file's name is returned in
*NameGuid. *NameGuid is not modified if no file is
found.
Attributes - Attributes is a pointer to a caller allocated
EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
attributes are returned in *Attributes. *Attributes is
not modified if no file is found.
Size - Size is a pointer to a caller allocated UINTN.
If a file is found, the file's size is returned in *Size.
*Size is not modified if no file is found.
Returns:
EFI_SUCCESS - Successfully find the file.
EFI_DEVICE_ERROR - Device error.
EFI_ACCESS_DENIED - Fv could not read.
EFI_NOT_FOUND - No matching file found.
EFI_INVALID_PARAMETER - Invalid parameter
--*/
;
EFI_STATUS
EFIAPI
FvReadFile (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN EFI_GUID *NameGuid,
IN OUT VOID **Buffer,
IN OUT UINTN *BufferSize,
OUT EFI_FV_FILETYPE *FoundType,
OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
OUT UINT32 *AuthenticationStatus
)
/*++
Routine Description:
Locates a file in the firmware volume and
copies it to the supplied buffer.
Arguments:
This - Indicates the calling context.
NameGuid - Pointer to an EFI_GUID, which is the filename.
Buffer - Buffer is a pointer to pointer to a buffer in
which the file or section contents or are returned.
BufferSize - BufferSize is a pointer to caller allocated
UINTN. On input *BufferSize indicates the size
in bytes of the memory region pointed to by
Buffer. On output, *BufferSize contains the number
of bytes required to read the file.
FoundType - FoundType is a pointer to a caller allocated
EFI_FV_FILETYPE that on successful return from Read()
contains the type of file read. This output reflects
the file type irrespective of the value of the
SectionType input.
FileAttributes - FileAttributes is a pointer to a caller allocated
EFI_FV_FILE_ATTRIBUTES. On successful return from
Read(), *FileAttributes contains the attributes of
the file read.
AuthenticationStatus - AuthenticationStatus is a pointer to a caller
allocated UINTN in which the authentication status
is returned.
Returns:
EFI_SUCCESS - Successfully read to memory buffer.
EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
EFI_NOT_FOUND - Not found.
EFI_DEVICE_ERROR - Device error.
EFI_ACCESS_DENIED - Could not read.
EFI_INVALID_PARAMETER - Invalid parameter.
EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
--*/
;
EFI_STATUS
EFIAPI
FvReadFileSection (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN EFI_GUID *NameGuid,
IN EFI_SECTION_TYPE SectionType,
IN UINTN SectionInstance,
IN OUT VOID **Buffer,
IN OUT UINTN *BufferSize,
OUT UINT32 *AuthenticationStatus
)
/*++
Routine Description:
Locates a section in a given FFS File and
copies it to the supplied buffer (not including section header).
Arguments:
This - Indicates the calling context.
NameGuid - Pointer to an EFI_GUID, which is the filename.
SectionType - Indicates the section type to return.
SectionInstance - Indicates which instance of sections with a type of
SectionType to return.
Buffer - Buffer is a pointer to pointer to a buffer in which
the file or section contents or are returned.
BufferSize - BufferSize is a pointer to caller allocated UINTN.
AuthenticationStatus -AuthenticationStatus is a pointer to a caller
allocated UINT32 in which the authentication status
is returned.
Returns:
EFI_SUCCESS - Successfully read the file section into buffer.
EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
EFI_NOT_FOUND - Section not found.
EFI_DEVICE_ERROR - Device error.
EFI_ACCESS_DENIED - Could not read.
EFI_INVALID_PARAMETER - Invalid parameter.
--*/
;
EFI_STATUS
EFIAPI
FvWriteFile (
IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
IN UINT32 NumberOfFiles,
IN EFI_FV_WRITE_POLICY WritePolicy,
IN EFI_FV_WRITE_FILE_DATA *FileData
)
/*++
Routine Description:
Writes one or more files to the firmware volume.
Arguments:
This - Indicates the calling context.
WritePolicy - WritePolicy indicates the level of reliability for
the write in the event of a power failure or other
system failure during the write operation.
FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA.
Each element of FileData[] represents a file to be written.
Returns:
EFI_SUCCESS - Files successfully written to firmware volume
EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
EFI_DEVICE_ERROR - Device error.
EFI_WRITE_PROTECTED - Write protected.
EFI_NOT_FOUND - Not found.
EFI_INVALID_PARAMETER - Invalid parameter.
EFI_UNSUPPORTED - This function not supported.
--*/
;
//
//Internal functions
//
typedef enum {
EfiCheckSumUint8 = 0,
EfiCheckSumUint16 = 1,
EfiCheckSumUint32 = 2,
EfiCheckSumUint64 = 3,
EfiCheckSumMaximum = 4
} EFI_CHECKSUM_TYPE;
BOOLEAN
IsBufferErased (
IN UINT8 ErasePolarity,
IN VOID *Buffer,
IN UINTN BufferSize
)
/*++
Routine Description:
Check if a block of buffer is erased
Arguments:
ErasePolarity - Erase polarity attribute of the firmware volume
Buffer - The buffer to be checked
BufferSize - Size of the buffer in bytes
Returns:
TRUE - The block of buffer is erased
FALSE - The block of buffer is not erased
--*/
;
EFI_FFS_FILE_STATE
GetFileState (
IN UINT8 ErasePolarity,
IN EFI_FFS_FILE_HEADER *FfsHeader
)
/*++
Routine Description:
Get the FFS file state by checking the highest bit set in the header's state field
Arguments:
ErasePolarity - Erase polarity attribute of the firmware volume
FfsHeader - Points to the FFS file header
Returns:
FFS File state
--*/
;
VOID
SetFileState (
IN UINT8 State,
IN EFI_FFS_FILE_HEADER *FfsHeader
)
/*++
Routine Description:
Set the FFS file state.
Arguments:
State - The state to be set.
FfsHeader - Points to the FFS file header
Returns:
None.
--*/
;
BOOLEAN
VerifyFvHeaderChecksum (
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
)
/*++
Routine Description:
Verify checksum of the firmware volume header
Arguments:
FvHeader - Points to the firmware volume header to be checked
Returns:
TRUE - Checksum verification passed
FALSE - Checksum verification failed
--*/
;
BOOLEAN
IsValidFfsHeader (
IN UINT8 ErasePolarity,
IN EFI_FFS_FILE_HEADER *FfsHeader,
OUT EFI_FFS_FILE_STATE *FileState
)
/*++
Routine Description:
Check if it's a valid FFS file header
Arguments:
ErasePolarity - Erase polarity attribute of the firmware volume
FfsHeader - Points to the FFS file header to be checked
FileState - FFS file state to be returned
Returns:
TRUE - Valid FFS file header
FALSE - Invalid FFS file header
--*/
;
BOOLEAN
IsValidFfsFile (
IN UINT8 ErasePolarity,
IN EFI_FFS_FILE_HEADER *FfsHeader
)
/*++
Routine Description:
Check if it's a valid FFS file.
Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
Arguments:
ErasePolarity - Erase polarity attribute of the firmware volume
FfsHeader - Points to the FFS file to be checked
Returns:
TRUE - Valid FFS file
FALSE - Invalid FFS file
--*/
;
EFI_STATUS
GetFwVolHeader (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
)
/*++
Routine Description:
given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
copy the volume header into it.
Arguments:
Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume
header
FwVolHeader - Pointer to pointer to allocated buffer in which the volume
header is returned.
Returns:
Status code.
--*/
;
EFI_STATUS
FvCheck (
IN OUT FV_DEVICE *FvDevice
)
/*++
Routine Description:
Check if a FV is consistent and allocate cache
Arguments:
FvDevice - pointer to the FvDevice to be checked.
Returns:
EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
EFI_SUCCESS - FV is consistent and cache is allocated.
EFI_VOLUME_CORRUPTED - File system is corrupted.
--*/
;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,848 @@
/*++
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:
DriverSupport.c
Abstract:
EFI Driver Support Protocol
Revision History
--*/
#include <DxeMain.h>
STATIC
EFI_STATUS
GetHandleFromDriverBinding (
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed,
OUT EFI_HANDLE *Handle
);
//
// Driver Support Function Prototypes
//
STATIC
EFI_STATUS
CoreConnectSingleController (
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE *DriverImageHandle OPTIONAL,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
//
// Driver Support Functions
//
EFI_STATUS
EFIAPI
CoreConnectController (
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE *DriverImageHandle OPTIONAL,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
IN BOOLEAN Recursive
)
/*++
Routine Description:
Connects one or more drivers to a controller.
Arguments:
ControllerHandle - Handle of the controller to be connected.
DriverImageHandle - DriverImageHandle A pointer to an ordered list of driver image handles.
RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child of the
controller specified by ControllerHandle.
Recursive - Whether the function would be called recursively or not.
Returns:
Status code.
--*/
{
EFI_STATUS Status;
EFI_STATUS ReturnStatus;
IHANDLE *Handle;
PROTOCOL_INTERFACE *Prot;
LIST_ENTRY *Link;
LIST_ENTRY *ProtLink;
OPEN_PROTOCOL_DATA *OpenData;
EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath;
//
// Make sure ControllerHandle is valid
//
Status = CoreValidateHandle (ControllerHandle);
if (EFI_ERROR (Status)) {
return Status;
}
Handle = ControllerHandle;
//
// Connect all drivers to ControllerHandle
//
AlignedRemainingDevicePath = NULL;
if (RemainingDevicePath != NULL) {
AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);
}
ReturnStatus = CoreConnectSingleController (
ControllerHandle,
DriverImageHandle,
AlignedRemainingDevicePath
);
if (AlignedRemainingDevicePath != NULL) {
CoreFreePool (AlignedRemainingDevicePath);
}
//
// If not recursive, then just return after connecting drivers to ControllerHandle
//
if (!Recursive) {
return ReturnStatus;
}
//
// If recursive, then connect all drivers to all of ControllerHandle's children
//
CoreAcquireProtocolLock ();
for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
for (ProtLink = Prot->OpenList.ForwardLink;
ProtLink != &Prot->OpenList;
ProtLink = ProtLink->ForwardLink) {
OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
CoreReleaseProtocolLock ();
Status = CoreConnectController (
OpenData->ControllerHandle,
NULL,
NULL,
TRUE
);
CoreAcquireProtocolLock ();
}
}
}
CoreReleaseProtocolLock ();
return ReturnStatus;
}
VOID
AddSortedDriverBindingProtocol (
IN EFI_HANDLE DriverBindingHandle,
IN OUT UINTN *NumberOfSortedDriverBindingProtocols,
IN OUT EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols,
IN UINTN DriverBindingHandleCount,
IN OUT EFI_HANDLE *DriverBindingHandleBuffer
)
/*++
Routine Description:
Add Driver Binding Protocols from Context Driver Image Handles to sorted
Driver Binding Protocol list.
Arguments:
DriverBindingHandle - Handle of the driver binding protocol.
NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols
SortedDriverBindingProtocols - The sorted protocol list.
DriverBindingHandleCount - Driver Binding Handle Count.
DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.
Returns:
None.
--*/
{
EFI_STATUS Status;
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
UINTN Index;
//
// Make sure the DriverBindingHandle is valid
//
Status = CoreValidateHandle (DriverBindingHandle);
if (EFI_ERROR (Status)) {
return;
}
//
// Retrieve the Driver Binding Protocol from DriverBindingHandle
//
Status = CoreHandleProtocol(
DriverBindingHandle,
&gEfiDriverBindingProtocolGuid,
(VOID **)&DriverBinding
);
//
// If DriverBindingHandle does not support the Driver Binding Protocol then return
//
if (EFI_ERROR (Status) || DriverBinding == NULL) {
return;
}
//
// See if DriverBinding is already in the sorted list
//
for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols; Index++) {
if (DriverBinding == SortedDriverBindingProtocols[Index]) {
return;
}
}
//
// Add DriverBinding to the end of the list
//
SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
*NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
//
// Mark the cooresponding handle in DriverBindingHandleBuffer as used
//
for (Index = 0; Index < DriverBindingHandleCount; Index++) {
if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
DriverBindingHandleBuffer[Index] = NULL;
}
}
}
STATIC
EFI_STATUS
CoreConnectSingleController (
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
/*++
Routine Description:
Connects a controller to a driver.
Arguments:
ControllerHandle - Handle of the controller to be connected.
ContextDriverImageHandles - DriverImageHandle A pointer to an ordered list of driver image handles.
RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child
of the controller specified by ControllerHandle.
Returns:
EFI_SUCCESS - One or more drivers were connected to ControllerHandle.
EFI_OUT_OF_RESOURCES - No enough system resources to complete the request.
EFI_NOT_FOUND - No drivers were connected to ControllerHandle.
--*/
{
EFI_STATUS Status;
UINTN Index;
EFI_HANDLE DriverImageHandle;
UINTN PlatformDriverOverrideHandleCount;
EFI_HANDLE *PlatformDriverOverrideHandleBuffer;
EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *PlatformDriverOverride;
EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
UINTN DriverBindingHandleCount;
EFI_HANDLE *DriverBindingHandleBuffer;
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
UINTN NumberOfSortedDriverBindingProtocols;
EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols;
UINT32 HighestVersion;
UINTN HighestIndex;
UINTN SortIndex;
BOOLEAN OneStarted;
BOOLEAN DriverFound;
EFI_HANDLE DriverBindingHandle;
//
// DriverBindingHandle is used for performance measurement, initialize it here just in case.
//
DriverBindingHandle = NULL;
//
// Initialize local variables
//
DriverBindingHandleCount = 0;
DriverBindingHandleBuffer = NULL;
PlatformDriverOverrideHandleCount = 0;
PlatformDriverOverrideHandleBuffer = NULL;
NumberOfSortedDriverBindingProtocols = 0;
SortedDriverBindingProtocols = NULL;
//
// Get list of all Driver Binding Protocol Instances
//
Status = CoreLocateHandleBuffer (
ByProtocol,
&gEfiDriverBindingProtocolGuid,
NULL,
&DriverBindingHandleCount,
&DriverBindingHandleBuffer
);
if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
return EFI_NOT_FOUND;
}
//
// Allocate a duplicate array for the sorted Driver Binding Protocol Instances
//
SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);
if (SortedDriverBindingProtocols == NULL) {
CoreFreePool (DriverBindingHandleBuffer);
return EFI_OUT_OF_RESOURCES;
}
//
// Add Driver Binding Protocols from Context Driver Image Handles first
//
if (ContextDriverImageHandles != NULL) {
for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
AddSortedDriverBindingProtocol (
ContextDriverImageHandles[Index],
&NumberOfSortedDriverBindingProtocols,
SortedDriverBindingProtocols,
DriverBindingHandleCount,
DriverBindingHandleBuffer
);
}
}
//
// Add the Platform Driver Override Protocol drivers for ControllerHandle next
//
Status = CoreLocateProtocol (
&gEfiPlatformDriverOverrideProtocolGuid,
NULL,
(VOID **)&PlatformDriverOverride
);
if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
DriverImageHandle = NULL;
do {
Status = PlatformDriverOverride->GetDriver (
PlatformDriverOverride,
ControllerHandle,
&DriverImageHandle
);
if (!EFI_ERROR (Status)) {
AddSortedDriverBindingProtocol (
DriverImageHandle,
&NumberOfSortedDriverBindingProtocols,
SortedDriverBindingProtocols,
DriverBindingHandleCount,
DriverBindingHandleBuffer
);
}
} while (!EFI_ERROR (Status));
}
//
// Get the Bus Specific Driver Override Protocol instance on the Controller Handle
//
Status = CoreHandleProtocol(
ControllerHandle,
&gEfiBusSpecificDriverOverrideProtocolGuid,
(VOID **)&BusSpecificDriverOverride
);
if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
DriverImageHandle = NULL;
do {
Status = BusSpecificDriverOverride->GetDriver (
BusSpecificDriverOverride,
&DriverImageHandle
);
if (!EFI_ERROR (Status)) {
AddSortedDriverBindingProtocol (
DriverImageHandle,
&NumberOfSortedDriverBindingProtocols,
SortedDriverBindingProtocols,
DriverBindingHandleCount,
DriverBindingHandleBuffer
);
}
} while (!EFI_ERROR (Status));
}
//
// Then add all the remaining Driver Binding Protocols
//
SortIndex = NumberOfSortedDriverBindingProtocols;
for (Index = 0; Index < DriverBindingHandleCount; Index++) {
AddSortedDriverBindingProtocol (
DriverBindingHandleBuffer[Index],
&NumberOfSortedDriverBindingProtocols,
SortedDriverBindingProtocols,
DriverBindingHandleCount,
DriverBindingHandleBuffer
);
}
//
// Free the Driver Binding Handle Buffer
//
CoreFreePool (DriverBindingHandleBuffer);
//
// Sort the remaining DriverBinding Protocol based on their Version field from
// highest to lowest.
//
for ( ; SortIndex < DriverBindingHandleCount; SortIndex++) {
HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
HighestIndex = SortIndex;
for (Index = SortIndex + 1; Index < DriverBindingHandleCount; Index++) {
if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
HighestVersion = SortedDriverBindingProtocols[Index]->Version;
HighestIndex = Index;
}
}
if (SortIndex != HighestIndex) {
DriverBinding = SortedDriverBindingProtocols[SortIndex];
SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
}
}
//
// Loop until no more drivers can be started on ControllerHandle
//
OneStarted = FALSE;
do {
//
// Loop through the sorted Driver Binding Protocol Instances in order, and see if
// any of the Driver Binding Protocols support the controller specified by
// ControllerHandle.
//
DriverBinding = NULL;
DriverFound = FALSE;
for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
if (SortedDriverBindingProtocols[Index] != NULL) {
DriverBinding = SortedDriverBindingProtocols[Index];
Status = DriverBinding->Supported(
DriverBinding,
ControllerHandle,
RemainingDevicePath
);
if (!EFI_ERROR (Status)) {
SortedDriverBindingProtocols[Index] = NULL;
DriverFound = TRUE;
//
// A driver was found that supports ControllerHandle, so attempt to start the driver
// on ControllerHandle.
//
PERF_CODE_BEGIN ();
GetHandleFromDriverBinding (DriverBinding, &DriverBindingHandle);
PERF_CODE_END ();
PERF_START (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
Status = DriverBinding->Start (
DriverBinding,
ControllerHandle,
RemainingDevicePath
);
PERF_END (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
if (!EFI_ERROR (Status)) {
//
// The driver was successfully started on ControllerHandle, so set a flag
//
OneStarted = TRUE;
}
}
}
}
} while (DriverFound);
//
// Free any buffers that were allocated with AllocatePool()
//
CoreFreePool (SortedDriverBindingProtocols);
//
// If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
//
if (OneStarted) {
return EFI_SUCCESS;
}
//
// If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
//
if (RemainingDevicePath != NULL) {
if (IsDevicePathEnd (RemainingDevicePath)) {
return EFI_SUCCESS;
}
}
//
// Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
//
return EFI_NOT_FOUND;
}
EFI_STATUS
EFIAPI
CoreDisconnectController (
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE DriverImageHandle OPTIONAL,
IN EFI_HANDLE ChildHandle OPTIONAL
)
/*++
Routine Description:
Disonnects a controller from a driver
Arguments:
ControllerHandle - ControllerHandle The handle of the controller from which driver(s)
are to be disconnected.
DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
ChildHandle - ChildHandle The handle of the child to destroy.
Returns:
EFI_SUCCESS - One or more drivers were disconnected from the controller.
EFI_SUCCESS - On entry, no drivers are managing ControllerHandle.
EFI_SUCCESS - DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
EFI_OUT_OF_RESOURCES - There are not enough resources available to disconnect any drivers from ControllerHandle.
EFI_DEVICE_ERROR - The controller could not be disconnected because of a device error.
--*/
{
EFI_STATUS Status;
IHANDLE *Handle;
EFI_HANDLE *DriverImageHandleBuffer;
EFI_HANDLE *ChildBuffer;
UINTN Index;
UINTN HandleIndex;
UINTN DriverImageHandleCount;
UINTN ChildrenToStop;
UINTN ChildBufferCount;
UINTN StopCount;
BOOLEAN Duplicate;
BOOLEAN ChildHandleValid;
BOOLEAN DriverImageHandleValid;
LIST_ENTRY *Link;
LIST_ENTRY *ProtLink;
OPEN_PROTOCOL_DATA *OpenData;
PROTOCOL_INTERFACE *Prot;
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
//
// Make sure ControllerHandle is valid
//
Status = CoreValidateHandle (ControllerHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Make sure ChildHandle is valid if it is not NULL
//
if (ChildHandle != NULL) {
Status = CoreValidateHandle (ChildHandle);
if (EFI_ERROR (Status)) {
return Status;
}
}
Handle = ControllerHandle;
//
// Get list of drivers that are currently managing ControllerHandle
//
DriverImageHandleBuffer = NULL;
DriverImageHandleCount = 1;
if (DriverImageHandle == NULL) {
//
// Look at each protocol interface for a match
//
DriverImageHandleCount = 0;
CoreAcquireProtocolLock ();
for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
for (ProtLink = Prot->OpenList.ForwardLink;
ProtLink != &Prot->OpenList;
ProtLink = ProtLink->ForwardLink) {
OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
DriverImageHandleCount++;
}
}
}
CoreReleaseProtocolLock ();
//
// If there are no drivers managing this controller, then return EFI_SUCCESS
//
if (DriverImageHandleCount == 0) {
Status = EFI_SUCCESS;
goto Done;
}
DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
if (DriverImageHandleBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
DriverImageHandleCount = 0;
CoreAcquireProtocolLock ();
for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
for (ProtLink = Prot->OpenList.ForwardLink;
ProtLink != &Prot->OpenList;
ProtLink = ProtLink->ForwardLink) {
OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
Duplicate = FALSE;
for (Index = 0; Index< DriverImageHandleCount; Index++) {
if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
Duplicate = TRUE;
break;
}
}
if (!Duplicate) {
DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
DriverImageHandleCount++;
}
}
}
}
CoreReleaseProtocolLock ();
}
StopCount = 0;
for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
if (DriverImageHandleBuffer != NULL) {
DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
}
//
// Get the Driver Binding Protocol of the driver that is managing this controller
//
Status = CoreHandleProtocol (
DriverImageHandle,
&gEfiDriverBindingProtocolGuid,
(VOID **)&DriverBinding
);
if (EFI_ERROR (Status)) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
//
// Look at each protocol interface for a match
//
DriverImageHandleValid = FALSE;
ChildBufferCount = 0;
CoreAcquireProtocolLock ();
for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
for (ProtLink = Prot->OpenList.ForwardLink;
ProtLink != &Prot->OpenList;
ProtLink = ProtLink->ForwardLink) {
OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
if (OpenData->AgentHandle == DriverImageHandle) {
if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
ChildBufferCount++;
}
if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
DriverImageHandleValid = TRUE;
}
}
}
}
CoreReleaseProtocolLock ();
if (DriverImageHandleValid) {
ChildHandleValid = FALSE;
ChildBuffer = NULL;
if (ChildBufferCount != 0) {
ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount);
if (ChildBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
ChildBufferCount = 0;
CoreAcquireProtocolLock ();
for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
for (ProtLink = Prot->OpenList.ForwardLink;
ProtLink != &Prot->OpenList;
ProtLink = ProtLink->ForwardLink) {
OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
if ((OpenData->AgentHandle == DriverImageHandle) &&
((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
Duplicate = FALSE;
for (Index = 0; Index < ChildBufferCount; Index++) {
if (ChildBuffer[Index] == OpenData->ControllerHandle) {
Duplicate = TRUE;
break;
}
}
if (!Duplicate) {
ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
if (ChildHandle == ChildBuffer[ChildBufferCount]) {
ChildHandleValid = TRUE;
}
ChildBufferCount++;
}
}
}
}
CoreReleaseProtocolLock ();
}
if (ChildHandle == NULL || ChildHandleValid) {
ChildrenToStop = 0;
Status = EFI_SUCCESS;
if (ChildBufferCount > 0) {
if (ChildHandle != NULL) {
ChildrenToStop = 1;
Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
} else {
ChildrenToStop = ChildBufferCount;
Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
}
}
if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
}
if (!EFI_ERROR (Status)) {
StopCount++;
}
}
if (ChildBuffer != NULL) {
CoreFreePool (ChildBuffer);
}
}
}
if (StopCount > 0) {
Status = EFI_SUCCESS;
} else {
Status = EFI_NOT_FOUND;
}
Done:
if (DriverImageHandleBuffer != NULL) {
CoreFreePool (DriverImageHandleBuffer);
}
return Status;
}
STATIC
EFI_STATUS
GetHandleFromDriverBinding (
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed,
OUT EFI_HANDLE *Handle
)
/*++
Routine Description:
Locate the driver binding handle which a specified driver binding protocol installed on.
Arguments:
DriverBindingNeed - The specified driver binding protocol.
Handle - The driver binding handle which the protocol installed on.
Returns:
EFI_NOT_FOUND - Could not find the handle.
EFI_SUCCESS - Successfully find the associated driver binding handle.
--*/
{
EFI_STATUS Status ;
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
UINTN DriverBindingHandleCount;
EFI_HANDLE *DriverBindingHandleBuffer;
UINTN Index;
DriverBindingHandleCount = 0;
DriverBindingHandleBuffer = NULL;
*Handle = NULL_HANDLE;
Status = CoreLocateHandleBuffer (
ByProtocol,
&gEfiDriverBindingProtocolGuid,
NULL,
&DriverBindingHandleCount,
&DriverBindingHandleBuffer
);
if (EFI_ERROR (Status) || DriverBindingHandleCount == 0) {
return EFI_NOT_FOUND;
}
for (Index = 0 ; Index < DriverBindingHandleCount; Index++ ) {
Status = CoreOpenProtocol(
DriverBindingHandleBuffer[Index],
&gEfiDriverBindingProtocolGuid,
(VOID **)&DriverBinding,
gDxeCoreImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR (Status) && DriverBinding != NULL) {
if ( DriverBinding == DriverBindingNeed ) {
*Handle = DriverBindingHandleBuffer[Index];
CoreFreePool (DriverBindingHandleBuffer);
return EFI_SUCCESS ;
}
}
}
CoreFreePool (DriverBindingHandleBuffer);
return EFI_NOT_FOUND ;
}

View File

@@ -0,0 +1,333 @@
/*++
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:
notify.c
Abstract:
EFI notify infrastructure
Revision History
--*/
#include <DxeMain.h>
VOID
CoreNotifyProtocolEntry (
IN PROTOCOL_ENTRY *ProtEntry
)
/*++
Routine Description:
Signal event for every protocol in protocol entry.
Arguments:
ProtEntry - Protocol entry
Returns:
--*/
{
PROTOCOL_NOTIFY *ProtNotify;
LIST_ENTRY *Link;
ASSERT_LOCKED (&gProtocolDatabaseLock);
for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
CoreSignalEvent (ProtNotify->Event);
}
}
PROTOCOL_INTERFACE *
CoreRemoveInterfaceFromProtocol (
IN IHANDLE *Handle,
IN EFI_GUID *Protocol,
IN VOID *Interface
)
/*++
Routine Description:
Removes Protocol from the protocol list (but not the handle list).
Arguments:
Handle - The handle to remove protocol on.
Protocol - GUID of the protocol to be moved
Interface - The interface of the protocol
Returns:
Protocol Entry
--*/
{
PROTOCOL_INTERFACE *Prot;
PROTOCOL_NOTIFY *ProtNotify;
PROTOCOL_ENTRY *ProtEntry;
LIST_ENTRY *Link;
ASSERT_LOCKED (&gProtocolDatabaseLock);
Prot = CoreFindProtocolInterface (Handle, Protocol, Interface);
if (Prot != NULL) {
ProtEntry = Prot->Protocol;
//
// If there's a protocol notify location pointing to this entry, back it up one
//
for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
if (ProtNotify->Position == &Prot->ByProtocol) {
ProtNotify->Position = Prot->ByProtocol.BackLink;
}
}
//
// Remove the protocol interface entry
//
RemoveEntryList (&Prot->ByProtocol);
}
return Prot;
}
EFI_STATUS
EFIAPI
CoreRegisterProtocolNotify (
IN EFI_GUID *Protocol,
IN EFI_EVENT Event,
OUT VOID **Registration
)
/*++
Routine Description:
Add a new protocol notification record for the request protocol.
Arguments:
Protocol - The requested protocol to add the notify registration
Event - The event to signal
Registration - Returns the registration record
Returns:
EFI_INVALID_PARAMETER - Invalid parameter
EFI_SUCCESS - Successfully returned the registration record that has been added
--*/
{
PROTOCOL_ENTRY *ProtEntry;
PROTOCOL_NOTIFY *ProtNotify;
EFI_STATUS Status;
if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) {
return EFI_INVALID_PARAMETER;
}
CoreAcquireProtocolLock ();
ProtNotify = NULL;
//
// Get the protocol entry to add the notification too
//
ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
if (ProtEntry != NULL) {
//
// Allocate a new notification record
//
ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY));
if (ProtNotify != NULL) {
ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
ProtNotify->Protocol = ProtEntry;
ProtNotify->Event = Event;
//
// start at the begining
//
ProtNotify->Position = &ProtEntry->Protocols;
InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
}
}
CoreReleaseProtocolLock ();
//
// Done. If we have a protocol notify entry, then return it.
// Otherwise, we must have run out of resources trying to add one
//
Status = EFI_OUT_OF_RESOURCES;
if (ProtNotify != NULL) {
*Registration = ProtNotify;
Status = EFI_SUCCESS;
}
return Status;
}
EFI_STATUS
EFIAPI
CoreReinstallProtocolInterface (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
IN VOID *OldInterface,
IN VOID *NewInterface
)
/*++
Routine Description:
Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
Arguments:
UserHandle - Handle on which the interface is to be reinstalled
Protocol - The numeric ID of the interface
OldInterface - A pointer to the old interface
NewInterface - A pointer to the new interface
Returns:
Status code.
On EFI_SUCCESS The protocol interface was installed
On EFI_NOT_FOUND The OldInterface on the handle was not found
On EFI_INVALID_PARAMETER One of the parameters has an invalid value
--*/
{
EFI_STATUS Status;
IHANDLE *Handle;
PROTOCOL_INTERFACE *Prot;
PROTOCOL_ENTRY *ProtEntry;
Status = CoreValidateHandle (UserHandle);
if (EFI_ERROR (Status)) {
return Status;
}
if (Protocol == NULL) {
return EFI_INVALID_PARAMETER;
}
Handle = (IHANDLE *) UserHandle;
//
// Lock the protocol database
//
CoreAcquireProtocolLock ();
//
// Check that Protocol exists on UserHandle, and Interface matches the interface in the database
//
Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
if (Prot == NULL) {
CoreReleaseProtocolLock ();
return EFI_NOT_FOUND;
}
//
// Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled
//
Status = CoreDisconnectControllersUsingProtocolInterface (
UserHandle,
Prot
);
if (EFI_ERROR (Status)) {
//
// One or more drivers refused to release, so return the error
//
CoreReleaseProtocolLock ();
return Status;
}
//
// Remove the protocol interface from the protocol
//
Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);
if (Prot == NULL) {
CoreReleaseProtocolLock ();
return EFI_NOT_FOUND;
}
ProtEntry = Prot->Protocol;
//
// Update the interface on the protocol
//
Prot->Interface = NewInterface;
//
// Add this protocol interface to the tail of the
// protocol entry
//
InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
//
// Update the Key to show that the handle has been created/modified
//
gHandleDatabaseKey++;
Handle->Key = gHandleDatabaseKey;
//
// Release the lock and connect all drivers to UserHandle
//
CoreReleaseProtocolLock ();
Status = CoreConnectController (
UserHandle,
NULL,
NULL,
TRUE
);
CoreAcquireProtocolLock ();
//
// Notify the notification list for this protocol
//
CoreNotifyProtocolEntry (ProtEntry);
CoreReleaseProtocolLock ();
return EFI_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,737 @@
/*++
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:
locate.c
Abstract:
Locate handle functions
Revision History
--*/
#include <DxeMain.h>
//
// ProtocolRequest - Last LocateHandle request ID
//
UINTN mEfiLocateHandleRequest = 0;
//
// Internal prototypes
//
typedef struct {
EFI_GUID *Protocol;
VOID *SearchKey;
LIST_ENTRY *Position;
PROTOCOL_ENTRY *ProtEntry;
} LOCATE_POSITION;
typedef
IHANDLE *
(* CORE_GET_NEXT) (
IN OUT LOCATE_POSITION *Position,
OUT VOID **Interface
);
STATIC
IHANDLE *
CoreGetNextLocateAllHandles (
IN OUT LOCATE_POSITION *Position,
OUT VOID **Interface
);
STATIC
IHANDLE *
CoreGetNextLocateByRegisterNotify (
IN OUT LOCATE_POSITION *Position,
OUT VOID **Interface
);
STATIC
IHANDLE *
CoreGetNextLocateByProtocol (
IN OUT LOCATE_POSITION *Position,
OUT VOID **Interface
);
//
//
//
EFI_STATUS
EFIAPI
CoreLocateHandle (
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol OPTIONAL,
IN VOID *SearchKey OPTIONAL,
IN OUT UINTN *BufferSize,
OUT EFI_HANDLE *Buffer
)
/*++
Routine Description:
Locates the requested handle(s) and returns them in Buffer.
Arguments:
SearchType - The type of search to perform to locate the handles
Protocol - The protocol to search for
SearchKey - Dependant on SearchType
BufferSize - On input the size of Buffer. On output the
size of data returned.
Buffer - The buffer to return the results in
Returns:
EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.
EFI_INVALID_PARAMETER - Invalid parameter
EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.
--*/
{
EFI_STATUS Status;
LOCATE_POSITION Position;
PROTOCOL_NOTIFY *ProtNotify;
CORE_GET_NEXT GetNext;
UINTN ResultSize;
IHANDLE *Handle;
IHANDLE **ResultBuffer;
VOID *Interface;
if (BufferSize == NULL) {
Status = EFI_INVALID_PARAMETER;
}
if ((*BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
GetNext = NULL;
//
// Set initial position
//
Position.Protocol = Protocol;
Position.SearchKey = SearchKey;
Position.Position = &gHandleList;
ResultSize = 0;
ResultBuffer = (IHANDLE **) Buffer;
Status = EFI_SUCCESS;
//
// Lock the protocol database
//
CoreAcquireProtocolLock ();
//
// Get the search function based on type
//
switch (SearchType) {
case AllHandles:
GetNext = CoreGetNextLocateAllHandles;
break;
case ByRegisterNotify:
//
// Must have SearchKey for locate ByRegisterNotify
//
if (SearchKey == NULL) {
Status = EFI_INVALID_PARAMETER;
break;
}
GetNext = CoreGetNextLocateByRegisterNotify;
break;
case ByProtocol:
GetNext = CoreGetNextLocateByProtocol;
if (Protocol == NULL) {
Status = EFI_INVALID_PARAMETER;
break;
}
//
// Look up the protocol entry and set the head pointer
//
Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
if (Position.ProtEntry == NULL) {
Status = EFI_NOT_FOUND;
break;
}
Position.Position = &Position.ProtEntry->Protocols;
break;
default:
Status = EFI_INVALID_PARAMETER;
break;
}
if (EFI_ERROR(Status)) {
CoreReleaseProtocolLock ();
return Status;
}
//
// Enumerate out the matching handles
//
mEfiLocateHandleRequest += 1;
for (; ;) {
//
// Get the next handle. If no more handles, stop
//
Handle = GetNext (&Position, &Interface);
if (NULL == Handle) {
break;
}
//
// Increase the resulting buffer size, and if this handle
// fits return it
//
ResultSize += sizeof(Handle);
if (ResultSize <= *BufferSize) {
*ResultBuffer = Handle;
ResultBuffer += 1;
}
}
//
// If the result is a zero length buffer, then there were no
// matching handles
//
if (ResultSize == 0) {
Status = EFI_NOT_FOUND;
} else {
//
// Return the resulting buffer size. If it's larger than what
// was passed, then set the error code
//
if (ResultSize > *BufferSize) {
Status = EFI_BUFFER_TOO_SMALL;
}
*BufferSize = ResultSize;
if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {
//
// If this is a search by register notify and a handle was
// returned, update the register notification position
//
ProtNotify = SearchKey;
ProtNotify->Position = ProtNotify->Position->ForwardLink;
}
}
CoreReleaseProtocolLock ();
return Status;
}
STATIC
IHANDLE *
CoreGetNextLocateAllHandles (
IN OUT LOCATE_POSITION *Position,
OUT VOID **Interface
)
/*++
Routine Description:
Routine to get the next Handle, when you are searching for all handles.
Arguments:
Position - Information about which Handle to seach for.
Interface - Return the interface structure for the matching protocol.
Returns:
IHANDLE - An IHANDLE is returned if the next Position is not the end of the
list. A NULL_HANDLE is returned if it's the end of the list.
--*/
{
IHANDLE *Handle;
//
// Next handle
//
Position->Position = Position->Position->ForwardLink;
//
// If not at the end of the list, get the handle
//
Handle = NULL_HANDLE;
*Interface = NULL;
if (Position->Position != &gHandleList) {
Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
}
return Handle;
}
STATIC
IHANDLE *
CoreGetNextLocateByRegisterNotify (
IN OUT LOCATE_POSITION *Position,
OUT VOID **Interface
)
/*++
Routine Description:
Routine to get the next Handle, when you are searching for register protocol
notifies.
Arguments:
Position - Information about which Handle to seach for.
Interface - Return the interface structure for the matching protocol.
Returns:
IHANDLE - An IHANDLE is returned if the next Position is not the end of the
list. A NULL_HANDLE is returned if it's the end of the list.
--*/
{
IHANDLE *Handle;
PROTOCOL_NOTIFY *ProtNotify;
PROTOCOL_INTERFACE *Prot;
LIST_ENTRY *Link;
Handle = NULL_HANDLE;
*Interface = NULL;
ProtNotify = Position->SearchKey;
//
// If this is the first request, get the next handle
//
if (ProtNotify != NULL) {
ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
Position->SearchKey = NULL;
//
// If not at the end of the list, get the next handle
//
Link = ProtNotify->Position->ForwardLink;
if (Link != &ProtNotify->Protocol->Protocols) {
Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
Handle = (IHANDLE *) Prot->Handle;
*Interface = Prot->Interface;
}
}
return Handle;
}
STATIC
IHANDLE *
CoreGetNextLocateByProtocol (
IN OUT LOCATE_POSITION *Position,
OUT VOID **Interface
)
/*++
Routine Description:
Routine to get the next Handle, when you are searching for a given protocol.
Arguments:
Position - Information about which Handle to seach for.
Interface - Return the interface structure for the matching protocol.
Returns:
IHANDLE - An IHANDLE is returned if the next Position is not the end of the
list. A NULL_HANDLE is returned if it's the end of the list.
--*/
{
IHANDLE *Handle;
LIST_ENTRY *Link;
PROTOCOL_INTERFACE *Prot;
Handle = NULL_HANDLE;
*Interface = NULL;
for (; ;) {
//
// Next entry
//
Link = Position->Position->ForwardLink;
Position->Position = Link;
//
// If not at the end, return the handle
//
if (Link == &Position->ProtEntry->Protocols) {
Handle = NULL_HANDLE;
break;
}
//
// Get the handle
//
Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
Handle = (IHANDLE *) Prot->Handle;
*Interface = Prot->Interface;
//
// If this handle has not been returned this request, then
// return it now
//
if (Handle->LocateRequest != mEfiLocateHandleRequest) {
Handle->LocateRequest = mEfiLocateHandleRequest;
break;
}
}
return Handle;
}
EFI_STATUS
EFIAPI
CoreLocateDevicePath (
IN EFI_GUID *Protocol,
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
OUT EFI_HANDLE *Device
)
/*++
Routine Description:
Locates the handle to a device on the device path that best matches the specified protocol.
Arguments:
Protocol - The protocol to search for.
DevicePath - On input, a pointer to a pointer to the device path. On output, the device
path pointer is modified to point to the remaining part of the devicepath.
Device - A pointer to the returned device handle.
Returns:
EFI_SUCCESS - The resulting handle was returned.
EFI_NOT_FOUND - No handles matched the search.
EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
--*/
{
INTN SourceSize;
INTN Size;
INTN BestMatch;
UINTN HandleCount;
UINTN Index;
EFI_STATUS Status;
EFI_HANDLE *Handles;
EFI_HANDLE Handle;
EFI_DEVICE_PATH_PROTOCOL *SourcePath;
EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
if (Protocol == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((DevicePath == NULL) || (*DevicePath == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Device == NULL) {
return EFI_INVALID_PARAMETER;
}
*Device = NULL_HANDLE;
SourcePath = *DevicePath;
SourceSize = CoreDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
//
// The source path can only have 1 instance
//
if (CoreIsDevicePathMultiInstance (SourcePath)) {
DEBUG((EFI_D_ERROR, "LocateDevicePath: Device path has too many instances\n"));
return EFI_INVALID_PARAMETER;
}
//
// Get a list of all handles that support the requested protocol
//
Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);
if (EFI_ERROR (Status) || HandleCount == 0) {
return EFI_NOT_FOUND;
}
BestMatch = -1;
for(Index = 0; Index < HandleCount; Index += 1) {
Handle = Handles[Index];
Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);
if (EFI_ERROR (Status)) {
//
// If this handle doesn't support device path, then skip it
//
continue;
}
//
// Check if DevicePath is first part of SourcePath
//
Size = CoreDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {
//
// If the size is equal to the best match, then we
// have a duplice device path for 2 different device
// handles
//
ASSERT (Size != BestMatch);
//
// We've got a match, see if it's the best match so far
//
if (Size > BestMatch) {
BestMatch = Size;
*Device = Handle;
}
}
}
CoreFreePool (Handles);
//
// If there wasn't any match, then no parts of the device path was found.
// Which is strange since there is likely a "root level" device path in the system.
//
if (BestMatch == -1) {
return EFI_NOT_FOUND;
}
//
// Return the remaining part of the device path
//
*DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
CoreLocateProtocol (
IN EFI_GUID *Protocol,
IN VOID *Registration OPTIONAL,
OUT VOID **Interface
)
/*++
Routine Description:
Return the first Protocol Interface that matches the Protocol GUID. If
Registration is pasased in return a Protocol Instance that was just add
to the system. If Retistration is NULL return the first Protocol Interface
you find.
Arguments:
Protocol - The protocol to search for
Registration - Optional Registration Key returned from RegisterProtocolNotify()
Interface - Return the Protocol interface (instance).
Returns:
EFI_SUCCESS - If a valid Interface is returned
EFI_INVALID_PARAMETER - Invalid parameter
EFI_NOT_FOUND - Protocol interface not found
--*/
{
EFI_STATUS Status;
LOCATE_POSITION Position;
PROTOCOL_NOTIFY *ProtNotify;
IHANDLE *Handle;
if (Interface == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Protocol == NULL) {
return EFI_NOT_FOUND;
}
*Interface = NULL;
Status = EFI_SUCCESS;
//
// Set initial position
//
Position.Protocol = Protocol;
Position.SearchKey = Registration;
Position.Position = &gHandleList;
//
// Lock the protocol database
//
CoreAcquireProtocolLock ();
mEfiLocateHandleRequest += 1;
if (NULL == Registration) {
//
// Look up the protocol entry and set the head pointer
//
Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
if (Position.ProtEntry == NULL) {
Status = EFI_NOT_FOUND;
goto Done;
}
Position.Position = &Position.ProtEntry->Protocols;
Handle = CoreGetNextLocateByProtocol (&Position, Interface);
} else {
Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);
}
if (NULL == Handle) {
Status = EFI_NOT_FOUND;
} else if (NULL != Registration) {
//
// If this is a search by register notify and a handle was
// returned, update the register notification position
//
ProtNotify = Registration;
ProtNotify->Position = ProtNotify->Position->ForwardLink;
}
Done:
CoreReleaseProtocolLock ();
return Status;
}
EFI_STATUS
EFIAPI
CoreLocateHandleBuffer (
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol OPTIONAL,
IN VOID *SearchKey OPTIONAL,
IN OUT UINTN *NumberHandles,
OUT EFI_HANDLE **Buffer
)
/*++
Routine Description:
Function returns an array of handles that support the requested protocol
in a buffer allocated from pool. This is a version of CoreLocateHandle()
that allocates a buffer for the caller.
Arguments:
SearchType - Specifies which handle(s) are to be returned.
Protocol - Provides the protocol to search by.
This parameter is only valid for SearchType ByProtocol.
SearchKey - Supplies the search key depending on the SearchType.
NumberHandles - The number of handles returned in Buffer.
Buffer - A pointer to the buffer to return the requested array of
handles that support Protocol.
Returns:
EFI_SUCCESS - The result array of handles was returned.
EFI_NOT_FOUND - No handles match the search.
EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
EFI_INVALID_PARAMETER - Invalid parameter
--*/
{
EFI_STATUS Status;
UINTN BufferSize;
if (NumberHandles == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
BufferSize = 0;
*NumberHandles = 0;
*Buffer = NULL;
Status = CoreLocateHandle (
SearchType,
Protocol,
SearchKey,
&BufferSize,
*Buffer
);
//
// LocateHandleBuffer() returns incorrect status code if SearchType is
// invalid.
//
// Add code to correctly handle expected errors from CoreLocateHandle().
//
if (EFI_ERROR(Status)) {
switch (Status) {
case EFI_BUFFER_TOO_SMALL:
break;
case EFI_INVALID_PARAMETER:
return Status;
default:
return EFI_NOT_FOUND;
}
}
*Buffer = CoreAllocateBootServicesPool (BufferSize);
if (*Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = CoreLocateHandle (
SearchType,
Protocol,
SearchKey,
&BufferSize,
*Buffer
);
*NumberHandles = BufferSize/sizeof(EFI_HANDLE);
if (EFI_ERROR(Status)) {
*NumberHandles = 0;
}
return Status;
}

View File

@@ -0,0 +1,380 @@
/*++
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:
Image.h
Abstract:
Revision History
--*/
#ifndef _IMAGE_H_
#define _IMAGE_H_
#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','d','r','i')
typedef struct {
UINTN Signature;
EFI_HANDLE Handle; // Image handle
UINTN Type; // Image type
BOOLEAN Started; // If entrypoint has been called
EFI_IMAGE_ENTRY_POINT EntryPoint; // The image's entry point
EFI_LOADED_IMAGE_PROTOCOL Info; // loaded image protocol
EFI_PHYSICAL_ADDRESS ImageBasePage; // Location in memory
UINTN NumberOfPages; // Number of pages
CHAR8 *FixupData; // Original fixup data
EFI_TPL Tpl; // Tpl of started image
EFI_STATUS Status; // Status returned by started image
UINTN ExitDataSize; // Size of ExitData from started image
VOID *ExitData; // Pointer to exit data from started image
BASE_LIBRARY_JUMP_BUFFER *JumpContext; // Pointer to buffer for context save/retore
UINT16 Machine; // Machine type from PE image
EFI_EBC_PROTOCOL *Ebc; // EBC Protocol pointer
BOOLEAN RuntimeFixupValid; // True if RT image needs fixup
VOID *RuntimeFixup; // Copy of fixup data;
LIST_ENTRY Link; // List of RT LOADED_IMAGE_PRIVATE_DATA
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; // PeCoffLoader ImageContext
} LOADED_IMAGE_PRIVATE_DATA;
#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
#define LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','p','e','i')
typedef struct {
UINTN Signature;
EFI_HANDLE Handle; // Image handle
EFI_PE32_IMAGE_PROTOCOL Pe32Image;
} LOAD_PE32_IMAGE_PRIVATE_DATA;
#define LOAD_PE32_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
CR(a, LOAD_PE32_IMAGE_PRIVATE_DATA, Pe32Image, LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE)
//
// Private Data Types
//
#define IMAGE_FILE_HANDLE_SIGNATURE EFI_SIGNATURE_32('i','m','g','f')
typedef struct {
UINTN Signature;
BOOLEAN FreeBuffer;
VOID *Source;
UINTN SourceSize;
} IMAGE_FILE_HANDLE;
//
// Abstractions for reading image contents
//
EFI_STATUS
CoreOpenImageFile (
IN BOOLEAN BootPolicy,
IN VOID *SourceBuffer OPTIONAL,
IN UINTN SourceSize,
IN OUT EFI_DEVICE_PATH_PROTOCOL *FilePath,
OUT EFI_HANDLE *DeviceHandle,
IN IMAGE_FILE_HANDLE *ImageFileHandle,
OUT UINT32 *AuthenticationStatus
)
/*++
Routine Description:
Opens a file for (simple) reading. The simple read abstraction
will access the file either from a memory copy, from a file
system interface, or from the load file interface.
Arguments:
BootPolicy - Policy for Open Image File.
SourceBuffer - Pointer to the memory location containing copy
of the image to be loaded.
SourceSize - The size in bytes of SourceBuffer.
FilePath - The specific file path from which the image is loaded
DeviceHandle - Pointer to the return device handle.
ImageFileHandle - Pointer to the image file handle.
AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.
Returns:
A handle to access the file
--*/
;
EFI_STATUS
EFIAPI
CoreReadImageFile (
IN VOID *UserHandle,
IN UINTN Offset,
IN OUT UINTN *ReadSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Read image file (specified by UserHandle) into user specified buffer with specified offset
and length.
Arguments:
UserHandle - Image file handle
Offset - Offset to the source file
ReadSize - For input, pointer of size to read;
For output, pointer of size actually read.
Buffer - Buffer to write into
Returns:
EFI_SUCCESS - Successfully read the specified part of file into buffer.
--*/
;
VOID
EFIAPI
CoreCloseImageFile (
IN IMAGE_FILE_HANDLE *ImageFileHandle
)
/*++
Routine Description:
A function out of date, should be removed.
Arguments:
ImageFileHandle - Handle of the file to close
Returns:
None
--*/
;
//
// Image processing worker functions
//
EFI_STATUS
CoreDevicePathToInterface (
IN EFI_GUID *Protocol,
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
OUT VOID **Interface,
OUT EFI_HANDLE *Handle
)
/*++
Routine Description:
Search a handle to a device on a specified device path that supports a specified protocol,
interface of that protocol on that handle is another output.
Arguments:
Protocol - The protocol to search for
FilePath - The specified device path
Interface - Interface of the protocol on the handle
Handle - The handle to the device on the specified device path that supports the protocol.
Returns:
Status code.
--*/
;
EFI_STATUS
CoreLoadPeImage (
IN VOID *Pe32Handle,
IN LOADED_IMAGE_PRIVATE_DATA *Image,
IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
IN UINT32 Attribute
)
/*++
Routine Description:
Loads, relocates, and invokes a PE/COFF image
Arguments:
Pe32Handle - The handle of PE32 image
Image - PE image to be loaded
DstBuffer - The buffer to store the image
EntryPoint - A pointer to the entry point
Attribute - The bit mask of attributes to set for the load PE image
Returns:
EFI_SUCCESS - The file was loaded, relocated, and invoked
EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
EFI_INVALID_PARAMETER - Invalid parameter
EFI_BUFFER_TOO_SMALL - Buffer for image is too small
--*/
;
LOADED_IMAGE_PRIVATE_DATA *
CoreLoadedImageInfo (
IN EFI_HANDLE ImageHandle
)
/*++
Routine Description:
TODO: Add function description
Arguments:
ImageHandle - TODO: add argument description
Returns:
TODO: add return values
--*/
;
VOID
CoreUnloadAndCloseImage (
IN LOADED_IMAGE_PRIVATE_DATA *Image,
IN BOOLEAN FreePage
)
/*++
Routine Description:
Unloads EFI image from memory.
Arguments:
Image - EFI image
FreePage - Free allocated pages
Returns:
None
--*/
;
//
// Exported Image functions
//
EFI_STATUS
EFIAPI
CoreLoadImageEx (
IN EFI_PE32_IMAGE_PROTOCOL *This,
IN EFI_HANDLE ParentImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN VOID *SourceBuffer OPTIONAL,
IN UINTN SourceSize,
IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
OUT UINTN *NumberOfPages OPTIONAL,
OUT EFI_HANDLE *ImageHandle,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
IN UINT32 Attribute
)
/*++
Routine Description:
Loads an EFI image into memory and returns a handle to the image with extended parameters.
Arguments:
ParentImageHandle - The caller's image handle.
FilePath - The specific file path from which the image is loaded.
SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
the image to be loaded.
SourceSize - The size in bytes of SourceBuffer.
DstBuffer - The buffer to store the image.
NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
For output, specifies the actual space size needed.
ImageHandle - Image handle for output.
EntryPoint - Image entry point for output.
Attribute - The bit mask of attributes to set for the load PE image.
Returns:
EFI_SUCCESS - The image was loaded into memory.
EFI_NOT_FOUND - The FilePath was not found.
EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
parsed to locate the proper protocol for loading the file.
EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
--*/
;
EFI_STATUS
EFIAPI
CoreUnloadImageEx (
IN EFI_PE32_IMAGE_PROTOCOL *This,
IN EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Unload the specified image.
Arguments:
This - Indicates the calling context.
ImageHandle - The specified image handle.
Returns:
EFI_INVALID_PARAMETER - Image handle is NULL.
EFI_UNSUPPORTED - Attempt to unload an unsupported image.
EFI_SUCCESS - Image successfully unloaded.
--*/
;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,569 @@
/*++
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:
ImageFile.c
Abstract:
Revision History
--*/
#include <DxeMain.h>
VOID
CoreDevicePathToFileName (
IN FILEPATH_DEVICE_PATH *FilePath,
OUT CHAR16 **String
);
EFI_STATUS
CoreOpenImageFile (
IN BOOLEAN BootPolicy,
IN VOID *SourceBuffer OPTIONAL,
IN UINTN SourceSize,
IN OUT EFI_DEVICE_PATH_PROTOCOL *FilePath,
OUT EFI_HANDLE *DeviceHandle,
IN IMAGE_FILE_HANDLE *ImageFileHandle,
OUT UINT32 *AuthenticationStatus
)
/*++
Routine Description:
Opens a file for (simple) reading. The simple read abstraction
will access the file either from a memory copy, from a file
system interface, or from the load file interface.
Arguments:
BootPolicy - Policy for Open Image File.
SourceBuffer - Pointer to the memory location containing copy
of the image to be loaded.
SourceSize - The size in bytes of SourceBuffer.
FilePath - The specific file path from which the image is loaded
DeviceHandle - Pointer to the return device handle.
ImageFileHandle - Pointer to the image file handle.
AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.
Returns:
EFI_SUCCESS - Image file successfully opened.
EFI_LOAD_ERROR - If the caller passed a copy of the file, and SourceSize is 0.
EFI_INVALID_PARAMETER - File path is not valid.
EFI_NOT_FOUND - File not found.
--*/
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *TempFilePath;
FILEPATH_DEVICE_PATH *FilePathNode;
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
EFI_FILE_HANDLE FileHandle;
EFI_FILE_HANDLE LastHandle;
EFI_LOAD_FILE_PROTOCOL *LoadFile;
EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
EFI_SECTION_TYPE SectionType;
UINT8 *Pe32Buffer;
UINTN Pe32BufferSize;
EFI_FV_FILETYPE Type;
EFI_FV_FILE_ATTRIBUTES Attrib;
EFI_FILE_INFO *FileInfo;
UINTN FileInfoSize;
EFI_GUID *NameGuid;
*AuthenticationStatus = 0;
ZeroMem (ImageFileHandle, sizeof (IMAGE_FILE_HANDLE));
ImageFileHandle->Signature = IMAGE_FILE_HANDLE_SIGNATURE;
//
// If the caller passed a copy of the file, then just use it
//
if (SourceBuffer != NULL) {
ImageFileHandle->Source = SourceBuffer;
ImageFileHandle->SourceSize = SourceSize;
*DeviceHandle = NULL;
if (SourceSize > 0) {
Status = EFI_SUCCESS;
} else {
Status = EFI_LOAD_ERROR;
}
goto Done;
}
//
// Make sure FilePath is valid
//
if (FilePath == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Check to see if it's in a Firmware Volume
//
FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePath;
Status = CoreDevicePathToInterface (
&gEfiFirmwareVolumeProtocolGuid,
(EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode,
(VOID*)&FwVol,
DeviceHandle
);
if (!EFI_ERROR (Status)) {
//
// For FwVol File system there is only a single file name that is a GUID.
//
NameGuid = EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode);
if (NameGuid != NULL) {
SectionType = EFI_SECTION_PE32;
Pe32Buffer = NULL;
Status = FwVol->ReadSection (
FwVol,
NameGuid,
SectionType,
0,
(VOID **)&Pe32Buffer,
&Pe32BufferSize,
AuthenticationStatus
);
if (EFI_ERROR (Status)) {
//
// Try a raw file, since a PE32 SECTION does not exist
//
if (Pe32Buffer != NULL) {
CoreFreePool (Pe32Buffer);
*AuthenticationStatus = 0;
}
Pe32Buffer = NULL;
Status = FwVol->ReadFile (
FwVol,
NameGuid,
(VOID **)&Pe32Buffer,
&Pe32BufferSize,
&Type,
&Attrib,
AuthenticationStatus
);
}
if (!EFI_ERROR (Status)) {
//
// One of the reads passed so we are done
//
ImageFileHandle->Source = Pe32Buffer;
ImageFileHandle->SourceSize = Pe32BufferSize;
ImageFileHandle->FreeBuffer = TRUE;
goto Done;
}
}
}
//
// Attempt to access the file via a file system interface
//
FilePathNode = (FILEPATH_DEVICE_PATH *) FilePath;
Status = CoreDevicePathToInterface (
&gEfiSimpleFileSystemProtocolGuid,
(EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode,
(VOID*)&Volume,
DeviceHandle
);
if (!EFI_ERROR (Status)) {
//
// Open the Volume to get the File System handle
//
Status = Volume->OpenVolume (Volume, &FileHandle);
if (!EFI_ERROR (Status)) {
//
// Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
// directory information and filename can be seperate. The goal is to inch
// our way down each device path node and close the previous node
//
while (!IsDevicePathEnd (&FilePathNode->Header)) {
if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
Status = EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status)) {
//
// Exit loop on Error
//
break;
}
LastHandle = FileHandle;
FileHandle = NULL;
Status = LastHandle->Open (
LastHandle,
&FileHandle,
FilePathNode->PathName,
EFI_FILE_MODE_READ,
0
);
//
// Close the previous node
//
LastHandle->Close (LastHandle);
FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
}
if (!EFI_ERROR (Status)) {
//
// We have found the file. Now we need to read it. Before we can read the file we need to
// figure out how big the file is.
//
FileInfo = NULL;
FileInfoSize = sizeof (EFI_FILE_INFO);
while (CoreGrowBuffer (&Status, (VOID **)&FileInfo, FileInfoSize)) {
//
// Automatically allocate buffer of the correct size and make the call
//
Status = FileHandle->GetInfo (
FileHandle,
&gEfiFileInfoGuid,
&FileInfoSize,
FileInfo
);
}
if (!EFI_ERROR (Status)) {
//
// Allocate space for the file
//
ImageFileHandle->Source = CoreAllocateBootServicesPool ((UINTN)FileInfo->FileSize);
if (ImageFileHandle->Source != NULL) {
//
// Read the file into the buffer we allocated
//
ImageFileHandle->SourceSize = (UINTN)FileInfo->FileSize;
ImageFileHandle->FreeBuffer = TRUE;
Status = FileHandle->Read (FileHandle, &ImageFileHandle->SourceSize, ImageFileHandle->Source);
//
// Close the file since we are done
//
FileHandle->Close (FileHandle);
} else {
Status = EFI_OUT_OF_RESOURCES;
}
goto Done;
}
}
}
}
//
// Try LoadFile style
//
TempFilePath = FilePath;
Status = CoreDevicePathToInterface (
&gEfiLoadFileProtocolGuid,
&TempFilePath,
(VOID*)&LoadFile,
DeviceHandle
);
if (!EFI_ERROR (Status)) {
//
// Call LoadFile with the correct buffer size
//
while (CoreGrowBuffer (&Status, (VOID **)&ImageFileHandle->Source, ImageFileHandle->SourceSize)) {
Status = LoadFile->LoadFile (
LoadFile,
TempFilePath,
BootPolicy,
&ImageFileHandle->SourceSize,
ImageFileHandle->Source
);
//
// If success or other error happens, stop loop
//
if (Status != EFI_BUFFER_TOO_SMALL) {
break;
}
}
if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {
ImageFileHandle->FreeBuffer = TRUE;
goto Done;
}
}
//
// Nothing else to try
//
DEBUG ((EFI_D_LOAD|EFI_D_WARN, "CoreOpenImageFile: Device did not support a known load protocol\n"));
Status = EFI_NOT_FOUND;
Done:
//
// If the file was not accessed, clean up
//
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
if (ImageFileHandle->FreeBuffer) {
//
// Free the source buffer if we allocated it
//
CoreFreePool (ImageFileHandle->Source);
}
}
return Status;
}
EFI_STATUS
EFIAPI
CoreReadImageFile (
IN VOID *UserHandle,
IN UINTN Offset,
IN OUT UINTN *ReadSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Read image file (specified by UserHandle) into user specified buffer with specified offset
and length.
Arguments:
UserHandle - Image file handle
Offset - Offset to the source file
ReadSize - For input, pointer of size to read;
For output, pointer of size actually read.
Buffer - Buffer to write into
Returns:
EFI_SUCCESS - Successfully read the specified part of file into buffer.
--*/
{
UINTN EndPosition;
IMAGE_FILE_HANDLE *FHand;
FHand = (IMAGE_FILE_HANDLE *)UserHandle;
ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);
//
// Move data from our local copy of the file
//
EndPosition = Offset + *ReadSize;
if (EndPosition > FHand->SourceSize) {
*ReadSize = (UINT32)(FHand->SourceSize - Offset);
}
if (Offset >= FHand->SourceSize) {
*ReadSize = 0;
}
CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
return EFI_SUCCESS;
}
EFI_STATUS
CoreDevicePathToInterface (
IN EFI_GUID *Protocol,
IN EFI_DEVICE_PATH_PROTOCOL **FilePath,
OUT VOID **Interface,
OUT EFI_HANDLE *Handle
)
/*++
Routine Description:
Search a handle to a device on a specified device path that supports a specified protocol,
interface of that protocol on that handle is another output.
Arguments:
Protocol - The protocol to search for
FilePath - The specified device path
Interface - Interface of the protocol on the handle
Handle - The handle to the device on the specified device path that supports the protocol.
Returns:
Status code.
--*/
{
EFI_STATUS Status;
Status = CoreLocateDevicePath (Protocol, FilePath, Handle);
if (!EFI_ERROR (Status)) {
Status = CoreHandleProtocol (*Handle, Protocol, Interface);
}
return Status;
}
VOID
CoreDevicePathToFileName (
IN FILEPATH_DEVICE_PATH *FilePath,
OUT CHAR16 **String
)
/*++
Routine Description:
Transfer a device's full path a string.
Arguments:
FilePath - Device path
String - The string represent the device's full path
Returns:
None
--*/
{
UINTN StringSize;
FILEPATH_DEVICE_PATH *FilePathNode;
CHAR16 *Str;
*String = NULL;
StringSize = 0;
FilePathNode = FilePath;
while (!IsDevicePathEnd (&FilePathNode->Header)) {
//
// For filesystem access each node should be a filepath component
//
if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
return;
}
StringSize += StrLen (FilePathNode->PathName);
FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
}
*String = CoreAllocateBootServicesPool (StringSize);
if (*String == NULL) {
return;
}
FilePathNode = FilePath;
Str = *String;
while (!IsDevicePathEnd (&FilePathNode->Header)) {
StrCat (Str, FilePathNode->PathName);
FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
}
}
BOOLEAN
CoreGrowBuffer (
IN OUT EFI_STATUS *Status,
IN OUT VOID **Buffer,
IN UINTN BufferSize
)
/*++
Routine Description:
Helper function called as part of the code needed
to allocate the proper sized buffer for various
EFI interfaces.
Arguments:
Status - Current status
Buffer - Current allocated buffer, or NULL
BufferSize - Current buffer size needed
Returns:
TRUE - if the buffer was reallocated and the caller
should try the API again.
FALSE - buffer could not be allocated and the caller
should not try the API again.
--*/
{
BOOLEAN TryAgain;
TryAgain = FALSE;
//
// If this is an initial request, buffer will be null with a new buffer size
//
if (*Buffer == NULL) {
*Status = EFI_BUFFER_TOO_SMALL;
}
if (BufferSize == 0) {
return TRUE;
}
//
// If the status code is "buffer too small", resize the buffer
//
if (*Status == EFI_BUFFER_TOO_SMALL) {
if (*Buffer != NULL) {
CoreFreePool (*Buffer);
}
*Buffer = CoreAllocateBootServicesPool (BufferSize);
if (*Buffer != NULL) {
TryAgain = TRUE;
} else {
*Status = EFI_OUT_OF_RESOURCES;
}
}
//
// If there's an error, free the buffer
//
if ((!TryAgain) && (EFI_ERROR (*Status)) && (*Buffer)) {
CoreFreePool (*Buffer);
*Buffer = NULL;
}
return TryAgain;
}

View File

@@ -0,0 +1,407 @@
/*++
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:
Library.h
Abstract:
Revision History
--*/
#ifndef _DXE_LIBRARY_H_
#define _DXE_LIBRARY_H_
VOID
CoreReportProgressCode (
IN EFI_STATUS_CODE_VALUE Value
)
/*++
Routine Description:
Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid.
Arguments:
Value - Describes the class/subclass/operation of the hardware or software entity
that the Status Code relates to.
Returns:
None
--*/
;
VOID
CoreReportProgressCodeSpecific (
IN EFI_STATUS_CODE_VALUE Value,
IN EFI_HANDLE Handle
)
/*++
Routine Description:
Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid,
with a handle as additional information.
Arguments:
Value - Describes the class/subclass/operation of the hardware or software entity
that the Status Code relates to.
Handle - Additional information.
Returns:
None
--*/
;
VOID
CoreAcquireLock (
IN EFI_LOCK *Lock
)
/*++
Routine Description:
Raising to the task priority level of the mutual exclusion
lock, and then acquires ownership of the lock.
Arguments:
Lock - The lock to acquire
Returns:
Lock owned
--*/
;
EFI_STATUS
CoreAcquireLockOrFail (
IN EFI_LOCK *Lock
)
/*++
Routine Description:
Initialize a basic mutual exclusion lock. Each lock
provides mutual exclusion access at it's task priority
level. Since there is no-premption (at any TPL) or
multiprocessor support, acquiring the lock only consists
of raising to the locks TPL.
Arguments:
Lock - The EFI_LOCK structure to initialize
Returns:
EFI_SUCCESS - Lock Owned.
EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned.
--*/
;
VOID
CoreReleaseLock (
IN EFI_LOCK *Lock
)
/*++
Routine Description:
Releases ownership of the mutual exclusion lock, and
restores the previous task priority level.
Arguments:
Lock - The lock to release
Returns:
Lock unowned
--*/
;
//
// Device Path functions
//
UINTN
CoreDevicePathSize (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
/*++
Routine Description:
Calculate the size of a whole device path.
Arguments:
DevicePath - The pointer to the device path data.
Returns:
Size of device path data structure..
--*/
;
BOOLEAN
CoreIsDevicePathMultiInstance (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
/*++
Routine Description:
Return TRUE is this is a multi instance device path.
Arguments:
DevicePath - A pointer to a device path data structure.
Returns:
TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
instance.
--*/
;
EFI_DEVICE_PATH_PROTOCOL *
CoreDuplicateDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
/*++
Routine Description:
Duplicate a new device path data structure from the old one.
Arguments:
DevicePath - A pointer to a device path data structure.
Returns:
A pointer to the new allocated device path data.
Caller must free the memory used by DevicePath if it is no longer needed.
--*/
;
EFI_DEVICE_PATH_PROTOCOL *
CoreAppendDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *Src1,
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
/*++
Routine Description:
Function is used to append a Src1 and Src2 together.
Arguments:
Src1 - A pointer to a device path data structure.
Node - A pointer to a device path data structure.
Returns:
A pointer to the new device path is returned.
NULL is returned if space for the new device path could not be allocated from pool.
It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
--*/
;
VOID *
CoreAllocateBootServicesPool (
IN UINTN AllocationSize
)
/*++
Routine Description:
Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize.
Arguments:
AllocationSize - Size to allocate.
Returns:
Pointer of the allocated pool.
--*/
;
VOID *
CoreAllocateZeroBootServicesPool (
IN UINTN AllocationSize
)
/*++
Routine Description:
Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize.
Arguments:
AllocationSize - Size to allocate.
Returns:
Pointer of the allocated pool.
--*/
;
EFI_STATUS
CoreGetConfigTable (
IN EFI_GUID *Guid,
IN OUT VOID **Table
)
/*++
Routine Description:
Find a config table by name in system table's ConfigurationTable.
Arguments:
Guid - The table name to look for
Table - Pointer of the config table
Returns:
EFI_NOT_FOUND - Could not find the table in system table's ConfigurationTable.
EFI_SUCCESS - Table successfully found.
--*/
;
VOID *
CoreAllocateRuntimeCopyPool (
IN UINTN AllocationSize,
IN VOID *Buffer
)
/*++
Routine Description:
Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool.
Arguments:
AllocationSize - Size to allocate.
Buffer - Specified buffer that will be copy to the allocated pool
Returns:
Pointer of the allocated pool.
--*/
;
VOID *
CoreAllocateRuntimePool (
IN UINTN AllocationSize
)
/*++
Routine Description:
Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize.
Arguments:
AllocationSize - Size to allocate.
Returns:
Pointer of the allocated pool.
--*/
;
VOID *
CoreAllocateCopyPool (
IN UINTN AllocationSize,
IN VOID *Buffer
)
/*++
Routine Description:
Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool.
Arguments:
AllocationSize - Size to allocate.
Buffer - Specified buffer that will be copy to the allocated pool
Returns:
Pointer of the allocated pool.
--*/
;
EFI_EVENT
CoreCreateProtocolNotifyEvent (
IN EFI_GUID *ProtocolGuid,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN VOID *NotifyContext,
OUT VOID **Registration,
IN BOOLEAN SignalFlag
)
/*++
Routine Description:
Create a protocol notification event and return it.
Arguments:
ProtocolGuid - Protocol to register notification event on.
NotifyTpl - Maximum TPL to signal the NotifyFunction.
NotifyFuncition - EFI notification routine.
NotifyContext - Context passed into Event when it is created.
Registration - Registration key returned from RegisterProtocolNotify().
SignalFlag - Boolean value to decide whether kick the event after register or not.
Returns:
The EFI_EVENT that has been registered to be signaled when a ProtocolGuid
is added to the system.
--*/
;
#endif

View File

@@ -0,0 +1,613 @@
/*++
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:
Library.c
Abstract:
DXE Core library services.
--*/
#include <DxeMain.h>
UINTN mErrorLevel = EFI_D_ERROR | EFI_D_LOAD;
EFI_DEVICE_HANDLE_EXTENDED_DATA mStatusCodeData = {
{
sizeof (EFI_STATUS_CODE_DATA),
0,
EFI_STATUS_CODE_SPECIFIC_DATA_GUID
},
NULL
};
VOID
CoreReportProgressCodeSpecific (
IN EFI_STATUS_CODE_VALUE Value,
IN EFI_HANDLE Handle
)
/*++
Routine Description:
Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid,
with a handle as additional information.
Arguments:
Value - Describes the class/subclass/operation of the hardware or software entity
that the Status Code relates to.
Handle - Additional information.
Returns:
None
--*/
{
mStatusCodeData.DataHeader.Size = sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA);
mStatusCodeData.Handle = Handle;
if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
gStatusCode->ReportStatusCode (
EFI_PROGRESS_CODE,
Value,
0,
&gEfiDxeServicesTableGuid,
(EFI_STATUS_CODE_DATA *) &mStatusCodeData
);
}
}
VOID
CoreReportProgressCode (
IN EFI_STATUS_CODE_VALUE Value
)
/*++
Routine Description:
Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid.
Arguments:
Value - Describes the class/subclass/operation of the hardware or software entity
that the Status Code relates to.
Returns:
None
--*/
{
if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
gStatusCode->ReportStatusCode (
EFI_PROGRESS_CODE,
Value,
0,
&gEfiDxeServicesTableGuid,
NULL
);
}
}
VOID *
CoreAllocateBootServicesPool (
IN UINTN AllocationSize
)
/*++
Routine Description:
Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize.
Arguments:
AllocationSize - Size to allocate.
Returns:
Pointer of the allocated pool.
--*/
{
VOID *Memory;
CoreAllocatePool (EfiBootServicesData, AllocationSize, &Memory);
return Memory;
}
VOID *
CoreAllocateZeroBootServicesPool (
IN UINTN AllocationSize
)
/*++
Routine Description:
Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize.
Arguments:
AllocationSize - Size to allocate.
Returns:
Pointer of the allocated pool.
--*/
{
VOID *Memory;
Memory = CoreAllocateBootServicesPool (AllocationSize);
SetMem (Memory, (Memory == NULL) ? 0 : AllocationSize, 0);
return Memory;
}
VOID *
CoreAllocateCopyPool (
IN UINTN AllocationSize,
IN VOID *Buffer
)
/*++
Routine Description:
Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool.
Arguments:
AllocationSize - Size to allocate.
Buffer - Specified buffer that will be copy to the allocated pool
Returns:
Pointer of the allocated pool.
--*/
{
VOID *Memory;
Memory = CoreAllocateBootServicesPool (AllocationSize);
CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize);
return Memory;
}
VOID *
CoreAllocateRuntimePool (
IN UINTN AllocationSize
)
/*++
Routine Description:
Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize.
Arguments:
AllocationSize - Size to allocate.
Returns:
Pointer of the allocated pool.
--*/
{
VOID *Memory;
CoreAllocatePool (EfiRuntimeServicesData, AllocationSize, &Memory);
return Memory;
}
VOID *
CoreAllocateRuntimeCopyPool (
IN UINTN AllocationSize,
IN VOID *Buffer
)
/*++
Routine Description:
Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool.
Arguments:
AllocationSize - Size to allocate.
Buffer - Specified buffer that will be copy to the allocated pool
Returns:
Pointer of the allocated pool.
--*/
{
VOID *Memory;
Memory = CoreAllocateRuntimePool (AllocationSize);
CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize);
return Memory;
}
//
// Lock Stuff
//
EFI_STATUS
CoreAcquireLockOrFail (
IN EFI_LOCK *Lock
)
/*++
Routine Description:
Initialize a basic mutual exclusion lock. Each lock
provides mutual exclusion access at it's task priority
level. Since there is no-premption (at any TPL) or
multiprocessor support, acquiring the lock only consists
of raising to the locks TPL.
Arguments:
Lock - The EFI_LOCK structure to initialize
Returns:
EFI_SUCCESS - Lock Owned.
EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned.
--*/
{
ASSERT (Lock != NULL);
ASSERT (Lock->Lock != EfiLockUninitialized);
if (Lock->Lock == EfiLockAcquired) {
//
// Lock is already owned, so bail out
//
return EFI_ACCESS_DENIED;
}
Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl);
Lock->Lock = EfiLockAcquired;
return EFI_SUCCESS;
}
VOID
CoreAcquireLock (
IN EFI_LOCK *Lock
)
/*++
Routine Description:
Raising to the task priority level of the mutual exclusion
lock, and then acquires ownership of the lock.
Arguments:
Lock - The lock to acquire
Returns:
Lock owned
--*/
{
ASSERT (Lock != NULL);
ASSERT (Lock->Lock == EfiLockReleased);
Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl);
Lock->Lock = EfiLockAcquired;
}
VOID
CoreReleaseLock (
IN EFI_LOCK *Lock
)
/*++
Routine Description:
Releases ownership of the mutual exclusion lock, and
restores the previous task priority level.
Arguments:
Lock - The lock to release
Returns:
Lock unowned
--*/
{
EFI_TPL Tpl;
ASSERT (Lock != NULL);
ASSERT (Lock->Lock == EfiLockAcquired);
Tpl = Lock->OwnerTpl;
Lock->Lock = EfiLockReleased;
CoreRestoreTpl (Tpl);
}
UINTN
CoreDevicePathSize (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
/*++
Routine Description:
Calculate the size of a whole device path.
Arguments:
DevicePath - The pointer to the device path data.
Returns:
Size of device path data structure..
--*/
{
EFI_DEVICE_PATH_PROTOCOL *Start;
if (DevicePath == NULL) {
return 0;
}
//
// Search for the end of the device path structure
//
Start = DevicePath;
while (!EfiIsDevicePathEnd (DevicePath)) {
DevicePath = EfiNextDevicePathNode (DevicePath);
}
//
// Compute the size and add back in the size of the end device path structure
//
return ((UINTN)DevicePath - (UINTN)Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL);
}
BOOLEAN
CoreIsDevicePathMultiInstance (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
/*++
Routine Description:
Return TRUE is this is a multi instance device path.
Arguments:
DevicePath - A pointer to a device path data structure.
Returns:
TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
instance.
--*/
{
EFI_DEVICE_PATH_PROTOCOL *Node;
if (DevicePath == NULL) {
return FALSE;
}
Node = DevicePath;
while (!EfiIsDevicePathEnd (Node)) {
if (EfiIsDevicePathEndInstance (Node)) {
return TRUE;
}
Node = EfiNextDevicePathNode (Node);
}
return FALSE;
}
EFI_DEVICE_PATH_PROTOCOL *
CoreDuplicateDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
/*++
Routine Description:
Duplicate a new device path data structure from the old one.
Arguments:
DevicePath - A pointer to a device path data structure.
Returns:
A pointer to the new allocated device path data.
Caller must free the memory used by DevicePath if it is no longer needed.
--*/
{
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
UINTN Size;
if (DevicePath == NULL) {
return NULL;
}
//
// Compute the size
//
Size = CoreDevicePathSize (DevicePath);
//
// Allocate space for duplicate device path
//
NewDevicePath = CoreAllocateCopyPool (Size, DevicePath);
return NewDevicePath;
}
EFI_DEVICE_PATH_PROTOCOL *
CoreAppendDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *Src1,
IN EFI_DEVICE_PATH_PROTOCOL *Src2
)
/*++
Routine Description:
Function is used to append a Src1 and Src2 together.
Arguments:
Src1 - A pointer to a device path data structure.
Src2 - A pointer to a device path data structure.
Returns:
A pointer to the new device path is returned.
NULL is returned if space for the new device path could not be allocated from pool.
It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
--*/
{
UINTN Size;
UINTN Size1;
UINTN Size2;
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath;
if (Src1 == NULL && Src2 == NULL) {
return NULL;
}
//
// Allocate space for the combined device path. It only has one end node of
// length EFI_DEVICE_PATH_PROTOCOL
//
Size1 = CoreDevicePathSize (Src1);
Size2 = CoreDevicePathSize (Src2);
Size = Size1 + Size2 - sizeof(EFI_DEVICE_PATH_PROTOCOL);
NewDevicePath = CoreAllocateCopyPool (Size, Src1);
if (NewDevicePath != NULL) {
//
// Over write Src1 EndNode and do the copy
//
SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath + (Size1 - sizeof(EFI_DEVICE_PATH_PROTOCOL)));
CopyMem (SecondDevicePath, Src2, Size2);
}
return NewDevicePath;
}
EFI_EVENT
CoreCreateProtocolNotifyEvent (
IN EFI_GUID *ProtocolGuid,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN VOID *NotifyContext,
OUT VOID **Registration,
IN BOOLEAN SignalFlag
)
/*++
Routine Description:
Create a protocol notification event and return it.
Arguments:
ProtocolGuid - Protocol to register notification event on.
NotifyTpl - Maximum TPL to signal the NotifyFunction.
NotifyFuncition - EFI notification routine.
NotifyContext - Context passed into Event when it is created.
Registration - Registration key returned from RegisterProtocolNotify().
SignalFlag - Boolean value to decide whether kick the event after register or not.
Returns:
The EFI_EVENT that has been registered to be signaled when a ProtocolGuid
is added to the system.
--*/
{
EFI_STATUS Status;
EFI_EVENT Event;
//
// Create the event
//
Status = CoreCreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
NotifyTpl,
NotifyFunction,
NotifyContext,
&Event
);
ASSERT_EFI_ERROR (Status);
//
// Register for protocol notifactions on this event
//
Status = CoreRegisterProtocolNotify (
ProtocolGuid,
Event,
Registration
);
ASSERT_EFI_ERROR (Status);
if (SignalFlag) {
//
// Kick the event so we will perform an initial pass of
// current installed drivers
//
CoreSignalEvent (Event);
}
return Event;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
/*++
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:
memdata.c
Abstract:
Global data used in memory service
Revision History
--*/
#include <DxeMain.h>
//
// MemoryLock - synchronizes access to the memory map and pool lists
//
EFI_LOCK gMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
//
// MemoryMap - the current memory map
//
LIST_ENTRY gMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap);
//
// MemoryLastConvert - the last memory descriptor used for a conversion request
//
MEMORY_MAP *gMemoryLastConvert;

View File

@@ -0,0 +1,613 @@
/*++
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:
pool.c
Abstract:
EFI Memory pool management
Revision History
--*/
#include <DxeMain.h>
#define POOL_FREE_SIGNATURE EFI_SIGNATURE_32('p','f','r','0')
typedef struct {
UINT32 Signature;
UINT32 Index;
LIST_ENTRY Link;
} POOL_FREE;
#define POOL_HEAD_SIGNATURE EFI_SIGNATURE_32('p','h','d','0')
typedef struct {
UINT32 Signature;
UINT32 Size;
EFI_MEMORY_TYPE Type;
UINTN Reserved;
CHAR8 Data[1];
} POOL_HEAD;
#define SIZE_OF_POOL_HEAD EFI_FIELD_OFFSET(POOL_HEAD,Data)
#define POOL_TAIL_SIGNATURE EFI_SIGNATURE_32('p','t','a','l')
typedef struct {
UINT32 Signature;
UINT32 Size;
} POOL_TAIL;
#define POOL_SHIFT 7
#define POOL_OVERHEAD (SIZE_OF_POOL_HEAD + sizeof(POOL_TAIL))
#define HEAD_TO_TAIL(a) \
((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL)));
#define SIZE_TO_LIST(a) ((a) >> POOL_SHIFT)
#define LIST_TO_SIZE(a) ((a+1) << POOL_SHIFT)
#define MAX_POOL_LIST SIZE_TO_LIST(DEFAULT_PAGE_ALLOCATION)
#define MAX_POOL_SIZE 0xffffff00
//
// Globals
//
#define POOL_SIGNATURE EFI_SIGNATURE_32('p','l','s','t')
typedef struct {
INTN Signature;
UINTN Used;
EFI_MEMORY_TYPE MemoryType;
LIST_ENTRY FreeList[MAX_POOL_LIST];
LIST_ENTRY Link;
} POOL;
POOL PoolHead[EfiMaxMemoryType];
LIST_ENTRY PoolHeadList;
//
//
//
VOID
CoreInitializePool (
VOID
)
/*++
Routine Description:
Called to initialize the pool.
Arguments:
None
Returns:
None
--*/
{
UINTN Type;
UINTN Index;
for (Type=0; Type < EfiMaxMemoryType; Type++) {
PoolHead[Type].Signature = 0;
PoolHead[Type].Used = 0;
PoolHead[Type].MemoryType = Type;
for (Index=0; Index < MAX_POOL_LIST; Index++) {
InitializeListHead (&PoolHead[Type].FreeList[Index]);
}
}
InitializeListHead (&PoolHeadList);
}
POOL *
LookupPoolHead (
IN EFI_MEMORY_TYPE MemoryType
)
/*++
Routine Description:
Look up pool head for specified memory type.
Arguments:
MemoryType - Memory type of which pool head is looked for
Returns:
Pointer of Corresponding pool head.
--*/
{
LIST_ENTRY *Link;
POOL *Pool;
UINTN Index;
if (MemoryType >= 0 && MemoryType < EfiMaxMemoryType) {
return &PoolHead[MemoryType];
}
if (MemoryType < 0) {
for (Link = PoolHeadList.ForwardLink; Link != &PoolHeadList; Link = Link->ForwardLink) {
Pool = CR(Link, POOL, Link, POOL_SIGNATURE);
if (Pool->MemoryType == MemoryType) {
return Pool;
}
}
Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL));
if (Pool == NULL) {
return NULL;
}
Pool->Signature = POOL_SIGNATURE;
Pool->Used = 0;
Pool->MemoryType = MemoryType;
for (Index=0; Index < MAX_POOL_LIST; Index++) {
InitializeListHead (&Pool->FreeList[Index]);
}
InsertHeadList (&PoolHeadList, &Pool->Link);
return Pool;
}
return NULL;
}
EFI_STATUS
EFIAPI
CoreAllocatePool (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
)
/*++
Routine Description:
Allocate pool of a particular type.
Arguments:
PoolType - Type of pool to allocate
Size - The amount of pool to allocate
Buffer - The address to return a pointer to the allocated pool
Returns:
EFI_INVALID_PARAMETER - PoolType not valid
EFI_OUT_OF_RESOURCES - Size exceeds max pool size or allocation failed.
EFI_SUCCESS - Pool successfully allocated.
--*/
{
EFI_STATUS Status;
//
// If it's not a valid type, fail it
//
if ((PoolType >= EfiMaxMemoryType && PoolType <= 0x7fffffff) ||
PoolType == EfiConventionalMemory) {
return EFI_INVALID_PARAMETER;
}
*Buffer = NULL;
//
// If size is too large, fail it
// Base on the EFI spec, return status of EFI_OUT_OF_RESOURCES
//
if (Size > MAX_POOL_SIZE) {
return EFI_OUT_OF_RESOURCES;
}
//
// Acquire the memory lock and make the allocation
//
Status = CoreAcquireLockOrFail (&gMemoryLock);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
*Buffer = CoreAllocatePoolI (PoolType, Size);
CoreReleaseMemoryLock ();
return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
}
VOID *
CoreAllocatePoolI (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size
)
/*++
Routine Description:
Internal function to allocate pool of a particular type.
Caller must have the memory lock held
Arguments:
PoolType - Type of pool to allocate
Size - The amount of pool to allocate
Returns:
The allocate pool, or NULL
--*/
{
POOL *Pool;
POOL_FREE *Free;
POOL_HEAD *Head;
POOL_TAIL *Tail;
CHAR8 *NewPage;
VOID *Buffer;
UINTN Index;
UINTN FSize;
UINTN offset;
UINTN Adjustment;
UINTN NoPages;
ASSERT_LOCKED (&gMemoryLock);
//
// Adjust the size by the pool header & tail overhead
//
//
// Adjusting the Size to be of proper alignment so that
// we don't get an unaligned access fault later when
// pool_Tail is being initialized
//
ALIGN_VARIABLE (Size, Adjustment);
Size += POOL_OVERHEAD;
Index = SIZE_TO_LIST(Size);
Pool = LookupPoolHead (PoolType);
if (Pool== NULL) {
return NULL;
}
Head = NULL;
//
// If allocation is over max size, just allocate pages for the request
// (slow)
//
if (Index >= MAX_POOL_LIST) {
NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;
NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);
Head = CoreAllocatePoolPages (PoolType, NoPages, DEFAULT_PAGE_ALLOCATION);
goto Done;
}
//
// If there's no free pool in the proper list size, go get some more pages
//
if (IsListEmpty (&Pool->FreeList[Index])) {
//
// Get another page
//
NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION);
if (NewPage == NULL) {
goto Done;
}
//
// Carve up new page into free pool blocks
//
offset = 0;
while (offset < DEFAULT_PAGE_ALLOCATION) {
ASSERT (Index < MAX_POOL_LIST);
FSize = LIST_TO_SIZE(Index);
while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
Free = (POOL_FREE *) &NewPage[offset];
Free->Signature = POOL_FREE_SIGNATURE;
Free->Index = (UINT32)Index;
InsertHeadList (&Pool->FreeList[Index], &Free->Link);
offset += FSize;
}
Index -= 1;
}
ASSERT (offset == DEFAULT_PAGE_ALLOCATION);
Index = SIZE_TO_LIST(Size);
}
//
// Remove entry from free pool list
//
Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);
RemoveEntryList (&Free->Link);
Head = (POOL_HEAD *) Free;
Done:
Buffer = NULL;
if (Head != NULL) {
//
// If we have a pool buffer, fill in the header & tail info
//
Head->Signature = POOL_HEAD_SIGNATURE;
Head->Size = (UINT32) Size;
Head->Type = (EFI_MEMORY_TYPE) PoolType;
Tail = HEAD_TO_TAIL (Head);
Tail->Signature = POOL_TAIL_SIGNATURE;
Tail->Size = (UINT32) Size;
Buffer = Head->Data;
DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);
DEBUG (
(EFI_D_POOL,
"AllcocatePoolI: Type %x, Addr %x (len %x) %,d\n",
PoolType,
Buffer,
Size - POOL_OVERHEAD,
Pool->Used)
);
//
// Account the allocation
//
Pool->Used += Size;
} else {
DEBUG ((EFI_D_ERROR | EFI_D_POOL, "AllocatePool: failed to allocate %d bytes\n", Size));
}
return Buffer;
}
EFI_STATUS
EFIAPI
CoreFreePool (
IN VOID *Buffer
)
/*++
Routine Description:
Frees pool.
Arguments:
Buffer - The allocated pool entry to free
Returns:
EFI_INVALID_PARAMETER - Buffer is not a valid value.
EFI_SUCCESS - Pool successfully freed.
--*/
{
EFI_STATUS Status;
if (NULL == Buffer) {
return EFI_INVALID_PARAMETER;
}
CoreAcquireMemoryLock ();
Status = CoreFreePoolI (Buffer);
CoreReleaseMemoryLock ();
return Status;
}
EFI_STATUS
CoreFreePoolI (
IN VOID *Buffer
)
/*++
Routine Description:
Internal function to free a pool entry.
Caller must have the memory lock held
Arguments:
Buffer - The allocated pool entry to free
Returns:
EFI_INVALID_PARAMETER - Buffer not valid
EFI_SUCCESS - Buffer successfully freed.
--*/
{
POOL *Pool;
POOL_HEAD *Head;
POOL_TAIL *Tail;
POOL_FREE *Free;
UINTN Index;
UINTN NoPages;
UINTN Size;
CHAR8 *NewPage;
UINTN FSize;
UINTN offset;
BOOLEAN AllFree;
ASSERT(NULL != Buffer);
//
// Get the head & tail of the pool entry
//
Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);
ASSERT(NULL != Head);
if (Head->Signature != POOL_HEAD_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
Tail = HEAD_TO_TAIL (Head);
ASSERT(NULL != Tail);
//
// Debug
//
ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);
ASSERT (Head->Size == Tail->Size);
ASSERT_LOCKED (&gMemoryLock);
if (Tail->Signature != POOL_TAIL_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
if (Head->Size != Tail->Size) {
return EFI_INVALID_PARAMETER;
}
//
// Determine the pool type and account for it
//
Size = Head->Size;
Pool = LookupPoolHead (Head->Type);
if (Pool == NULL) {
return EFI_INVALID_PARAMETER;
}
Pool->Used -= Size;
DEBUG ((EFI_D_POOL, "FreePool: %x (len %x) %,d\n", Head->Data, Head->Size - POOL_OVERHEAD, Pool->Used));
//
// Determine the pool list
//
Index = SIZE_TO_LIST(Size);
DEBUG_CLEAR_MEMORY (Head, Size);
//
// If it's not on the list, it must be pool pages
//
if (Index >= MAX_POOL_LIST) {
//
// Return the memory pages back to free memory
//
NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;
NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);
CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);
} else {
//
// Put the pool entry onto the free pool list
//
Free = (POOL_FREE *) Head;
ASSERT(NULL != Free);
Free->Signature = POOL_FREE_SIGNATURE;
Free->Index = (UINT32)Index;
InsertHeadList (&Pool->FreeList[Index], &Free->Link);
//
// See if all the pool entries in the same page as Free are freed pool
// entries
//
NewPage = (CHAR8 *)((UINTN)Free & ~((DEFAULT_PAGE_ALLOCATION) -1));
Free = (POOL_FREE *) &NewPage[0];
ASSERT(NULL != Free);
if (Free->Signature == POOL_FREE_SIGNATURE) {
Index = Free->Index;
AllFree = TRUE;
offset = 0;
while ((offset < DEFAULT_PAGE_ALLOCATION) && (AllFree)) {
FSize = LIST_TO_SIZE(Index);
while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
Free = (POOL_FREE *) &NewPage[offset];
ASSERT(NULL != Free);
if (Free->Signature != POOL_FREE_SIGNATURE) {
AllFree = FALSE;
}
offset += FSize;
}
Index -= 1;
}
if (AllFree) {
//
// All of the pool entries in the same page as Free are free pool
// entries
// Remove all of these pool entries from the free loop lists.
//
Free = (POOL_FREE *) &NewPage[0];
ASSERT(NULL != Free);
Index = Free->Index;
offset = 0;
while (offset < DEFAULT_PAGE_ALLOCATION) {
FSize = LIST_TO_SIZE(Index);
while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
Free = (POOL_FREE *) &NewPage[offset];
ASSERT(NULL != Free);
RemoveEntryList (&Free->Link);
offset += FSize;
}
Index -= 1;
}
//
// Free the page
//
CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION));
}
}
}
//
// If this is an OS specific memory type, then check to see if the last
// portion of that memory type has been freed. If it has, then free the
// list entry for that memory type
//
if (Pool->MemoryType < 0 && Pool->Used == 0) {
RemoveEntryList (&Pool->Link);
CoreFreePoolI (Pool);
}
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,260 @@
/*++
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:
DebugImageInfo.c
Abstract:
Support functions for managing debug image info table when loading and unloading
images.
--*/
#include <DxeMain.h>
static EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugInfoTableHeader = {
0, // volatile UINT32 UpdateStatus;
0, // UINT32 TableSize;
NULL // EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
};
static EFI_SYSTEM_TABLE_POINTER *mDebugTable = NULL;
VOID
CoreInitializeDebugImageInfoTable (
VOID
)
/*++
Routine Description:
Creates and initializes the DebugImageInfo Table. Also creates the configuration
table and registers it into the system table.
Arguments:
None
Returns:
NA
Notes:
This function allocates memory, frees it, and then allocates memory at an
address within the initial allocation. Since this function is called early
in DXE core initialization (before drivers are dispatched), this should not
be a problem.
--*/
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS Mem;
UINTN NumberOfPages;
//
// Allocate boot services memory for the structure. It's required to be aligned on
// a 4M boundary, so allocate a 4M block (plus what we require), free it up, calculate
// a 4M aligned address within the memory we just freed, and then allocate memory at that
// address for our initial structure.
//
NumberOfPages = FOUR_MEG_PAGES + EFI_SIZE_TO_PAGES(sizeof (EFI_SYSTEM_TABLE_POINTER));
Status = CoreAllocatePages (AllocateAnyPages, EfiBootServicesData, NumberOfPages , &Mem);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR(Status)) {
return;
}
Status = CoreFreePages (Mem, NumberOfPages);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR(Status)) {
return;
}
//
// Now get a 4M aligned address within the memory range we were given.
// Then allocate memory at that address
//
Mem = (Mem + FOUR_MEG_MASK) & (~FOUR_MEG_MASK);
Status = CoreAllocatePages (AllocateAddress, EfiBootServicesData, NumberOfPages - FOUR_MEG_PAGES, &Mem);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR(Status)) {
return;
}
//
// We now have a 4M aligned page allocated, so fill in the data structure.
// Ideally we would update the CRC now as well, but the service may not yet be available.
// See comments in the CoreUpdateDebugTableCrc32() function below for details.
//
mDebugTable = (EFI_SYSTEM_TABLE_POINTER *)(UINTN)Mem;
mDebugTable->Signature = EFI_SYSTEM_TABLE_SIGNATURE;
mDebugTable->EfiSystemTableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) gST;
mDebugTable->Crc32 = 0;
Status = CoreInstallConfigurationTable (&gEfiDebugImageInfoTableGuid, &mDebugInfoTableHeader);
ASSERT_EFI_ERROR (Status);
}
VOID
CoreUpdateDebugTableCrc32 (
VOID
)
/*++
Routine Description:
Update the CRC32 in the Debug Table.
Since the CRC32 service is made available by the Runtime driver, we have to
wait for the Runtime Driver to be installed before the CRC32 can be computed.
This function is called elsewhere by the core when the runtime architectural
protocol is produced.
Arguments:
None
Returns:
NA
--*/
{
ASSERT(mDebugTable != NULL);
mDebugTable->Crc32 = 0;
gBS->CalculateCrc32 ((VOID *)mDebugTable, sizeof (EFI_SYSTEM_TABLE_POINTER), &mDebugTable->Crc32);
}
VOID
CoreNewDebugImageInfoEntry (
IN UINTN ImageInfoType,
IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
IN EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates
the table if it's not large enough to accomidate another entry.
Arguments:
ImageInfoType - type of debug image information
LoadedImage - pointer to the loaded image protocol for the image being loaded
ImageHandle - image handle for the image being loaded
Returns:
NA
--*/
{
EFI_DEBUG_IMAGE_INFO *Table;
EFI_DEBUG_IMAGE_INFO *NewTable;
UINTN Index;
UINTN MaxTableIndex;
UINTN TableSize;
//
// Set the flag indicating that we're in the process of updating the table.
//
mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
MaxTableIndex = mDebugInfoTableHeader.TableSize;
for (Index = 0; Index < MaxTableIndex; Index++) {
if (Table[Index].NormalImage == NULL) {
//
// We have found a free entry so exit the loop
//
break;
}
}
if (Index == MaxTableIndex) {
//
// Table is full, so re-allocate another page for a larger table...
//
TableSize = MaxTableIndex * EFI_DEBUG_TABLE_ENTRY_SIZE;
NewTable = CoreAllocateZeroBootServicesPool (TableSize + EFI_PAGE_SIZE);
if (NewTable == NULL) {
mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
return;
}
//
// Copy the old table into the new one
//
CopyMem (NewTable, Table, TableSize);
//
// Free the old table
//
CoreFreePool (Table);
//
// Update the table header
//
Table = NewTable;
mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
mDebugInfoTableHeader.TableSize += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
}
//
// Allocate data for new entry
//
Table[Index].NormalImage = CoreAllocateZeroBootServicesPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
if (Table[Index].NormalImage != NULL) {
//
// Update the entry
//
Table[Index].NormalImage->ImageInfoType = (UINT32) ImageInfoType;
Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage;
Table[Index].NormalImage->ImageHandle = ImageHandle;
}
mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
}
VOID
CoreRemoveDebugImageInfoEntry (
EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Removes and frees an entry from the DebugImageInfo Table.
Arguments:
ImageHandle - image handle for the image being unloaded
Returns:
NA
--*/
{
EFI_DEBUG_IMAGE_INFO *Table;
UINTN Index;
mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
for (Index = 0; Index < mDebugInfoTableHeader.TableSize; Index++) {
if (Table[Index].NormalImage != NULL && Table[Index].NormalImage->ImageHandle == ImageHandle) {
//
// Found a match. Free up the record, then NULL the pointer to indicate the slot
// is free.
//
CoreFreePool (Table[Index].NormalImage);
Table[Index].NormalImage = NULL;
break;
}
}
mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
}

View File

@@ -0,0 +1,214 @@
/*++
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:
InstallConfigurationTable.c
Abstract:
Tiano Miscellaneous Services InstallConfigurationTable service
--*/
#include <DxeMain.h>
#define CONFIG_TABLE_SIZE_INCREASED 0x10
UINTN mSystemTableAllocateSize = 0;
EFI_STATUS
CoreGetConfigTable (
IN EFI_GUID *Guid,
OUT VOID **Table
)
/*++
Routine Description:
Find a config table by name in system table's ConfigurationTable.
Arguments:
Guid - The table name to look for
Table - Pointer of the config table
Returns:
EFI_NOT_FOUND - Could not find the table in system table's ConfigurationTable.
EFI_SUCCESS - Table successfully found.
--*/
{
UINTN Index;
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (CompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) {
*Table = gST->ConfigurationTable[Index].VendorTable;
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
EFIAPI
CoreInstallConfigurationTable (
IN EFI_GUID *Guid,
IN VOID *Table
)
/*++
Routine Description:
Boot Service called to add, modify, or remove a system configuration table from
the EFI System Table.
Arguments:
Guid - Pointer to the GUID for the entry to add, update, or remove
Table - Pointer to the configuration table for the entry to add, update, or
remove, may be NULL.
Returns:
EFI_SUCCESS Guid, Table pair added, updated, or removed.
EFI_INVALID_PARAMETER Input GUID not valid.
EFI_NOT_FOUND Attempted to delete non-existant entry
EFI_OUT_OF_RESOURCES Not enough memory available
--*/
{
UINTN Index;
EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
//
// If Guid is NULL, then this operation cannot be performed
//
if (Guid == NULL) {
return EFI_INVALID_PARAMETER;
}
EfiConfigurationTable = gST->ConfigurationTable;
//
// Search all the table for an entry that matches Guid
//
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (CompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) {
break;
}
}
if (Index < gST->NumberOfTableEntries) {
//
// A match was found, so this is either a modify or a delete operation
//
if (Table != NULL) {
//
// If Table is not NULL, then this is a modify operation.
// Modify the table enty and return.
//
gST->ConfigurationTable[Index].VendorTable = Table;
return EFI_SUCCESS;
}
//
// A match was found and Table is NULL, so this is a delete operation.
//
gST->NumberOfTableEntries--;
//
// Copy over deleted entry
//
CopyMem (
&(EfiConfigurationTable[Index]),
&(gST->ConfigurationTable[Index + 1]),
(gST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
);
} else {
//
// No matching GUIDs were found, so this is an add operation.
//
if (Table == NULL) {
//
// If Table is NULL on an add operation, then return an error.
//
return EFI_NOT_FOUND;
}
//
// Assume that Index == gST->NumberOfTableEntries
//
if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) {
//
// Allocate a table with one additional entry.
//
mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
EfiConfigurationTable = CoreAllocateRuntimePool (mSystemTableAllocateSize);
if (EfiConfigurationTable == NULL) {
//
// If a new table could not be allocated, then return an error.
//
return EFI_OUT_OF_RESOURCES;
}
if (gST->ConfigurationTable != NULL) {
//
// Copy the old table to the new table.
//
CopyMem (
EfiConfigurationTable,
gST->ConfigurationTable,
Index * sizeof (EFI_CONFIGURATION_TABLE)
);
//
// Free Old Table
//
CoreFreePool (gST->ConfigurationTable);
}
//
// Update System Table
//
gST->ConfigurationTable = EfiConfigurationTable;
}
//
// Fill in the new entry
//
CopyMem ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid, sizeof (EFI_GUID));
EfiConfigurationTable[Index].VendorTable = Table;
//
// This is an add operation, so increment the number of table entries
//
gST->NumberOfTableEntries++;
}
//
// Fix up the CRC-32 in the EFI System Table
//
CalculateEfiHdrCrc (&gST->Hdr);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,83 @@
/*++
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:
SetWatchdogTimer.c
Abstract:
Tiano Miscellaneous Services SetWatchdogTimer service implementation
--*/
#include <DxeMain.h>
#define WATCHDOG_TIMER_CALIBRATE_PER_SECOND 10000000
EFI_STATUS
EFIAPI
CoreSetWatchdogTimer (
IN UINTN Timeout,
IN UINT64 WatchdogCode,
IN UINTN DataSize,
IN CHAR16 *WatchdogData OPTIONAL
)
/*++
Routine Description:
Sets the system's watchdog timer.
Arguments:
Timeout The number of seconds. Zero disables the timer.
///////following three parameters are left for platform specific using
WatchdogCode The numberic code to log. 0x0 to 0xffff are firmware
DataSize Size of the optional data
WatchdogData Optional Null terminated unicode string followed by binary
data.
Returns:
EFI_SUCCESS Timeout has been set
EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet
EFI_UNSUPPORTED System does not have a timer (currently not used)
EFI_DEVICE_ERROR Could not complete due to hardware error
--*/
{
EFI_STATUS Status;
//
// Check our architectural protocol
//
if (gWatchdogTimer == NULL) {
return EFI_NOT_AVAILABLE_YET;
}
//
// Attempt to set the timeout
//
Status = gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, MultU64x32 (Timeout, WATCHDOG_TIMER_CALIBRATE_PER_SECOND));
//
// Check for errors
//
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,82 @@
/*++
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:
Stall.c
Abstract:
Tiano Miscellaneous Services Stall service implementation
--*/
//
// Include statements
//
#include <DxeMain.h>
EFI_STATUS
EFIAPI
CoreStall (
IN UINTN Microseconds
)
/*++
Routine Description:
Introduces a fine-grained stall.
Arguments:
Microseconds The number of microseconds to stall execution
Returns:
EFI_SUCCESS - Execution was stalled for at least the requested amount
of microseconds.
EFI_NOT_AVAILABLE_YET - gMetronome is not available yet
--*/
{
UINT32 Counter;
UINT32 Remainder;
if (gMetronome == NULL) {
return EFI_NOT_AVAILABLE_YET;
}
//
// Calculate the number of ticks by dividing the number of microseconds by
// the TickPeriod.
// Calcullation is based on 100ns unit.
//
Counter = (UINT32) DivU64x32Remainder (
Microseconds * 10,
gMetronome->TickPeriod,
&Remainder
);
//
// Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
// periods, thus attempting to ensure Microseconds of stall time.
//
if (Remainder != 0) {
Counter++;
}
gMetronome->WaitForTick (gMetronome, Counter);
return EFI_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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="DxeMain"><!--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="Core\Dxe"/>
<property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
<property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
<target name="DxeMain">
<GenBuild baseName="DxeMain" mbdFilename="${MODULE_DIR}\DxeMain.mbd" msaFilename="${MODULE_DIR}\DxeMain.msa"/>
</target>
<target depends="DxeMain_clean" name="clean"/>
<target depends="DxeMain_cleanall" name="cleanall"/>
<target name="DxeMain_clean">
<OutputDirSetup baseName="DxeMain" mbdFilename="${MODULE_DIR}\DxeMain.mbd" msaFilename="${MODULE_DIR}\DxeMain.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\DxeMain_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\DxeMain_build.xml" target="clean"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
</target>
<target name="DxeMain_cleanall">
<OutputDirSetup baseName="DxeMain" mbdFilename="${MODULE_DIR}\DxeMain.mbd" msaFilename="${MODULE_DIR}\DxeMain.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\DxeMain_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\DxeMain_build.xml" target="cleanall"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}"/>
<delete dir="${DEST_DIR_DEBUG}"/>
<delete>
<fileset dir="${BIN_DIR}" includes="**DxeMain*"/>
</delete>
</target>
</project>

View File

@@ -0,0 +1,209 @@
/*++
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:
exec.h
Abstract:
EFI Event support
--*/
#ifndef _EXEC_H_
#define _EXEC_H_
#define VALID_TPL(a) ((a) <= EFI_TPL_HIGH_LEVEL)
//
// EFI_EVENT
//
#define EVENT_SIGNATURE EFI_SIGNATURE_32('e','v','n','t')
typedef struct {
UINTN Signature;
UINT32 Type;
UINT32 SignalCount;
//
// Entry if the event is registered to be signalled
//
LIST_ENTRY SignalLink;
//
// Notification information for this event
//
EFI_TPL NotifyTpl;
EFI_EVENT_NOTIFY NotifyFunction;
VOID *NotifyContext;
EFI_GUID EventGroup;
LIST_ENTRY NotifyLink;
BOOLEAN ExFlag;
//
// A list of all runtime events
//
LIST_ENTRY RuntimeLink;
//
// Information by event type
//
union {
//
// For timer events
//
struct {
LIST_ENTRY Link;
UINT64 TriggerTime;
UINT64 Period;
} Timer;
} u;
} IEVENT;
//
// Internal prototypes
//
VOID
CoreDispatchEventNotifies (
IN EFI_TPL Priority
)
/*++
Routine Description:
Dispatches all pending events.
Arguments:
Priority - The task priority level of event notifications to dispatch
Returns:
None
--*/
;
UINTN
CoreHighestSetBit (
IN UINTN Number
)
/*++
Routine Description:
Return the highest set bit
Arguments:
Number - The value to check
Returns:
Bit position of the highest set bit
--*/
;
BOOLEAN
GetInterruptState (
VOID
)
/*++
Routine Description:
Disables CPU interrupts.
Arguments:
This - Protocol instance structure
State - Pointer to the CPU's current interrupt state
Returns:
EFI_SUCCESS - If interrupts were disabled in the CPU.
EFI_INVALID_PARAMETER - State is NULL.
--*/
;
//
// Exported functions
//
VOID
CoreEventVirtualAddressFixup (
VOID
)
/*++
Routine Description:
A function out of date, should be removed.
Arguments:
None
Returns:
None
--*/
;
VOID
CoreInitializeTimer (
VOID
)
/*++
Routine Description:
Initializes timer support
Arguments:
None
Returns:
None
--*/
;
//
// extern data declarations
//
extern EFI_LOCK gEventQueueLock;
extern UINTN gEventPending;
extern LIST_ENTRY gEventQueue[];
extern LIST_ENTRY gEventSignalQueue;
extern UINT8 gHSB[];
extern LIST_ENTRY mRuntimeEventList;
#endif

View File

@@ -0,0 +1,51 @@
/*++
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:
gcd.h
Abstract:
Revision History
--*/
#ifndef _GCD_H
#define _GCD_H
//
// GCD Operations
//
#define GCD_MEMORY_SPACE_OPERATION 0x20
#define GCD_IO_SPACE_OPERATION 0x40
#define GCD_ADD_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 0)
#define GCD_ALLOCATE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 1)
#define GCD_FREE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 2)
#define GCD_REMOVE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 3)
#define GCD_SET_ATTRIBUTES_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 4)
#define GCD_ADD_IO_OPERATION (GCD_IO_SPACE_OPERATION | 0)
#define GCD_ALLOCATE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 1)
#define GCD_FREE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 2)
#define GCD_REMOVE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 3)
//
// The data structure used to convert from GCD attributes to EFI Memory Map attributes
//
typedef struct {
UINT64 Attribute;
UINT64 Capability;
BOOLEAN Memory;
} GCD_ATTRIBUTE_CONVERSION_ENTRY;
#endif

View File

@@ -0,0 +1,337 @@
/*++
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:
hand.h
Abstract:
EFI internal protocol definitions
Revision History
--*/
#ifndef _HAND_H_
#define _HAND_H_
//
// IHANDLE - contains a list of protocol handles
//
#define EFI_HANDLE_SIGNATURE EFI_SIGNATURE_32('h','n','d','l')
typedef struct {
UINTN Signature;
LIST_ENTRY AllHandles; // All handles list of IHANDLE
LIST_ENTRY Protocols; // List of PROTOCOL_INTERFACE's for this handle
UINTN LocateRequest; //
UINT64 Key; // The Handle Database Key value when this handle was last created or modified
} IHANDLE;
#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE)
//
// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol
// database. Each handler that supports this protocol is listed, along
// with a list of registered notifies.
//
#define PROTOCOL_ENTRY_SIGNATURE EFI_SIGNATURE_32('p','r','t','e')
typedef struct {
UINTN Signature;
LIST_ENTRY AllEntries; // All entries
EFI_GUID ProtocolID; // ID of the protocol
LIST_ENTRY Protocols; // All protocol interfaces
LIST_ENTRY Notify; // Registerd notification handlers
} PROTOCOL_ENTRY;
//
// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked
// with a protocol interface structure
//
#define PROTOCOL_INTERFACE_SIGNATURE EFI_SIGNATURE_32('p','i','f','c')
typedef struct {
UINTN Signature;
EFI_HANDLE Handle; // Back pointer
LIST_ENTRY Link; // Link on IHANDLE.Protocols
LIST_ENTRY ByProtocol; // Link on PROTOCOL_ENTRY.Protocols
PROTOCOL_ENTRY *Protocol; // The protocol ID
VOID *Interface; // The interface value
LIST_ENTRY OpenList; // OPEN_PROTOCOL_DATA list.
UINTN OpenListCount;
EFI_HANDLE ControllerHandle;
} PROTOCOL_INTERFACE;
#define OPEN_PROTOCOL_DATA_SIGNATURE EFI_SIGNATURE_32('p','o','d','l')
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
EFI_HANDLE AgentHandle;
EFI_HANDLE ControllerHandle;
UINT32 Attributes;
UINT32 OpenCount;
} OPEN_PROTOCOL_DATA;
//
// PROTOCOL_NOTIFY - used for each register notification for a protocol
//
#define PROTOCOL_NOTIFY_SIGNATURE EFI_SIGNATURE_32('p','r','t','n')
typedef struct {
UINTN Signature;
PROTOCOL_ENTRY *Protocol;
LIST_ENTRY Link; // All notifications for this protocol
EFI_EVENT Event; // Event to notify
LIST_ENTRY *Position; // Last position notified
} PROTOCOL_NOTIFY;
//
// Internal prototypes
//
PROTOCOL_ENTRY *
CoreFindProtocolEntry (
IN EFI_GUID *Protocol,
IN BOOLEAN Create
)
/*++
Routine Description:
Finds the protocol entry for the requested protocol.
The gProtocolDatabaseLock must be owned
Arguments:
Protocol - The ID of the protocol
Create - Create a new entry if not found
Returns:
Protocol entry
--*/
;
VOID
CoreNotifyProtocolEntry (
IN PROTOCOL_ENTRY *ProtEntry
)
/*++
Routine Description:
Signal event for every protocol in protocol entry.
Arguments:
ProtEntry - Protocol entry
Returns:
--*/
;
PROTOCOL_INTERFACE *
CoreFindProtocolInterface (
IN IHANDLE *Handle,
IN EFI_GUID *Protocol,
IN VOID *Interface
)
/*++
Routine Description:
Finds the protocol instance for the requested handle and protocol.
Note: This function doesn't do parameters checking, it's caller's responsibility
to pass in valid parameters.
Arguments:
Handle - The handle to search the protocol on
Protocol - GUID of the protocol
Interface - The interface for the protocol being searched
Returns:
Protocol instance (NULL: Not found)
--*/
;
PROTOCOL_INTERFACE *
CoreRemoveInterfaceFromProtocol (
IN IHANDLE *Handle,
IN EFI_GUID *Protocol,
IN VOID *Interface
)
/*++
Routine Description:
Removes Protocol from the protocol list (but not the handle list).
Arguments:
Handle - The handle to remove protocol on.
Protocol - GUID of the protocol to be moved
Interface - The interface of the protocol
Returns:
Protocol Entry
--*/
;
EFI_STATUS
CoreUnregisterProtocolNotify (
IN EFI_EVENT Event
)
/*++
Routine Description:
Removes all the events in the protocol database that match Event.
Arguments:
Event - The event to search for in the protocol database.
Returns:
EFI_SUCCESS when done searching the entire database.
--*/
;
EFI_STATUS
CoreDisconnectControllersUsingProtocolInterface (
IN EFI_HANDLE UserHandle,
IN PROTOCOL_INTERFACE *Prot
)
/*++
Routine Description:
Attempts to disconnect all drivers that are using the protocol interface being queried.
If failed, reconnect all drivers disconnected.
Note: This function doesn't do parameters checking, it's caller's responsibility
to pass in valid parameters.
Arguments:
UserHandle - The handle on which the protocol is installed
Prot - The protocol to disconnect drivers from
Returns:
EFI_SUCCESS - Drivers using the protocol interface are all disconnected
EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers
--*/
;
VOID
CoreAcquireProtocolLock (
VOID
)
/*++
Routine Description:
Acquire lock on gProtocolDatabaseLock.
Arguments:
None
Returns:
None
--*/
;
VOID
CoreReleaseProtocolLock (
VOID
)
/*++
Routine Description:
Release lock on gProtocolDatabaseLock.
Arguments:
None
Returns:
None
--*/
;
EFI_STATUS
CoreValidateHandle (
IN EFI_HANDLE UserHandle
)
/*++
Routine Description:
Check whether a handle is a valid EFI_HANDLE
Arguments:
UserHandle - The handle to check
Returns:
EFI_INVALID_PARAMETER - The handle is NULL or not a valid EFI_HANDLE.
EFI_SUCCESS - The handle is valid EFI_HANDLE.
--*/
;
//
// Externs
//
extern EFI_LOCK gProtocolDatabaseLock;
extern LIST_ENTRY gHandleList;
extern UINT64 gHandleDatabaseKey;
#endif

View File

@@ -0,0 +1,227 @@
/*++
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:
imem.h
Abstract:
Head file to imem.h
Revision History
--*/
#ifndef _IMEM_H_
#define _IMEM_H_
#if defined (MDE_CPU_IPF)
//
// For Itanium machines make the default allocations 8K aligned
//
#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE * 2)
#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE * 2)
#else
//
// For genric EFI machines make the default allocations 4K aligned
//
#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE)
#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE)
#endif
//
// MEMORY_MAP_ENTRY
//
#define MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('m','m','a','p')
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
BOOLEAN FromPool;
EFI_MEMORY_TYPE Type;
UINT64 Start;
UINT64 End;
UINT64 VirtualStart;
UINT64 Attribute;
} MEMORY_MAP;
//
// Internal prototypes
//
VOID *
CoreAllocatePoolPages (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN NumberOfPages,
IN UINTN Alignment
)
/*++
Routine Description:
Internal function. Used by the pool functions to allocate pages
to back pool allocation requests.
Arguments:
PoolType - The type of memory for the new pool pages
NumberOfPages - No of pages to allocate
Alignment - Bits to align.
Returns:
The allocated memory, or NULL
--*/
;
VOID
CoreFreePoolPages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
)
/*++
Routine Description:
Internal function. Frees pool pages allocated via AllocatePoolPages ()
Arguments:
Memory - The base address to free
NumberOfPages - The number of pages to free
Returns:
None
--*/
;
VOID *
CoreAllocatePoolI (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size
)
/*++
Routine Description:
Internal function to allocate pool of a particular type.
Caller must have the memory lock held
Arguments:
PoolType - Type of pool to allocate
Size - The amount of pool to allocate
Returns:
The allocate pool, or NULL
--*/
;
EFI_STATUS
CoreFreePoolI (
IN VOID *Buffer
)
/*++
Routine Description:
Internal function to free a pool entry.
Caller must have the memory lock held
Arguments:
Buffer - The allocated pool entry to free
Returns:
EFI_INVALID_PARAMETER - Buffer not valid
EFI_SUCCESS - Buffer successfully freed.
--*/
;
VOID
CoreAcquireMemoryLock (
VOID
)
/*++
Routine Description:
Enter critical section by gaining lock on gMemoryLock
Arguments:
None
Returns:
None
--*/
;
VOID
CoreReleaseMemoryLock (
VOID
)
/*++
Routine Description:
Exit critical section by releasing lock on gMemoryLock
Arguments:
None
Returns:
None
--*/
;
//
// Internal Global data
//
extern EFI_LOCK gMemoryLock;
extern LIST_ENTRY gMemoryMap;
extern MEMORY_MAP *gMemoryLastConvert;
extern LIST_ENTRY mGcdMemorySpaceMap;
#endif

View File

@@ -0,0 +1,29 @@
/*++
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:
DxeIpl.dxs
Abstract:
Dependency expression file for DXE Initial Program Loader PEIM.
--*/
#include <AutoGen.h>
#include <PeimDepex.h>
DEPENDENCY_START
EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID
DEPENDENCY_END

View File

@@ -0,0 +1,146 @@
/*++
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:
DxeIpl.h
Abstract:
--*/
#ifndef __PEI_DXEIPL_H__
#define __PEI_DXEIPL_H__
#define STACK_SIZE 0x20000
#define BSP_STORE_SIZE 0x4000
extern BOOLEAN gInMemory;
VOID
SwitchIplStacks (
VOID *EntryPoint,
UINTN Parameter1,
UINTN Parameter2,
VOID *NewStack,
VOID *NewBsp
)
;
EFI_STATUS
PeiFindFile (
IN UINT8 Type,
IN UINT16 SectionType,
OUT EFI_GUID *FileName,
OUT VOID **Pe32Data
)
;
EFI_STATUS
PeiLoadFile (
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
IN VOID *Pe32Data,
OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
OUT UINT64 *ImageSize,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint
)
;
EFI_STATUS
CreateArchSpecificHobs (
OUT EFI_PHYSICAL_ADDRESS *BspStore
)
;
EFI_STATUS
GetImageReadFunction (
IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
;
EFI_STATUS
PeiImageRead (
IN VOID *FileHandle,
IN UINTN FileOffset,
IN OUT UINTN *ReadSize,
OUT VOID *Buffer
)
;
EFI_STATUS
EFIAPI
DxeIplLoadFile (
IN EFI_PEI_FV_FILE_LOADER_PPI *This,
IN EFI_FFS_FILE_HEADER *FfsHeader,
OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
OUT UINT64 *ImageSize,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint
);
EFI_STATUS
ShadowDxeIpl (
IN EFI_FFS_FILE_HEADER *DxeIpl,
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader
);
EFI_STATUS
EFIAPI
DxeLoadCore (
IN EFI_DXE_IPL_PPI *This,
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_HOB_POINTERS HobList
);
EFI_STATUS
PeiProcessFile (
IN UINT16 SectionType,
IN EFI_FFS_FILE_HEADER *FfsFileHeader,
OUT VOID **Pe32Data
);
EFI_STATUS
EFIAPI
PeimInitializeDxeIpl (
IN EFI_FFS_FILE_HEADER *FfsHeader,
IN EFI_PEI_SERVICES **PeiServices
);
EFI_STATUS
PeiLoadx64File (
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
IN VOID *Pe32Data,
IN EFI_MEMORY_TYPE MemoryType,
OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
OUT UINT64 *ImageSize,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint
)
;
EFI_PHYSICAL_ADDRESS
CreateIdentityMappingPageTables (
IN UINT32 NumberOfProcessorPhysicalAddressBits
)
;
VOID
ActivateLongMode (
IN EFI_PHYSICAL_ADDRESS PageTables,
IN EFI_PHYSICAL_ADDRESS HobStart,
IN EFI_PHYSICAL_ADDRESS Stack,
IN EFI_PHYSICAL_ADDRESS CodeEntryPoint1,
IN EFI_PHYSICAL_ADDRESS CodeEntryPoint2
);
VOID
LoadGo64Gdt();
#endif

View File

@@ -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.
-->
<ModuleBuildDescription 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">
<MbdHeader>
<BaseName>DxeIpl</BaseName>
<Guid>86D70125-BAA3-4296-A62F-602BEBBB9081</Guid>
<Version>EDK_RELEASE_VERSION 0x00020000</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-22 18:54</Modified>
</MbdHeader>
<Libraries>
<Library>PeimEntryPoint</Library>
<Library>PeiMemoryLib</Library>
<Library>PeiCoreLib</Library>
<Library>PeiServicesTablePointerLib</Library>
<Library>PeiHobLib</Library>
<Library>BaseCacheMaintenanceLib</Library>
<Library>BaseUefiTianoDecompressLib</Library>
<Library>BaseCustomDecompressLibNull</Library>
<Library>PeiReportStatusCodeLib</Library>
<Library>BaseDebugLibReportStatusCode</Library>
<Library>BaseLib</Library>
<Library>PeiMemoryAllocationLib</Library>
<Arch ArchType="IA32">
<Library OverrideID="8888">EdkPeCoffLoaderLib</Library>
<Library OverrideID="8888">BasePeCoffLib</Library>
</Arch>
<Arch ArchType="X64">
<Library>EdkPeCoffLoaderLib</Library>
<Library>BasePeCoffLib</Library>
</Arch>
<Arch ArchType="IPF">
<Library>EdkPeCoffLoaderLib</Library>
<Library>BasePeCoffLib</Library>
</Arch>
<Arch ArchType="EBC">
<Library>EdkPeCoffLoaderLib</Library>
<Library>BasePeCoffLib</Library>
</Arch>
</Libraries>
<BuildOptions ToolChain="MSFT">
<ImageEntryPoint>_ModuleEntryPoint</ImageEntryPoint>
</BuildOptions>
</ModuleBuildDescription>

View File

@@ -0,0 +1,129 @@
<?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.
-->
<ModuleSurfaceArea 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">
<MsaHeader>
<BaseName>DxeIpl</BaseName>
<ModuleType>PEIM</ModuleType>
<ComponentType>PE32_PEIM</ComponentType>
<Guid>86D70125-BAA3-4296-A62F-602BEBBB9081</Guid>
<Version>EDK_RELEASE_VERSION 0x00020000</Version>
<Abstract>Component description file for DxeIpl module</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>EFI_SPECIFICATION_VERSION 0x00000000</Specification>
<Created>2006-03-12 17:09</Created>
<Updated>2006-03-22 18:54</Updated>
</MsaHeader>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeimEntryPoint</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">CacheMaintenanceLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">EdkPeCoffLoaderLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">TianoDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">CustomDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeiServicesTablePointerLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>DxeLoad.c</Filename>
<Filename>DxeIpl.dxs</Filename>
<Arch ArchType="IA32">
<Filename>ia32\ImageRead.c</Filename>
<Filename>ia32\DxeLoadFunc.c</Filename>
</Arch>
<Arch ArchType="X64">
<Filename>ia32\ImageRead.c</Filename>
<Filename>ia32\DxeLoadFunc.c</Filename>
</Arch>
<Arch ArchType="IPF">
<Filename>ipf\ImageRead.c</Filename>
<Filename>ipf\DxeLoadFunc.c</Filename>
</Arch>
<Arch ArchType="EBC">
<Filename>ia32\ImageRead.c</Filename>
<Filename>ia32\DxeLoadFunc.c</Filename>
</Arch>
</SourceFiles>
<Includes>
<PackageName>MdePkg</PackageName>
<PackageName>EdkModulePkg</PackageName>
</Includes>
<Protocols>
<Protocol Usage="SOMETIMES_PRODUCED">Decompress</Protocol>
<Protocol Usage="SOMETIMES_PRODUCED">TianoDecompress</Protocol>
<Protocol Usage="SOMETIMES_PRODUCED">CustomizedDecompress</Protocol>
</Protocols>
<Hobs>
<Hob Usage="SOMETIMES_PRODUCED" HobType="MEMORY_ALLOCATION">
<C_Name>gEfiHobMemoryAllocBspStoreGuid</C_Name>
<Guid>0x564b33cd, 0xc92a, 0x4593, 0x90, 0xbf, 0x24, 0x73, 0xe4, 0x3c, 0x63, 0x22</Guid>
</Hob>
<Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
<C_Name>gEfiDecompressProtocolGuid</C_Name>
<Guid>0xd8117cfe, 0x94a6, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d</Guid>
</Hob>
<Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
<C_Name>gEfiTianoDecompressProtocolGuid</C_Name>
<Guid>0xe84cf29c, 0x191f, 0x4eae, 0x96, 0xe1, 0xf4, 0x6a, 0xec, 0xea, 0xea, 0x0b</Guid>
</Hob>
<Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
<C_Name>gEfiCustomizedDecompressProtocolGuid</C_Name>
<Guid>0x9a44198e, 0xa4a2, 0x44e6, 0x8a, 0x1f, 0x39, 0xbe, 0xfd, 0xac, 0x89, 0x6f</Guid>
</Hob>
<Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
<C_Name>gEfiPeiPeCoffLoaderGuid</C_Name>
<Guid>0xd8117cff, 0x94a6, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d</Guid>
</Hob>
<Hob Usage="SOMETIMES_PRODUCED" HobType="MEMORY_ALLOCATION">
<C_Name>gEfiHobMemoryAllocModuleGuid</C_Name>
<Guid>0xf8e21975, 0x0899, 0x4f58, 0xa4, 0xbe, 0x55, 0x25, 0xa9, 0xc6, 0xd7, 0x7a</Guid>
</Hob>
<Hob Usage="SOMETIMES_PRODUCED" HobType="FIRMWARE_VOLUME">
<Name>DecompressedFvmain.fv</Name>
</Hob>
</Hobs>
<PPIs>
<Ppi Usage="SOMETIMES_PRODUCED">DxeIpl</Ppi>
<Ppi Usage="SOMETIMES_PRODUCED">FvFileLoader</Ppi>
<Ppi Usage="SOMETIMES_PRODUCED">EndOfPeiSignal</Ppi>
<Ppi Usage="SOMETIMES_CONSUMED">RecoveryModule</Ppi>
<Ppi Usage="SOMETIMES_CONSUMED">S3Resume</Ppi>
<Ppi Usage="SOMETIMES_CONSUMED">SectionExtraction</Ppi>
<Ppi Usage="SOMETIMES_CONSUMED">Security</Ppi>
<Ppi Usage="PRIVATE">PeiInMemory</Ppi>
</PPIs>
<Guids>
<GuidEntry Usage="SOMETIMES_CONSUMED">
<C_Name>PeiPeCoffLoader</C_Name>
</GuidEntry>
</Guids>
<Externs>
<Extern>
<ModuleEntryPoint>PeimInitializeDxeIpl</ModuleEntryPoint>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@@ -0,0 +1,49 @@
<?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.
-->
<ModuleBuildDescription 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">
<MbdHeader>
<BaseName>DxeIpl</BaseName>
<Guid>86D70125-BAA3-4296-A62F-602BEBBB9081</Guid>
<Version>EDK_RELEASE_VERSION 0x00020000</Version>
<Description>FIX ME!</Description>
<Copyright>Copyright 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-04-03 23:58</Created>
</MbdHeader>
<Libraries>
<Library>PeimEntryPoint</Library>
<Library>PeiMemoryLib</Library>
<Library>PeiCoreLib</Library>
<Library>PeiServicesTablePointerLib</Library>
<Library>PeiHobLib</Library>
<Library>BaseCacheMaintenanceLib</Library>
<Library>BaseUefiTianoDecompressLib</Library>
<Library>BaseCustomDecompressLibNull</Library>
<Library>PeiReportStatusCodeLib</Library>
<Library>BaseDebugLibReportStatusCode</Library>
<Library>BaseLib</Library>
<Library>PeiMemoryAllocationLib</Library>
<Library>PeiReportStatusCodeLib</Library>
<Arch ArchType="IA32" OverrideID="8888">
<Library>EdkPeCoffLoaderX64Lib</Library>
<Library>EdkPeCoffLoaderLib</Library>
<Library>BasePeCoffLib</Library>
</Arch>
</Libraries>
</ModuleBuildDescription>

View File

@@ -0,0 +1,85 @@
<?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.
-->
<ModuleSurfaceArea 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">
<MsaHeader>
<BaseName>DxeIpl</BaseName>
<ModuleType>PEIM</ModuleType>
<ComponentType>PE32_PEIM</ComponentType>
<Guid>86D70125-BAA3-4296-A62F-602BEBBB9081</Guid>
<Version>EDK_RELEASE_VERSION 0x00020000</Version>
<Abstract>Component description file for DxeIpl module</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright 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>EFI_SPECIFICATION_VERSION 0x00000000</Specification>
<Created>2006-04-03 23:58</Created>
</MsaHeader>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeimEntryPoint</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">CacheMaintenanceLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">EdkPeCoffLoaderLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">TianoDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">CustomDecompressLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeiServicesTablePointerLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">EdkPeCoffLoaderX64Lib</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>DxeIpl.dxs</Filename>
<Filename>DxeLoadX64.c</Filename>
<Arch ArchType="IA32">
<Filename>x64\ImageRead.c</Filename>
<Filename>x64\LongMode.asm</Filename>
<Filename>x64\DxeLoadFunc.c</Filename>
<Filename>x64\VirtualMemory.c</Filename>
</Arch>
</SourceFiles>
<Includes>
<PackageName>MdePkg</PackageName>
<PackageName>EdkModulePkg</PackageName>
</Includes>
<Protocols>
<Protocol Usage="ALWAYS_CONSUMED">Decompress</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">TianoDecompress</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">CustomizedDecompress</Protocol>
</Protocols>
<PPIs>
<Ppi Usage="ALWAYS_CONSUMED">PeiInMemory</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">RecoveryModule</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">SectionExtraction</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">Security</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">DxeIpl</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">S3Resume</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">EndOfPeiSignal</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">FvFileLoader</Ppi>
</PPIs>
<Guids>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>PeiPeCoffLoader</C_Name>
</GuidEntry>
</Guids>
</ModuleSurfaceArea>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
/*++
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:
IpfDxeLoad.c
Abstract:
Ipf-specifc functionality for DxeLoad.
--*/
#include <DxeIpl.h>
EFI_STATUS
CreateArchSpecificHobs (
OUT EFI_PHYSICAL_ADDRESS *BspStore
)
/*++
Routine Description:
Creates architecture-specific HOBs.
Note: New parameters should NOT be added for any HOBs that are added to this
function. BspStore is a special case because it is required for the
call to SwitchStacks() in DxeLoad().
Arguments:
BspStore - The address of the BSP Store for those architectures that need
it. Otherwise 0.
Returns:
EFI_SUCCESS - The HOBs were created successfully.
--*/
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
ASSERT (NULL != BspStore);
//
// Allocate 16KB for the BspStore
//
Status = PeiCoreAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (BSP_STORE_SIZE), BspStore);
if (EFI_ERROR (Status)) {
return Status;
}
BuildBspStoreHob (
*BspStore,
BSP_STORE_SIZE,
EfiBootServicesData
);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,72 @@
/*++
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:
ImageRead.c
Abstract:
--*/
#include <DxeIpl.h>
EFI_STATUS
PeiImageRead (
IN VOID *FileHandle,
IN UINTN FileOffset,
IN OUT UINTN *ReadSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
Arguments:
FileHandle - The handle to the PE/COFF file
FileOffset - The offset, in bytes, into the file to read
ReadSize - The number of bytes to read from the file starting at FileOffset
Buffer - A pointer to the buffer to read the data into.
Returns:
EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
--*/
{
CHAR8 *Destination8;
CHAR8 *Source8;
UINTN Length;
Destination8 = Buffer;
Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
Length = *ReadSize;
while (Length--) {
*(Destination8++) = *(Source8++);
}
return EFI_SUCCESS;
}
EFI_STATUS
GetImageReadFunction (
IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
{
ImageContext->ImageRead = PeiImageRead;
return EFI_SUCCESS;
}

View File

@@ -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="DxeIpl"><!--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="Core\DxeIplPeim"/>
<property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
<property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
<target name="DxeIpl">
<GenBuild baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIpl.mbd" msaFilename="${MODULE_DIR}\DxeIpl.msa"/>
</target>
<target depends="DxeIpl_clean" name="clean"/>
<target depends="DxeIpl_cleanall" name="cleanall"/>
<target name="DxeIpl_clean">
<OutputDirSetup baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIpl.mbd" msaFilename="${MODULE_DIR}\DxeIpl.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\DxeIpl_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\DxeIpl_build.xml" target="clean"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
</target>
<target name="DxeIpl_cleanall">
<OutputDirSetup baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIpl.mbd" msaFilename="${MODULE_DIR}\DxeIpl.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\DxeIpl_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\DxeIpl_build.xml" target="cleanall"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}"/>
<delete dir="${DEST_DIR_DEBUG}"/>
<delete>
<fileset dir="${BIN_DIR}" includes="**DxeIpl*"/>
</delete>
</target>
</project>

View File

@@ -0,0 +1,46 @@
<?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="DxeIpl"><!--Apply external ANT tasks-->
<taskdef resource="GenBuild.tasks"/>
<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="Core\DxeIplPeim"/>
<property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
<property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
<target name="DxeIpl">
<GenBuild baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIplX64.mbd" msaFilename="${MODULE_DIR}\DxeIplX64.msa"/>
</target>
<target depends="DxeIpl_clean" name="clean"/>
<target depends="DxeIpl_cleanAll" name="cleanAll"/>
<target name="DxeIpl_clean">
<OutputDirSetup baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIplX64.mbd" msaFilename="${MODULE_DIR}\DxeIplX64.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\DxeIpl_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\DxeIpl_build.xml" target="clean"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
</target>
<target name="DxeIpl_cleanAll">
<OutputDirSetup baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIplX64.mbd" msaFilename="${MODULE_DIR}\DxeIplX64.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\DxeIpl_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\DxeIpl_build.xml" target="cleanAll"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}"/>
<delete dir="${DEST_DIR_DEBUG}"/>
<delete>
<fileset dir="${BIN_DIR}" includes="**DxeIpl*"/>
</delete>
</target>
</project>

View File

@@ -0,0 +1,51 @@
/*++
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:
DxeLoadFunc.c
Abstract:
Ia32-specifc functionality for DxeLoad.
--*/
#include <DxeIpl.h>
EFI_STATUS
CreateArchSpecificHobs (
OUT EFI_PHYSICAL_ADDRESS *BspStore
)
/*++
Routine Description:
Creates architecture-specific HOBs.
Note: New parameters should NOT be added for any HOBs that are added to this
function. BspStore is a special case because it is required for the
call to SwitchStacks() in DxeLoad().
Arguments:
BspStore - The address of the BSP Store for those architectures that need
it. Otherwise 0.
Returns:
EFI_SUCCESS - The HOBs were created successfully.
--*/
{
*BspStore = 0;
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,112 @@
/*++
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:
ImageRead.c
Abstract:
--*/
#include <DxeIpl.h>
EFI_STATUS
EFIAPI
PeiImageRead (
IN VOID *FileHandle,
IN UINTN FileOffset,
IN OUT UINTN *ReadSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
Arguments:
FileHandle - The handle to the PE/COFF file
FileOffset - The offset, in bytes, into the file to read
ReadSize - The number of bytes to read from the file starting at FileOffset
Buffer - A pointer to the buffer to read the data into.
Returns:
EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
--*/
{
UINT8 *Destination32;
UINT8 *Source32;
UINTN Length;
Destination32 = Buffer;
Source32 = (UINT8 *) ((UINTN) FileHandle + FileOffset);
//
// This function assumes 32-bit alignment to increase performance
//
// ASSERT (ALIGN_POINTER (Destination32, sizeof (UINT32)) == Destination32);
// ASSERT (ALIGN_POINTER (Source32, sizeof (UINT32)) == Source32);
Length = *ReadSize;
while (Length--) {
*(Destination32++) = *(Source32++);
}
return EFI_SUCCESS;
}
EFI_STATUS
GetImageReadFunction (
IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
/*++
Routine Description:
Support routine to return the PE32 Image Reader.
If the PeiImageRead() function is less than a page
in legnth. If the function is more than a page the DXE IPL will crash!!!!
Arguments:
ImageContext - The context of the image being loaded
Returns:
EFI_SUCCESS - If Image function location is found
--*/
{
VOID *MemoryBuffer;
if (gInMemory) {
ImageContext->ImageRead = PeiImageRead;
return EFI_SUCCESS;
}
//
// BugBug; This code assumes PeiImageRead() is less than a page in size!
// Allocate a page so we can shaddow the read function from FLASH into
// memory to increase performance.
//
MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead);
ASSERT (MemoryBuffer != NULL);
ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,53 @@
/*++
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:
DxeLoadFunc.c
Abstract:
Ia32-specifc functionality for DxeLoad X64 Lakeport.
--*/
#include <DxeIpl.h>
EFI_STATUS
CreateArchSpecificHobs (
OUT EFI_PHYSICAL_ADDRESS *BspStore
)
/*++
Routine Description:
Creates architecture-specific HOBs.
Note: New parameters should NOT be added for any HOBs that are added to this
function. BspStore is a special case because it is required for the
call to SwitchStacks() in DxeLoad().
Arguments:
PeiServices - General purpose services available to every PEIM.
BspStore - The address of the BSP Store for those architectures that need
it. Otherwise 0.
Returns:
EFI_SUCCESS - The HOBs were created successfully.
--*/
{
*BspStore = 0;
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,106 @@
/*++
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:
ImageRead.c
Abstract:
--*/
#include <DxeIpl.h>
EFI_STATUS
EFIAPI
PeiImageRead (
IN VOID *FileHandle,
IN UINTN FileOffset,
IN OUT UINTN *ReadSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
Arguments:
FileHandle - The handle to the PE/COFF file
FileOffset - The offset, in bytes, into the file to read
ReadSize - The number of bytes to read from the file starting at FileOffset
Buffer - A pointer to the buffer to read the data into.
Returns:
EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
--*/
{
CHAR8 *Destination8;
CHAR8 *Source8;
UINTN Length;
Destination8 = Buffer;
Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
Length = *ReadSize;
while (Length--) {
*(Destination8++) = *(Source8++);
}
return EFI_SUCCESS;
}
EFI_STATUS
GetImageReadFunction (
IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
/*++
Routine Description:
Support routine to return the PE32 Image Reader.
If the PeiImageRead() function is less than a page
in legnth. If the function is more than a page the DXE IPL will crash!!!!
Arguments:
ImageContext - The context of the image being loaded
Returns:
EFI_SUCCESS - If Image function location is found
--*/
{
VOID *MemoryBuffer;
if (gInMemory) {
ImageContext->ImageRead = PeiImageRead;
return EFI_SUCCESS;
}
//
// BugBug; This code assumes PeiImageRead() is less than a page in size!
// Allocate a page so we can shaddow the read function from FLASH into
// memory to increase performance.
//
MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead);
ASSERT (MemoryBuffer != NULL);
ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;
return EFI_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,434 @@
/*++
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:
VirtualMemory.c
Abstract:
x64 Virtual Memory Management Services in the form of an IA-32 driver.
Used to establish a 1:1 Virtual to Physical Mapping that is required to
enter Long Mode (x64 64-bit mode).
While we make a 1:1 mapping (identity mapping) for all physical pages
we still need to use the MTRR's to ensure that the cachability attirbutes
for all memory regions is correct.
The basic idea is to use 2MB page table entries where ever possible. If
more granularity of cachability is required then 4K page tables are used.
References:
1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel
2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
--*/
#include "VirtualMemory.h"
x64_MTRR_VARIABLE_RANGE *mMTRRVariableRange;
x64_MTRR_FIXED_RANGE mMTRRFixedRange;
//
// Physial memory limit values for each of the 11 fixed MTRRs
//
UINTN mFixedRangeLimit[] = {
0x7FFFF, // Fixed MTRR #0 describes 0x00000..0x7FFFF
0x9FFFF, // Fixed MTRR #1 describes 0x80000..0x9FFFF
0xBFFFF, // Fixed MTRR #2 describes 0xA0000..0xBFFFF
0xC7FFF, // Fixed MTRR #3 describes 0xC0000..0xC7FFF
0xCFFFF, // Fixed MTRR #4 describes 0xC8000..0xCFFFF
0xD7FFF, // Fixed MTRR #5 describes 0xD0000..0xD7FFF
0xDFFFF, // Fixed MTRR #6 describes 0xD8000..0xDFFFF
0xE7FFF, // Fixed MTRR #7 describes 0xE0000..0xE7FFF
0xEFFFF, // Fixed MTRR #8 describes 0xE8000..0xEFFFF
0xF7FFF, // Fixed MTRR #9 describes 0xF0000..0xF7FFF
0xFFFFF // Fixed MTRR #10 describes 0xF8000..0xFFFFF
};
//
// The size, in bits, of each of the 11 fixed MTRR.
//
UINTN mFixedRangeShift[] = {
16, // Fixed MTRR #0 describes 8, 64 KB ranges
14, // Fixed MTRR #1 describes 8, 16 KB ranges
14, // Fixed MTRR #2 describes 8, 16 KB ranges
12, // Fixed MTRR #3 describes 8, 4 KB ranges
12, // Fixed MTRR #4 describes 8, 4 KB ranges
12, // Fixed MTRR #5 describes 8, 4 KB ranges
12, // Fixed MTRR #6 describes 8, 4 KB ranges
12, // Fixed MTRR #7 describes 8, 4 KB ranges
12, // Fixed MTRR #8 describes 8, 4 KB ranges
12, // Fixed MTRR #9 describes 8, 4 KB ranges
12 // Fixed MTRR #10 describes 8, 4 KB ranges
};
UINTN mPowerOf2[] = {
1,
2,
4,
8,
16,
32,
64,
128,
256,
512
};
x64_MTRR_MEMORY_TYPE
EfiGetMTRRMemoryType (
IN EFI_PHYSICAL_ADDRESS Address
)
/*++
Routine Description:
Retrieves the memory type from the MTRR that describes a physical address.
Arguments:
VariableRange - Set of Variable MTRRs
FixedRange - Set of Fixed MTRRs
Address - The physical address for which the MTRR memory type is being retrieved
Returns:
The MTRR Memory Type for the physical memory specified by Address.
--*/
{
UINTN Index;
UINTN TypeIndex;
BOOLEAN Found;
x64_MTRR_MEMORY_TYPE VariableType;
EFI_PHYSICAL_ADDRESS MaskBase;
EFI_PHYSICAL_ADDRESS PhysMask;
//
// If the MTRRs are disabled, then return the Uncached Memory Type
//
if (mMTRRFixedRange.DefaultType.Bits.E == 0) {
return Uncached;
}
//
// If the CPU supports Fixed MTRRs and the Fixed MTRRs are enabled, then
// see if Address falls into one of the Fixed MTRRs
//
if (mMTRRFixedRange.Capabilities.Bits.FIX && mMTRRFixedRange.DefaultType.Bits.FE) {
//
// Loop though 11 fixed MTRRs
//
for (Index = 0; Index < 11; Index++) {
//
// Check for a matching range
//
if (Address <= mFixedRangeLimit[Index]) {
//
// Compute the offset address into the MTRR bu subtrating the base address of the MTRR
//
if (Index > 0) {
Address = Address - (mFixedRangeLimit[Index-1] + 1);
}
//
// Retrieve the index into the MTRR to extract the memory type. The range is 0..7
//
TypeIndex = (UINTN)RShiftU64 (Address, mFixedRangeShift[Index]);
//
// Retrieve and return the memory type for the matching range
//
return mMTRRFixedRange.Fixed[Index].Type[TypeIndex];
}
}
}
//
// If Address was not found in a Fixed MTRR, then search the Variable MTRRs
//
for (Index = 0, Found = FALSE, VariableType = WriteBack; Index < mMTRRFixedRange.Capabilities.Bits.VCNT; Index++) {
//
// BugBug: __aullshr complier error
//
if ((mMTRRVariableRange[Index].PhysMask.Uint64 & 0x800) == 0x800) {
//if (mMTRRVariableRange[Index].PhysMask.Bits.Valid == 1) {
PhysMask = mMTRRVariableRange[Index].PhysMask.Uint64 & ~0xfff;
MaskBase = PhysMask & (mMTRRVariableRange[Index].PhysBase.Uint64 & ~0xfff);
if (MaskBase == (PhysMask & Address)) {
//
// Check to see how many matches we find
//
Found = TRUE;
if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == Uncached) || (VariableType == Uncached)) {
//
// If any matching region uses UC, the memory region is UC
//
VariableType = Uncached;
} else if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == WriteThrough) || (VariableType == WriteThrough)){
//
// If it's WT and WB then set it to WT. If it's WT and other type it's undefined
//
VariableType = WriteThrough;
} else {
VariableType = mMTRRVariableRange[Index].PhysBase.Bits.Type;
}
}
}
}
if (Found) {
return VariableType;
}
//
// Address was not found in the Fixed or Variable MTRRs, so return the default memory type
//
return mMTRRFixedRange.DefaultType.Bits.Type;
}
BOOLEAN
CanNotUse2MBPage (
IN EFI_PHYSICAL_ADDRESS BaseAddress
)
/*++
Routine Description:
Test to see if a 2MB aligned page has all the same attributes. If a 2MB page
has more than one attibute type it needs to be split into multiple 4K pages.
Arguments:
BaseAddress - 2MB aligned address to check out
Returns:
TRUE - This 2MB address range (BaseAddress) can NOT be mapped by a 2MB page
FALSE - This 2MB address range can be mapped by a 2MB page
--*/
{
UINTN Index;
x64_MTRR_MEMORY_TYPE MemoryType;
x64_MTRR_MEMORY_TYPE PreviousMemoryType;
//
// Address needs to be 2MB aligned
//
ASSERT ((BaseAddress & 0x1fffff) == 0);
PreviousMemoryType = -1;
for (Index = 0; Index < 512; Index++, BaseAddress += 0x1000) {
MemoryType = EfiGetMTRRMemoryType (BaseAddress);
if ((Index != 0) && (MemoryType != PreviousMemoryType)) {
return TRUE;
}
PreviousMemoryType = MemoryType;
}
//
// All the pages had the same type
//
return FALSE;
}
VOID
Convert2MBPageTo4KPages (
IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB,
IN EFI_PHYSICAL_ADDRESS PageAddress
)
/*++
Routine Description:
Convert a single 2MB page entry to 512 4K page entries. The attributes for
the 4K pages are read from the MTRR registers.
Arguments:
PageDirectoryEntry2MB - Page directory entry for PageAddress
PageAddress - 2MB algined address of region to convert
Returns:
None
--*/
{
EFI_PHYSICAL_ADDRESS Address;
x64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4k;
x64_PAGE_TABLE_ENTRY_4K *PageTableEntry;
UINTN Index1;
//
// Allocate the page table entry for the 4K pages
//
PageTableEntry = (x64_PAGE_TABLE_ENTRY_4K *) AllocatePages (1);
ASSERT (PageTableEntry != NULL);
//
// Convert PageDirectoryEntry2MB into a 4K Page Directory
//
PageDirectoryEntry4k = (x64_PAGE_DIRECTORY_ENTRY_4K *)PageDirectoryEntry2MB;
PageDirectoryEntry2MB->Uint64 = (UINT64)PageTableEntry;
PageDirectoryEntry2MB->Bits.ReadWrite = 1;
PageDirectoryEntry2MB->Bits.Present = 1;
//
// Fill in the 4K page entries with the attributes from the MTRRs
//
for (Index1 = 0, Address = PageAddress; Index1 < 512; Index1++, PageTableEntry++, Address += 0x1000) {
PageTableEntry->Uint64 = (UINT64)Address;
PageTableEntry->Bits.ReadWrite = 1;
PageTableEntry->Bits.Present = 1;
}
}
EFI_PHYSICAL_ADDRESS
CreateIdentityMappingPageTables (
IN UINT32 NumberOfProcessorPhysicalAddressBits
)
/*++
Routine Description:
Allocates and fills in the Page Directory and Page Table Entries to
establish a 1:1 Virtual to Physical mapping for physical memory from
0 to 4GB. Memory above 4GB is not mapped. The MTRRs are used to
determine the cachability of the physical memory regions
Arguments:
NumberOfProcessorPhysicalAddressBits - Number of processor address bits to use.
Limits the number of page table entries
to the physical address space.
Returns:
EFI_OUT_OF_RESOURCES There are not enough resources to allocate the Page Tables
EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created
--*/
{
EFI_PHYSICAL_ADDRESS PageAddress;
UINTN Index;
UINTN MaxBitsSupported;
UINTN Index1;
UINTN Index2;
x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;
x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMap;
x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;
x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB;
//
// Page Table structure 4 level 4K, 3 level 2MB.
//
// PageMapLevel4Entry : bits 47-39
// PageDirectoryPointerEntry : bits 38-30
// Page Table 2MB : PageDirectoryEntry2M : bits 29-21
// Page Table 4K : PageDirectoryEntry4K : bits 29 - 21
// PageTableEntry : bits 20 - 12
//
// Strategy is to map every thing in the processor address space using
// 2MB pages. If more granularity is required the 2MB page will get
// converted to set of 4K pages.
//
//
// By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.
//
PageMap = PageMapLevel4Entry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1);
ASSERT (PageMap != NULL);
PageAddress = 0;
//
// The number of page-map Level-4 Offset entries is based on the number of
// physical address bits. Less than equal to 38 bits only takes one entry.
// 512 entries represents 48 address bits.
//
if (NumberOfProcessorPhysicalAddressBits <= 38) {
MaxBitsSupported = 1;
} else {
MaxBitsSupported = mPowerOf2[NumberOfProcessorPhysicalAddressBits - 39];
}
for (Index = 0; Index < MaxBitsSupported; Index++, PageMapLevel4Entry++) {
//
// Each PML4 entry points to a page of Page Directory Pointer entires.
// So lets allocate space for them and fill them in in the Index1 loop.
//
PageDirectoryPointerEntry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1);
ASSERT (PageDirectoryPointerEntry != NULL);
//
// Make a PML4 Entry
//
PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
PageMapLevel4Entry->Bits.ReadWrite = 1;
PageMapLevel4Entry->Bits.Present = 1;
for (Index1 = 0; Index1 < 512; Index1++, PageDirectoryPointerEntry++) {
//
// Each Directory Pointer entries points to a page of Page Directory entires.
// So lets allocate space for them and fill them in in the Index2 loop.
//
PageDirectoryEntry2MB = (x64_PAGE_TABLE_ENTRY_2M *) AllocatePages (1);
ASSERT (PageDirectoryEntry2MB != NULL);
//
// Fill in a Page Directory Pointer Entries
//
PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry2MB;
PageDirectoryPointerEntry->Bits.ReadWrite = 1;
PageDirectoryPointerEntry->Bits.Present = 1;
for (Index2 = 0; Index2 < 512; Index2++, PageDirectoryEntry2MB++, PageAddress += 0x200000) {
//
// Fill in the Page Directory entries
//
PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;
PageDirectoryEntry2MB->Bits.ReadWrite = 1;
PageDirectoryEntry2MB->Bits.Present = 1;
PageDirectoryEntry2MB->Bits.MustBe1 = 1;
if (CanNotUse2MBPage (PageAddress)) {
//
// Check to see if all 2MB has the same mapping. If not convert
// to 4K pages by adding the 4th level of page table entries
//
Convert2MBPageTo4KPages (PageDirectoryEntry2MB, PageAddress);
}
}
}
}
//
// For the PML4 entries we are not using fill in a null entry.
// for now we just copy the first entry.
//
for (; Index < 512; Index++, PageMapLevel4Entry++) {
// EfiCopyMem (PageMapLevel4Entry, PageMap, sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K));
CopyMem (PageMapLevel4Entry,
PageMap,
sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K)
);
}
return (EFI_PHYSICAL_ADDRESS)PageMap;
}

View File

@@ -0,0 +1,239 @@
/*++
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:
VirtualMemory.h
Abstract:
x64 Long Mode Virtual Memory Management Definitions
References:
1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel
2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
--*/
#ifndef _VIRTUAL_MEMORY_H_
#define _VIRTUAL_MEMORY_H_
#pragma pack(1)
//
// Page-Map Level-4 Offset (PML4) and
// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
//
typedef union {
struct {
UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
UINT64 Reserved:1; // Reserved
UINT64 MustBeZero:2; // Must Be Zero
UINT64 Available:3; // Available for use by system software
UINT64 PageTableBaseAddress:40; // Page Table Base Address
UINT64 AvabilableHigh:11; // Available for use by system software
UINT64 Nx:1; // No Execute bit
} Bits;
UINT64 Uint64;
} x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K;
//
// Page-Directory Offset 4K
//
typedef union {
struct {
UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
UINT64 Reserved:1; // Reserved
UINT64 MustBeZero:1; // Must Be Zero
UINT64 Reserved2:1; // Reserved
UINT64 Available:3; // Available for use by system software
UINT64 PageTableBaseAddress:40; // Page Table Base Address
UINT64 AvabilableHigh:11; // Available for use by system software
UINT64 Nx:1; // No Execute bit
} Bits;
UINT64 Uint64;
} x64_PAGE_DIRECTORY_ENTRY_4K;
//
// Page Table Entry 4K
//
typedef union {
struct {
UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
UINT64 PAT:1; // 0 = Ignore Page Attribute Table
UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
UINT64 Available:3; // Available for use by system software
UINT64 PageTableBaseAddress:40; // Page Table Base Address
UINT64 AvabilableHigh:11; // Available for use by system software
UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
} Bits;
UINT64 Uint64;
} x64_PAGE_TABLE_ENTRY_4K;
//
// Page Table Entry 2MB
//
typedef union {
struct {
UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
UINT64 MustBe1:1; // Must be 1
UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
UINT64 Available:3; // Available for use by system software
UINT64 PAT:1; //
UINT64 MustBeZero:8; // Must be zero;
UINT64 PageTableBaseAddress:31; // Page Table Base Address
UINT64 AvabilableHigh:11; // Available for use by system software
UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
} Bits;
UINT64 Uint64;
} x64_PAGE_TABLE_ENTRY_2M;
typedef union {
UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
UINT64 Reserved:57;
} x64_PAGE_TABLE_ENTRY_COMMON;
typedef union {
x64_PAGE_TABLE_ENTRY_4K Page4k;
x64_PAGE_TABLE_ENTRY_2M Page2Mb;
x64_PAGE_TABLE_ENTRY_COMMON Common;
} x64_PAGE_TABLE_ENTRY;
//
// MTRR Definitions
//
typedef enum {
Uncached = 0,
WriteCombining = 1,
WriteThrough = 4,
WriteProtected = 5,
WriteBack = 6
} x64_MTRR_MEMORY_TYPE;
typedef union {
struct {
UINT32 VCNT:8; // The number of Variable Range MTRRs
UINT32 FIX:1; // 1=Fixed Range MTRRs supported. 0=Fixed Range MTRRs not supported
UINT32 Reserved_0; // Reserved
UINT32 WC:1; // Write combining memory type supported
UINT32 Reserved_1:21; // Reserved
UINT32 Reserved_2:32; // Reserved
} Bits;
UINT64 Uint64;
} x64_MTRRCAP_MSR;
typedef union {
struct {
UINT32 Type:8; // Default Memory Type
UINT32 Reserved_0:2; // Reserved
UINT32 FE:1; // 1=Fixed Range MTRRs enabled. 0=Fixed Range MTRRs disabled
UINT32 E:1; // 1=MTRRs enabled, 0=MTRRs disabled
UINT32 Reserved_1:20; // Reserved
UINT32 Reserved_2:32; // Reserved
} Bits;
UINT64 Uint64;
} x64_MTRR_DEF_TYPE_MSR;
typedef union {
UINT8 Type[8]; // The 8 Memory Type values in the 64-bit MTRR
UINT64 Uint64; // The full 64-bit MSR
} x64_MTRR_FIXED_RANGE_MSR;
typedef struct {
x64_MTRRCAP_MSR Capabilities; // MTRR Capabilities MSR value
x64_MTRR_DEF_TYPE_MSR DefaultType; // Default Memory Type MSR Value
x64_MTRR_FIXED_RANGE_MSR Fixed[11]; // The 11 Fixed MTRR MSR Values
} x64_MTRR_FIXED_RANGE;
typedef union {
struct {
UINT64 Type:8; // Memory Type
UINT64 Reserved0:4; // Reserved
UINT64 PhysBase:40; // The physical base address(bits 35..12) of the MTRR
UINT64 Reserved1:12 ; // Reserved
} Bits;
UINT64 Uint64;
} x64_MTRR_PHYSBASE_MSR;
typedef union {
struct {
UINT64 Reserved0:11; // Reserved
UINT64 Valid:1; // 1=MTRR is valid, 0=MTRR is not valid
UINT64 PhysMask:40; // The physical address mask (bits 35..12) of the MTRR
UINT64 Reserved1:12; // Reserved
} Bits;
UINT64 Uint64;
} x64_MTRR_PHYSMASK_MSR;
typedef struct {
x64_MTRR_PHYSBASE_MSR PhysBase; // Variable MTRR Physical Base MSR
x64_MTRR_PHYSMASK_MSR PhysMask; // Variable MTRR Physical Mask MSR
} x64_MTRR_VARIABLE_RANGE;
#pragma pack()
x64_MTRR_MEMORY_TYPE
EfiGetMTRRMemoryType (
IN EFI_PHYSICAL_ADDRESS Address
)
;
BOOLEAN
CanNotUse2MBPage (
IN EFI_PHYSICAL_ADDRESS BaseAddress
)
;
VOID
Convert2MBPageTo4KPages (
IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB,
IN EFI_PHYSICAL_ADDRESS PageAddress
)
;
EFI_PHYSICAL_ADDRESS
CreateIdentityMappingPageTables (
IN UINT32 NumberOfProcessorPhysicalAddressBits
)
;
#endif

View File

@@ -0,0 +1,106 @@
/*++
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:
BootMode.c
Abstract:
EFI PEI Core Boot Mode services
Revision History
--*/
#include <PeiMain.h>
EFI_STATUS
EFIAPI
PeiGetBootMode (
IN EFI_PEI_SERVICES **PeiServices,
OUT EFI_BOOT_MODE *BootMode
)
/*++
Routine Description:
This service enables PEIMs to ascertain the present value of the boot mode.
Arguments:
PeiServices - The PEI core services table.
BootMode - A pointer to contain the value of the boot mode.
Returns:
EFI_SUCCESS - The boot mode was returned successfully.
EFI_INVALID_PARAMETER - BootMode is NULL.
--*/
{
PEI_CORE_INSTANCE *PrivateData;
EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
if (BootMode == NULL) {
return EFI_INVALID_PARAMETER;
}
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
HandOffHob = (PrivateData->HobList.HandoffInformationTable);
*BootMode = HandOffHob->BootMode;
return EFI_SUCCESS;
};
EFI_STATUS
EFIAPI
PeiSetBootMode (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_BOOT_MODE BootMode
)
/*++
Routine Description:
This service enables PEIMs to update the boot mode variable.
Arguments:
PeiServices - The PEI core services table.
BootMode - The value of the boot mode to set.
Returns:
EFI_SUCCESS - The value was successfully updated
--*/
{
PEI_CORE_INSTANCE *PrivateData;
EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
HandOffHob = (PrivateData->HobList.HandoffInformationTable);
HandOffHob->BootMode = BootMode;
return EFI_SUCCESS;
};

View File

@@ -0,0 +1,264 @@
/*++
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:
dependency.c
Abstract:
PEI Dispatcher Dependency Evaluator
This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine
if a driver can be scheduled for execution. The criteria for
schedulability is that the dependency expression is satisfied.
--*/
#include <PeiMain.h>
#include "Dependency.h"
STATIC
BOOLEAN
IsPpiInstalled (
IN EFI_PEI_SERVICES **PeiServices,
IN EVAL_STACK_ENTRY *Stack
)
/*++
Routine Description:
This routine determines if a PPI has been installed.
The truth value of a GUID is determined by if the PPI has
been published and can be queried from the PPI database.
Arguments:
PeiServices - The PEI core services table.
Stack - Reference to EVAL_STACK_ENTRY that contains PPI GUID to check
Returns:
True if the PPI is already installed.
False if the PPI has yet to be installed.
--*/
{
VOID *PeiInstance;
EFI_STATUS Status;
EFI_GUID PpiGuid;
//
// If there is no GUID to evaluate, just return current result on stack.
//
if (Stack->Operator == NULL) {
return Stack->Result;
}
//
// Copy the Guid into a locale variable so that there are no
// possibilities of alignment faults for cross-compilation
// environments such as Intel?Itanium(TM).
//
CopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID));
//
// Check if the PPI is installed.
//
Status = PeiCoreLocatePpi(
&PpiGuid, // GUID
0, // INSTANCE
NULL, // EFI_PEI_PPI_DESCRIPTOR
&PeiInstance // PPI
);
if (EFI_ERROR(Status)) {
return FALSE;
}
return TRUE;
}
EFI_STATUS
PeimDispatchReadiness (
IN EFI_PEI_SERVICES **PeiServices,
IN VOID *DependencyExpression,
OUT BOOLEAN *Runnable
)
/*++
Routine Description:
This is the POSTFIX version of the dependency evaluator. When a
PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on
the evaluation stack. When that entry is poped from the evaluation
stack, the PPI is checked if it is installed. This method allows
some time savings as not all PPIs must be checked for certain
operation types (AND, OR).
Arguments:
PeiServices - Calling context.
DependencyExpression - Pointer to a dependency expression. The Grammar adheres to
the BNF described above and is stored in postfix notation.
Runnable - is True if the driver can be scheduled and False if the driver
cannot be scheduled. This is the value that the schedulers
should use for deciding the state of the driver.
Returns:
Status = EFI_SUCCESS if it is a well-formed Grammar
EFI_INVALID_PARAMETER if the dependency expression overflows
the evaluation stack
EFI_INVALID_PARAMETER if the dependency expression underflows
the evaluation stack
EFI_INVALID_PARAMETER if the dependency expression is not a
well-formed Grammar.
--*/
{
EFI_STATUS Status;
DEPENDENCY_EXPRESSION_OPERAND *Iterator;
EVAL_STACK_ENTRY *StackPtr;
EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE];
Status = EFI_SUCCESS;
Iterator = DependencyExpression;
*Runnable = FALSE;
StackPtr = &EvalStack[0];
while (TRUE) {
switch (*(Iterator++)) {
//
// For performance reason we put the frequently used items in front of
// the rarely used items
//
case (EFI_DEP_PUSH):
//
// Check to make sure the dependency grammar doesn't overflow the
// EvalStack on the push
//
if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {
return EFI_INVALID_PARAMETER;
}
//
// Push the pointer to the PUSH opcode operator (pointer to PPI GUID)
// We will evaluate if the PPI is insalled on the POP operation.
//
StackPtr->Operator = (VOID *) Iterator;
Iterator = Iterator + sizeof (EFI_GUID);
StackPtr++;
break;
case (EFI_DEP_AND):
case (EFI_DEP_OR):
//
// Check to make sure the dependency grammar doesn't underflow the
// EvalStack on the two POPs for the AND operation. Don't need to
// check for the overflow on PUSHing the result since we already
// did two POPs.
//
if (StackPtr < &EvalStack[2]) {
return EFI_INVALID_PARAMETER;
}
//
// Evaluate the first POPed operator only. If the operand is
// EFI_DEP_AND and the POPed operator evaluates to FALSE, or the
// operand is EFI_DEP_OR and the POPed operator evaluates to TRUE,
// we don't need to check the second operator, and the result will be
// evaluation of the POPed operator. Otherwise, don't POP the second
// operator since it will now evaluate to the final result on the
// next operand that causes a POP.
//
StackPtr--;
//
// Iterator has increased by 1 after we retrieve the operand, so here we
// should get the value pointed by (Iterator - 1), in order to obtain the
// same operand.
//
if (*(Iterator - 1) == EFI_DEP_AND) {
if (!(IsPpiInstalled (PeiServices, StackPtr))) {
(StackPtr-1)->Result = FALSE;
(StackPtr-1)->Operator = NULL;
}
} else {
if (IsPpiInstalled (PeiServices, StackPtr)) {
(StackPtr-1)->Result = TRUE;
(StackPtr-1)->Operator = NULL;
}
}
break;
case (EFI_DEP_END):
StackPtr--;
//
// Check to make sure EvalStack is balanced. If not, then there is
// an error in the dependency grammar, so return EFI_INVALID_PARAMETER.
//
if (StackPtr != &EvalStack[0]) {
return EFI_INVALID_PARAMETER;
}
*Runnable = IsPpiInstalled (PeiServices, StackPtr);
return EFI_SUCCESS;
break;
case (EFI_DEP_NOT):
//
// Check to make sure the dependency grammar doesn't underflow the
// EvalStack on the POP for the NOT operation. Don't need to
// check for the overflow on PUSHing the result since we already
// did a POP.
//
if (StackPtr < &EvalStack[1]) {
return EFI_INVALID_PARAMETER;
}
(StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1));
(StackPtr-1)->Operator = NULL;
break;
case (EFI_DEP_TRUE):
case (EFI_DEP_FALSE):
//
// Check to make sure the dependency grammar doesn't overflow the
// EvalStack on the push
//
if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {
return EFI_INVALID_PARAMETER;
}
//
// Iterator has increased by 1 after we retrieve the operand, so here we
// should get the value pointed by (Iterator - 1), in order to obtain the
// same operand.
//
if (*(Iterator - 1) == EFI_DEP_TRUE) {
StackPtr->Result = TRUE;
} else {
StackPtr->Result = FALSE;
}
StackPtr->Operator = NULL;
StackPtr++;
break;
default:
//
// The grammar should never arrive here
//
return EFI_INVALID_PARAMETER;
break;
}
}
}

View File

@@ -0,0 +1,38 @@
/*++
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:
dependency.h
Abstract:
This module contains data specific to dependency expressions
and local function prototypes.
--*/
#ifndef _PEI_DEPENDENCY_H_
#define _PEI_DEPENDENCY_H_
#define MAX_GRAMMAR_SIZE 256
//
// type definitions
//
typedef UINT8 DEPENDENCY_EXPRESSION_OPERAND;
typedef struct {
BOOLEAN Result;
VOID *Operator;
} EVAL_STACK_ENTRY;
#endif

View File

@@ -0,0 +1,535 @@
/*++
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:
Dispatcher.c
Abstract:
EFI PEI Core dispatch services
Revision History
--*/
#include <PeiMain.h>
VOID *
TransferOldDataToNewDataRange (
IN PEI_CORE_INSTANCE *PrivateData
);
EFI_GUID gEfiPeiCorePrivateGuid = EFI_PEI_CORE_PRIVATE_GUID;
EFI_STATUS
PeiDispatcher (
IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
IN PEI_CORE_INSTANCE *PrivateData,
IN PEI_CORE_DISPATCH_DATA *DispatchData
)
/*++
Routine Description:
Conduct PEIM dispatch.
Arguments:
PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR
PrivateData - Pointer to the private data passed in from caller
DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data.
Returns:
EFI_SUCCESS - Successfully dispatched PEIM.
EFI_NOT_FOUND - The dispatch failed.
--*/
{
EFI_STATUS Status;
PEI_CORE_TEMP_POINTERS TempPtr;
UINTN PrivateDataInMem;
BOOLEAN NextFvFound;
EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress;
EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress;
//
// Debug data for uninstalled Peim list
//
EFI_GUID DebugFoundPeimList[32];
REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
//
// save the Current FV Address so that we will not process it again if FindFv returns it later
//
DefaultFvAddress = DispatchData->BootFvAddress;
//
// This is the main dispatch loop. It will search known FVs for PEIMs and
// attempt to dispatch them. If any PEIM gets dispatched through a single
// pass of the dispatcher, it will start over from the Bfv again to see
// if any new PEIMs dependencies got satisfied. With a well ordered
// FV where PEIMs are found in the order their dependencies are also
// satisfied, this dipatcher should run only once.
//
for (;;) {
//
// This is the PEIM search loop. It will scan through all PEIMs it can find
// looking for PEIMs to dispatch, and will dipatch them if they have not
// already been dispatched and all of their dependencies are met.
// If no more PEIMs can be found in this pass through all known FVs,
// then it will break out of this loop.
//
for (;;) {
Status = FindNextPeim (
&PrivateData->PS,
DispatchData->CurrentFvAddress,
&DispatchData->CurrentPeimAddress
);
//
// If we found a PEIM, check if it is dispatched. If so, go to the
// next PEIM. If not, dispatch it if its dependencies are satisfied.
// If its dependencies are not satisfied, go to the next PEIM.
//
if (Status == EFI_SUCCESS) {
DEBUG_CODE (
//
// Fill list of found Peims for later list of those not installed
//
CopyMem (
&DebugFoundPeimList[DispatchData->CurrentPeim],
&DispatchData->CurrentPeimAddress->Name,
sizeof (EFI_GUID)
);
);
if (!Dispatched (
DispatchData->CurrentPeim,
DispatchData->DispatchedPeimBitMap
)) {
if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) {
Status = PeiLoadImage (
&PrivateData->PS,
DispatchData->CurrentPeimAddress,
&TempPtr.Raw
);
if (Status == EFI_SUCCESS) {
//
// The PEIM has its dependencies satisfied, and its entry point
// has been found, so invoke it.
//
PERF_START (
(VOID *) (UINTN) (DispatchData->CurrentPeimAddress),
"PEIM",
NULL,
0
);
//
// BUGBUG: Used to be EFI_PEI_REPORT_STATUS_CODE_CODE
//
ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress;
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
EFI_PROGRESS_CODE,
EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN,
(VOID *)(&ExtendedData),
sizeof (ExtendedData)
);
//
// Is this a authentic image
//
Status = VerifyPeim (
&PrivateData->PS,
DispatchData->CurrentPeimAddress
);
if (Status != EFI_SECURITY_VIOLATION) {
Status = TempPtr.PeimEntry (
DispatchData->CurrentPeimAddress,
&PrivateData->PS
);
}
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
EFI_PROGRESS_CODE,
EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END,
(VOID *)(&ExtendedData),
sizeof (ExtendedData)
);
PERF_END ((VOID *) (UINTN) (DispatchData->CurrentPeimAddress), "PEIM", NULL, 0);
//
// Mark the PEIM as dispatched so we don't attempt to run it again
//
SetDispatched (
&PrivateData->PS,
DispatchData->CurrentPeim,
&DispatchData->DispatchedPeimBitMap
);
//
// Process the Notify list and dispatch any notifies for
// newly installed PPIs.
//
ProcessNotifyList (&PrivateData->PS);
//
// If real system memory was discovered and installed by this
// PEIM, switch the stacks to the new memory. Since we are
// at dispatch level, only the Core's private data is preserved,
// nobody else should have any data on the stack.
//
if (PrivateData->SwitchStackSignal) {
TempPtr.PeiCore = (PEI_CORE_ENTRY_POINT)PeiCore;
PrivateDataInMem = (UINTN) TransferOldDataToNewDataRange (PrivateData);
ASSERT (PrivateDataInMem != 0);
//
//Subtract 0x10 from the 4th parameter indicating the new stack base,
//in order to provide buffer protection against possible illegal stack
//access that might corrupt the stack.
//
SwitchStack (
(SWITCH_STACK_ENTRY_POINT)(UINTN)TempPtr.Raw,
PeiStartupDescriptor,
(VOID*)PrivateDataInMem,
(VOID*)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize)
);
}
}
}
}
DispatchData->CurrentPeim++;
continue;
} else {
//
// If we could not find another PEIM in the current FV, go try
// the FindFv PPI to look in other FVs for more PEIMs. If we can
// not locate the FindFv PPI, or if the FindFv PPI can not find
// anymore FVs, then exit the PEIM search loop.
//
if (DispatchData->FindFv == NULL) {
Status = PeiCoreLocatePpi (
&gEfiFindFvPpiGuid,
0,
NULL,
(VOID **)&DispatchData->FindFv
);
if (Status != EFI_SUCCESS) {
break;
}
}
NextFvFound = FALSE;
while (!NextFvFound) {
Status = DispatchData->FindFv->FindFv (
DispatchData->FindFv,
&PrivateData->PS,
&DispatchData->CurrentFv,
&NextFvAddress
);
//
// if there is no next fv, get out of this loop of finding FVs
//
if (Status != EFI_SUCCESS) {
break;
}
//
// don't process the default Fv again. (we don't know the order in which the hobs were created)
//
if ((NextFvAddress != DefaultFvAddress) &&
(NextFvAddress != DispatchData->CurrentFvAddress)) {
//
// VerifyFv() is currently returns SUCCESS all the time, add code to it to
// actually verify the given FV
//
Status = VerifyFv (NextFvAddress);
if (Status == EFI_SUCCESS) {
NextFvFound = TRUE;
DispatchData->CurrentFvAddress = NextFvAddress;
DispatchData->CurrentPeimAddress = NULL;
//
// current PRIM number (CurrentPeim) must continue as is, don't reset it here
//
}
}
}
//
// if there is no next fv, get out of this loop of dispatching PEIMs
//
if (!NextFvFound) {
break;
}
//
// continue in the inner for(;;) loop with a new FV;
//
}
}
//
// If all the PEIMs that we have found have been dispatched, then
// there is nothing left to dispatch and we don't need to go search
// through all PEIMs again.
//
if ((~(DispatchData->DispatchedPeimBitMap) &
((1 << DispatchData->CurrentPeim)-1)) == 0) {
break;
}
//
// Check if no more PEIMs that depex was satisfied
//
if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) {
break;
}
//
// Case when Depex is not satisfied and has to traverse the list again
//
DispatchData->CurrentPeim = 0;
DispatchData->CurrentPeimAddress = 0;
DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap;
//
// don't go back to the loop without making sure that the CurrentFvAddress is the
// same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and
// mess it up, always start processing the PEIMs from the default FV just like in the first time around.
//
DispatchData->CurrentFv = 0;
DispatchData->CurrentFvAddress = DefaultFvAddress;
}
DEBUG_CODE (
//
// Debug data for uninstalled Peim list
//
UINT32 DebugNotDispatchedBitmap;
UINT8 DebugFoundPeimPoint;
DebugFoundPeimPoint = 0;
//
// Get bitmap of Peims that were not dispatched,
//
DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ ((1 << DispatchData->CurrentPeim)-1));
//
// Scan bitmap of Peims not installed and print GUIDS
//
while (DebugNotDispatchedBitmap != 0) {
if ((DebugNotDispatchedBitmap & 1) != 0) {
DEBUG ((EFI_D_INFO, "WARNING -> InstallPpi: Not Installed: %g\n",
&DebugFoundPeimList[DebugFoundPeimPoint]
));
}
DebugFoundPeimPoint++;
DebugNotDispatchedBitmap >>= 1;
}
);
return EFI_NOT_FOUND;
}
VOID
InitializeDispatcherData (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_CORE_INSTANCE *OldCoreData,
IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor
)
/*++
Routine Description:
Initialize the Dispatcher's data members
Arguments:
PeiServices - The PEI core services table.
OldCoreData - Pointer to old core data (before switching stack).
NULL if being run in non-permament memory mode.
PeiStartupDescriptor - Information and services provided by SEC phase.
Returns:
None.
--*/
{
PEI_CORE_INSTANCE *PrivateData;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
if (OldCoreData == NULL) {
PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume;
PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume;
} else {
//
// Current peim has been dispatched, but not count
//
PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1);
}
return;
}
BOOLEAN
Dispatched (
IN UINT8 CurrentPeim,
IN UINT32 DispatchedPeimBitMap
)
/*++
Routine Description:
This routine checks to see if a particular PEIM has been dispatched during
the PEI core dispatch.
Arguments:
CurrentPeim - The PEIM/FV in the bit array to check.
DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.
Returns:
TRUE - PEIM already dispatched
FALSE - Otherwise
--*/
{
return (BOOLEAN)((DispatchedPeimBitMap & (1 << CurrentPeim)) != 0);
}
VOID
SetDispatched (
IN EFI_PEI_SERVICES **PeiServices,
IN UINT8 CurrentPeim,
OUT UINT32 *DispatchedPeimBitMap
)
/*++
Routine Description:
This routine sets a PEIM as having been dispatched once its entry
point has been invoked.
Arguments:
PeiServices - The PEI core services table.
CurrentPeim - The PEIM/FV in the bit array to check.
DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.
Returns:
None
--*/
{
//
// Check if the total number of PEIMs exceed the bitmap.
// CurrentPeim is 0-based
//
DEBUG_CODE (
if (CurrentPeim > (sizeof (*DispatchedPeimBitMap) * 8 - 1)) {
ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
}
);
*DispatchedPeimBitMap |= (1 << CurrentPeim);
return;
}
BOOLEAN
DepexSatisfied (
IN EFI_PEI_SERVICES **PeiServices,
IN VOID *CurrentPeimAddress
)
/*++
Routine Description:
This routine parses the Dependency Expression, if available, and
decides if the module can be executed.
Arguments:
PeiServices - The PEI Service Table
CurrentPeimAddress - Address of the PEIM Firmware File under investigation
Returns:
TRUE - Can be dispatched
FALSE - Cannot be dispatched
--*/
{
EFI_STATUS Status;
INT8 *DepexData;
BOOLEAN Runnable;
Status = PeiCoreFfsFindSectionData (
EFI_SECTION_PEI_DEPEX,
CurrentPeimAddress,
(VOID **)&DepexData
);
//
// If there is no DEPEX, assume the module can be executed
//
if (EFI_ERROR (Status)) {
return TRUE;
}
//
// Evaluate a given DEPEX
//
Status = PeimDispatchReadiness (
PeiServices,
DepexData,
&Runnable
);
return Runnable;
}
VOID *
TransferOldDataToNewDataRange (
IN PEI_CORE_INSTANCE *PrivateData
)
/*++
Routine Description:
This routine transfers the contents of the pre-permanent memory
PEI Core private data to a post-permanent memory data location.
Arguments:
PrivateData - Pointer to the current PEI Core private data pre-permanent memory
Returns:
Pointer to the PrivateData once the private data has been transferred to permanent memory
--*/
{
return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE));
}

View File

@@ -0,0 +1,474 @@
/*++
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:
FwVol.c
Abstract:
Pei Core Firmware File System service routines.
--*/
#include <PeiMain.h>
#define GETOCCUPIEDSIZE(ActualSize, Alignment) \
(ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
STATIC
EFI_FFS_FILE_STATE
GetFileState(
IN UINT8 ErasePolarity,
IN EFI_FFS_FILE_HEADER *FfsHeader
)
/*++
Routine Description:
Returns the highest bit set of the State field
Arguments:
ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY
in the Attributes field.
FfsHeader - Pointer to FFS File Header.
Returns:
Returns the highest bit in the State field
--*/
{
EFI_FFS_FILE_STATE FileState;
EFI_FFS_FILE_STATE HighestBit;
FileState = FfsHeader->State;
if (ErasePolarity != 0) {
FileState = (EFI_FFS_FILE_STATE)~FileState;
}
HighestBit = 0x80;
while (HighestBit != 0 && (HighestBit & FileState) == 0) {
HighestBit >>= 1;
}
return HighestBit;
}
STATIC
UINT8
CalculateHeaderChecksum (
IN EFI_FFS_FILE_HEADER *FileHeader
)
/*++
Routine Description:
Calculates the checksum of the header of a file.
Arguments:
FileHeader - Pointer to FFS File Header.
Returns:
Checksum of the header.
The header is zero byte checksum.
- Zero means the header is good.
- Non-zero means the header is bad.
Bugbug: For PEI performance reason, we comments this code at this time.
--*/
{
UINT8 *ptr;
UINTN Index;
UINT8 Sum;
Sum = 0;
ptr = (UINT8 *)FileHeader;
for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) {
Sum = (UINT8)(Sum + ptr[Index]);
Sum = (UINT8)(Sum + ptr[Index+1]);
Sum = (UINT8)(Sum + ptr[Index+2]);
Sum = (UINT8)(Sum + ptr[Index+3]);
}
for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {
Sum = (UINT8)(Sum + ptr[Index]);
}
//
// State field (since this indicates the different state of file).
//
Sum = (UINT8)(Sum - FileHeader->State);
//
// Checksum field of the file is not part of the header checksum.
//
Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);
return Sum;
}
STATIC
EFI_STATUS
PeiFfsFindNextFileEx (
IN EFI_FV_FILETYPE SearchType,
IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
IN OUT EFI_FFS_FILE_HEADER **FileHeader,
IN BOOLEAN Flag
)
/*++
Routine Description:
Given the input file pointer, search for the next matching file in the
FFS volume as defined by SearchType. The search starts from FileHeader inside
the Firmware Volume defined by FwVolHeader.
Arguments:
PeiServices - Pointer to the PEI Core Services Table.
SearchType - Filter to find only files of this type.
Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
FwVolHeader - Pointer to the FV header of the volume to search.
This parameter must point to a valid FFS volume.
FileHeader - Pointer to the current file from which to begin searching.
This pointer will be updated upon return to reflect the file found.
Flag - Indicator for if this is for PEI Dispath search
Returns:
EFI_NOT_FOUND - No files matching the search criteria were found
EFI_SUCCESS
--*/
{
EFI_FFS_FILE_HEADER *FfsFileHeader;
UINT32 FileLength;
UINT32 FileOccupiedSize;
UINT32 FileOffset;
UINT64 FvLength;
UINT8 ErasePolarity;
UINT8 FileState;
FvLength = FwVolHeader->FvLength;
if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
ErasePolarity = 1;
} else {
ErasePolarity = 0;
}
//
// If FileHeader is not specified (NULL) start with the first file in the
// firmware volume. Otherwise, start from the FileHeader.
//
if (*FileHeader == NULL) {
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
} else {
//
// Length is 24 bits wide so mask upper 8 bits
// FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
//
FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;
FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
}
FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
ASSERT (FileOffset <= 0xFFFFFFFF);
while (FileOffset < (FvLength - sizeof(EFI_FFS_FILE_HEADER))) {
//
// Get FileState which is the highest bit of the State
//
FileState = GetFileState (ErasePolarity, FfsFileHeader);
switch (FileState) {
case EFI_FILE_HEADER_INVALID:
FileOffset += sizeof(EFI_FFS_FILE_HEADER);
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));
break;
case EFI_FILE_DATA_VALID:
case EFI_FILE_MARKED_FOR_UPDATE:
if (CalculateHeaderChecksum (FfsFileHeader) == 0) {
FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
if (Flag) {
if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) ||
(FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) {
*FileHeader = FfsFileHeader;
return EFI_SUCCESS;
}
} else {
if ((SearchType == FfsFileHeader->Type) ||
(SearchType == EFI_FV_FILETYPE_ALL)) {
*FileHeader = FfsFileHeader;
return EFI_SUCCESS;
}
}
FileOffset += FileOccupiedSize;
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
} else {
ASSERT (FALSE);
return EFI_NOT_FOUND;
}
break;
case EFI_FILE_DELETED:
FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
FileOffset += FileOccupiedSize;
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
break;
default:
return EFI_NOT_FOUND;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
EFIAPI
PeiFfsFindSectionData (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_SECTION_TYPE SectionType,
IN EFI_FFS_FILE_HEADER *FfsFileHeader,
IN OUT VOID **SectionData
)
/*++
Routine Description:
Given the input file pointer, search for the next matching section in the
FFS volume.
Arguments:
PeiServices - Pointer to the PEI Core Services Table.
SearchType - Filter to find only sections of this type.
FfsFileHeader - Pointer to the current file to search.
SectionData - Pointer to the Section matching SectionType in FfsFileHeader.
- NULL if section not found
Returns:
EFI_NOT_FOUND - No files matching the search criteria were found
EFI_SUCCESS
--*/
{
UINT32 FileSize;
EFI_COMMON_SECTION_HEADER *Section;
UINT32 SectionLength;
UINT32 ParsedLength;
//
// Size is 24 bits wide so mask upper 8 bits.
// Does not include FfsFileHeader header size
// FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
//
Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);
FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
FileSize -= sizeof(EFI_FFS_FILE_HEADER);
*SectionData = NULL;
ParsedLength = 0;
while (ParsedLength < FileSize) {
if (Section->Type == SectionType) {
*SectionData = (VOID *)(Section + 1);
return EFI_SUCCESS;
}
//
// Size is 24 bits wide so mask upper 8 bits.
// SectionLength is adjusted it is 4 byte aligned.
// Go to the next section
//
SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
SectionLength = GETOCCUPIEDSIZE (SectionLength, 4);
ASSERT (SectionLength != 0);
ParsedLength += SectionLength;
Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
}
return EFI_NOT_FOUND;
}
EFI_STATUS
FindNextPeim (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader
)
/*++
Routine Description:
Given the input file pointer, search for the next matching file in the
FFS volume. The search starts from FileHeader inside
the Firmware Volume defined by FwVolHeader.
Arguments:
PeiServices - Pointer to the PEI Core Services Table.
FwVolHeader - Pointer to the FV header of the volume to search.
This parameter must point to a valid FFS volume.
PeimFileHeader - Pointer to the current file from which to begin searching.
This pointer will be updated upon return to reflect the file found.
Returns:
EFI_NOT_FOUND - No files matching the search criteria were found
EFI_SUCCESS
--*/
{
return PeiFfsFindNextFileEx (
0,
FwVolHeader,
PeimFileHeader,
TRUE
);
}
EFI_STATUS
EFIAPI
PeiFfsFindNextFile (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_FV_FILETYPE SearchType,
IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
IN OUT EFI_FFS_FILE_HEADER **FileHeader
)
/*++
Routine Description:
Given the input file pointer, search for the next matching file in the
FFS volume as defined by SearchType. The search starts from FileHeader inside
the Firmware Volume defined by FwVolHeader.
Arguments:
PeiServices - Pointer to the PEI Core Services Table.
SearchType - Filter to find only files of this type.
Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
FwVolHeader - Pointer to the FV header of the volume to search.
This parameter must point to a valid FFS volume.
FileHeader - Pointer to the current file from which to begin searching.
This pointer will be updated upon return to reflect the file found.
Returns:
EFI_NOT_FOUND - No files matching the search criteria were found
EFI_SUCCESS
--*/
{
return PeiFfsFindNextFileEx (
SearchType,
FwVolHeader,
FileHeader,
FALSE
);
}
EFI_STATUS
EFIAPI
PeiFvFindNextVolume (
IN EFI_PEI_SERVICES **PeiServices,
IN UINTN Instance,
IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
)
/*++
Routine Description:
Return the BFV location
BugBug -- Move this to the location of this code to where the
other FV and FFS support code lives.
Also, update to use FindFV for instances #'s >= 1.
Arguments:
PeiServices - The PEI core services table.
Instance - Instance of FV to find
FwVolHeader - Pointer to contain the data to return
Returns:
Pointer to the Firmware Volume instance requested
EFI_INVALID_PARAMETER - FwVolHeader is NULL
EFI_SUCCESS - Firmware volume instance successfully found.
--*/
{
PEI_CORE_INSTANCE *PrivateData;
EFI_STATUS Status;
EFI_PEI_FIND_FV_PPI *FindFvPpi;
UINT8 LocalInstance;
LocalInstance = (UINT8) Instance;
Status = EFI_SUCCESS;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
if (FwVolHeader == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Instance == 0) {
*FwVolHeader = PrivateData->DispatchData.BootFvAddress;
return Status;
} else {
//
// Locate all instances of FindFV
// Alternately, could use FV HOBs, but the PPI is cleaner
//
Status = PeiCoreLocatePpi (
&gEfiFindFvPpiGuid,
0,
NULL,
(VOID **)&FindFvPpi
);
if (Status != EFI_SUCCESS) {
Status = EFI_NOT_FOUND;
} else {
Status = FindFvPpi->FindFv (
FindFvPpi,
PeiServices,
&LocalInstance,
FwVolHeader
);
}
}
return Status;
}

View File

@@ -0,0 +1,189 @@
/*++
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:
Hob.c
Abstract:
EFI PEI Core HOB services
--*/
#include <PeiMain.h>
EFI_STATUS
EFIAPI
PeiGetHobList (
IN EFI_PEI_SERVICES **PeiServices,
IN OUT VOID **HobList
)
/*++
Routine Description:
Gets the pointer to the HOB List.
Arguments:
PeiServices - The PEI core services table.
HobList - Pointer to the HOB List.
Returns:
EFI_SUCCESS - Get the pointer of HOB List
EFI_NOT_AVAILABLE_YET - the HOB List is not yet published
EFI_INVALID_PARAMETER - HobList is NULL (in debug mode)
--*/
{
PEI_CORE_INSTANCE *PrivateData;
//
// Only check this parameter in debug mode
//
DEBUG_CODE (
if (HobList == NULL) {
return EFI_INVALID_PARAMETER;
}
);
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
*HobList = PrivateData->HobList.Raw;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PeiCreateHob (
IN EFI_PEI_SERVICES **PeiServices,
IN UINT16 Type,
IN UINT16 Length,
IN OUT VOID **Hob
)
/*++
Routine Description:
Add a new HOB to the HOB List.
Arguments:
PeiServices - The PEI core services table.
Type - Type of the new HOB.
Length - Length of the new HOB to allocate.
Hob - Pointer to the new HOB.
Returns:
Status - EFI_SUCCESS
- EFI_INVALID_PARAMETER if Hob is NULL
- EFI_NOT_AVAILABLE_YET if HobList is still not available.
- EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist.
--*/
{
EFI_STATUS Status;
EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
EFI_HOB_GENERIC_HEADER *HobEnd;
EFI_PHYSICAL_ADDRESS FreeMemory;
Status = PeiGetHobList (PeiServices, Hob);
if (EFI_ERROR(Status)) {
return Status;
}
HandOffHob = *Hob;
Length = (UINT16)((Length + 0x7) & (~0x7));
FreeMemory = HandOffHob->EfiFreeMemoryTop -
HandOffHob->EfiFreeMemoryBottom;
if (FreeMemory < Length) {
return EFI_OUT_OF_RESOURCES;
}
*Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type;
((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length;
((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0;
HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length);
HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
HobEnd->Reserved = 0;
HobEnd++;
HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
return EFI_SUCCESS;
}
EFI_STATUS
PeiCoreBuildHobHandoffInfoTable (
IN EFI_BOOT_MODE BootMode,
IN EFI_PHYSICAL_ADDRESS MemoryBegin,
IN UINT64 MemoryLength
)
/*++
Routine Description:
Builds a Handoff Information Table HOB
Arguments:
BootMode - Current Bootmode
MemoryBegin - Start Memory Address.
MemoryLength - Length of Memory.
Returns:
EFI_SUCCESS
--*/
{
EFI_HOB_HANDOFF_INFO_TABLE *Hob;
EFI_HOB_GENERIC_HEADER *HobEnd;
Hob = (VOID *)(UINTN)MemoryBegin;
HobEnd = (EFI_HOB_GENERIC_HEADER*) (Hob+1);
Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF;
Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE);
Hob->Header.Reserved = 0;
HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
HobEnd->Reserved = 0;
Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION;
Hob->BootMode = BootMode;
Hob->EfiMemoryTop = MemoryBegin + MemoryLength;
Hob->EfiMemoryBottom = MemoryBegin;
Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength;
Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd+1);
Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,237 @@
/*++
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:
Image.c
Abstract:
Pei Core Load Image Support
--*/
#include <PeiMain.h>
EFI_STATUS
PeiLoadImage (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_FFS_FILE_HEADER *PeimFileHeader,
OUT VOID **EntryPoint
)
/*++
Routine Description:
Routine for loading file image.
Arguments:
PeiServices - The PEI core services table.
PeimFileHeader - Pointer to the FFS file header of the image.
EntryPoint - Pointer to entry point of specified image file for output.
Returns:
Status - EFI_SUCCESS - Image is successfully loaded.
EFI_NOT_FOUND - Fail to locate necessary PPI
Others - Fail to load file.
--*/
{
EFI_STATUS Status;
VOID *Pe32Data;
EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi;
//#ifdef EFI_NT_EMULATOR
// EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor;
// NT_PEI_LOAD_FILE_PPI *PeiNtService;
//#endif
EFI_PHYSICAL_ADDRESS ImageAddress;
UINT64 ImageSize;
EFI_PHYSICAL_ADDRESS ImageEntryPoint;
EFI_TE_IMAGE_HEADER *TEImageHeader;
*EntryPoint = NULL;
TEImageHeader = NULL;
//
// Try to find a PE32 section.
//
Status = PeiCoreFfsFindSectionData (
EFI_SECTION_PE32,
PeimFileHeader,
&Pe32Data
);
//
// If we didn't find a PE32 section, try to find a TE section.
//
if (EFI_ERROR (Status)) {
Status = PeiCoreFfsFindSectionData (
EFI_SECTION_TE,
PeimFileHeader,
(VOID **) &TEImageHeader
);
if (EFI_ERROR (Status) || TEImageHeader == NULL) {
//
// There was not a PE32 or a TE section, so assume that it's a Compressed section
// and use the LoadFile
//
Status = PeiCoreLocatePpi (
&gEfiPeiFvFileLoaderPpiGuid,
0,
NULL,
(VOID **)&FvLoadFilePpi
);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
Status = FvLoadFilePpi->FvLoadFile (
FvLoadFilePpi,
PeimFileHeader,
&ImageAddress,
&ImageSize,
&ImageEntryPoint
);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
//
// Retrieve the entry point from the PE/COFF image header
//
Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)ImageAddress, EntryPoint);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
} else {
//
// Retrieve the entry point from the TE image header
//
ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader;
*EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +
TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize);
}
} else {
//
// Retrieve the entry point from the PE/COFF image header
//
ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;
Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
}
//
// Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
//
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint));
DEBUG_CODE (
EFI_IMAGE_DATA_DIRECTORY * DirectoryEntry;
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY * DebugEntry;
UINTN DirCount;
UINTN Index;
UINTN Index1;
BOOLEAN FileNameFound;
CHAR8 *AsciiString;
CHAR8 AsciiBuffer[512];
VOID *CodeViewEntryPointer;
INTN TEImageAdjust;
EFI_IMAGE_DOS_HEADER *DosHeader;
EFI_IMAGE_NT_HEADERS *PeHeader;
DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
//
// DOS image header is present, so read the PE header after the DOS image header
//
PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff));
} else {
//
// DOS image header is not present, so PE header is at the image base
//
PeHeader = (EFI_IMAGE_NT_HEADERS *) Pe32Data;
}
//
// Find the codeview info in the image and display the file name
// being loaded.
//
// Per the PE/COFF spec, you can't assume that a given data directory
// is present in the image. You have to check the NumberOfRvaAndSizes in
// the optional header to verify a desired directory entry is there.
//
DebugEntry = NULL;
DirectoryEntry = NULL;
TEImageAdjust = 0;
if (TEImageHeader == NULL) {
if (PeHeader->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHeader->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress);
}
} else {
if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize;
DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader +
TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
TEImageAdjust);
}
}
if (DebugEntry != NULL && DirectoryEntry != NULL) {
for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) {
if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
if (DebugEntry->SizeOfData > 0) {
CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust);
switch (* (UINT32 *) CodeViewEntryPointer) {
case CODEVIEW_SIGNATURE_NB10:
AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
break;
case CODEVIEW_SIGNATURE_RSDS:
AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
break;
default:
AsciiString = NULL;
break;
}
if (AsciiString != NULL) {
FileNameFound = FALSE;
for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) {
if (AsciiString[Index] == '\\') {
Index1 = Index;
FileNameFound = TRUE;
}
}
if (FileNameFound) {
for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) {
AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index];
}
AsciiBuffer[Index - (Index1 + 1)] = 0;
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));
break;
}
}
}
}
}
}
);
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,93 @@
//++
// 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:
//
// IpfCpuCore.i
//
// Abstract:
// IPF CPU definitions
//
//--
#ifndef _IPF_CPU_CORE_
#define _IPF_CPU_CORE_
#define PEI_BSP_STORE_SIZE 0x4000
#define ResetFn 0x00
#define MachineCheckFn 0x01
#define InitFn 0x02
#define RecoveryFn 0x03
#define GuardBand 0x10
//
// Define hardware RSE Configuration Register
//
//
// RS Configuration (RSC) bit field positions
//
#define RSC_MODE 0
#define RSC_PL 2
#define RSC_BE 4
//
// RSC bits 5-15 reserved
//
#define RSC_MBZ0 5
#define RSC_MBZ0_V 0x3ff
#define RSC_LOADRS 16
#define RSC_LOADRS_LEN 14
//
// RSC bits 30-63 reserved
//
#define RSC_MBZ1 30
#define RSC_MBZ1_V 0x3ffffffffULL
//
// RSC modes
//
//
// Lazy
//
#define RSC_MODE_LY (0x0)
//
// Store intensive
//
#define RSC_MODE_SI (0x1)
//
// Load intensive
//
#define RSC_MODE_LI (0x2)
//
// Eager
//
#define RSC_MODE_EA (0x3)
//
// RSC Endian bit values
//
#define RSC_BE_LITTLE 0
#define RSC_BE_BIG 1
//
// RSC while in kernel: enabled, little endian, pl = 0, eager mode
//
#define RSC_KERNEL ((RSC_MODE_EA<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE))
//
// Lazy RSC in kernel: enabled, little endian, pl = 0, lazy mode
//
#define RSC_KERNEL_LAZ ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE))
//
// RSE disabled: disabled, pl = 0, little endian, eager mode
//
#define RSC_KERNEL_DISABLED ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE))
#endif

View File

@@ -0,0 +1,192 @@
//++
// 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:
//
// IpfCpuCore.s
//
// Abstract:
// IPF Specific assembly routines
//
//--
.file "IpfCpuCore.s"
#include "IpfMacro.i"
#include "IpfCpuCore.i"
//----------------------------------------------------------------------------------
// This module supports terminating CAR (Cache As RAM) stage. It copies all the
// CAR data into real RAM and then makes a stack switch.
// EFI_STATUS
// SwitchCoreStacks (
// IN VOID *EntryPoint,
// IN UINTN CopySize,
// IN VOID *OldBase,
// IN VOID *NewBase
// IN UINTN NewSP, OPTIONAL
// IN UINTN NewBSP OPTIONAL
// )
// EFI_STATUS
// SwitchCoreStacks (
// IN VOID *EntryPointForContinuationFunction,
// IN UINTN StartupDescriptor,
// IN VOID PEICorePointer,
// IN UINTN NewSP
// )
//----------------------------------------------------------------------------------
PROCEDURE_ENTRY (SwitchCoreStacks)
NESTED_SETUP (4,2,0,0)
// first save all stack registers in GPRs.
mov r13 = in0;; // this is a pointer to the PLABEL of the continuation function.
ld8 r16 = [r13],8;; // r16 = address of continuation function from the PLABEL
ld8 gp = [r13];; // gp = gp of continuation function from the PLABEL
mov b1 = r16;;
// save the parameters in r5, r6. these 2 seemed to be preserved across PAL calls
mov r5 = in1;; // this is the parameter1 to pass to the continuation function
mov r6 = in2;; // this is the parameter2 to pass to the continuation function
dep r6=0,r6,63,1;; // zero the bit 63.
mov r8 = in3;; // new stack pointer.
// r8 has the sp, this is 128K stack size, from this we will reserve 16K for the bspstore
movl r15 = PEI_BSP_STORE_SIZE;;
sub r8 = r8, r15;;
add r15 = (GuardBand),r8;; // some little buffer, now r15 will be our bspstore
// save the bspstore value to r4, save sp value to r7
mov r4 = r15
mov r7 = r8
mov r16 = r8;; // will be the new sp in uncache mode
alloc r11=0,0,0,0;; // Set 0-size frame
flushrs;;
mov r21 = RSC_KERNEL_DISABLED;; // for rse disable
mov ar.rsc = r21;; // turn off RSE
add sp = r0, r16 // transfer to the EFI stack
mov ar.bspstore = r15 // switch to EFI BSP
invala // change of ar.bspstore needs invala.
mov r19 = RSC_KERNEL_LAZ;; // RSC enabled, Lazy mode
mov ar.rsc = r19;; // turn rse on, in kernel mode
//-----------------------------------------------------------------------------------
// Save here the meaningful stuff for next few lines and then make the PAL call.
// Make PAL call to terminate the CAR status.
// AVL: do this only for recovery check call...
mov r28=ar.k3;;
dep r2 = r28,r0,0,8;; // Extract Function bits from GR20.
cmp.eq p6,p7 = RecoveryFn,r2;; // Is it Recovery check
(p7) br.sptk.few DoneCARTermination; // if not, don't terminate car..
TerminateCAR::
mov r28 = ip;;
add r28 = (DoneCARTerminationPALCall - TerminateCAR),r28;;
mov b0 = r28
mov r8 = ar.k5;;
mov b6 = r8
mov r28 = 0x208
mov r29 = r0
mov r30 = r0
mov r31 = r0
mov r8 = r0;;
br.sptk.few b6;; // Call PAL-A call.
DoneCARTerminationPALCall::
// don't check error in soft sdv, it is always returning -1 for this call for some reason
#if SOFT_SDV
#else
ReturnToPEIMain::
cmp.eq p6,p7 = r8,r0;;
//
// dead loop if the PAL call failed, we have the CAR on but the stack is now pointing to memory
//
(p7) br.sptk.few ReturnToPEIMain;;
//
// PAL call successed,now the stack are in memory so come into cache mode
// instead of uncache mode
//
alloc r11=0,0,0,0;; // Set 0-size frame
flushrs;;
mov r21 = RSC_KERNEL_DISABLED;; // for rse disable
mov ar.rsc = r21;; // turn off RSE
dep r6 = 0,r6,63,1 // zero the bit 63
dep r7 = 0,r7,63,1 // zero the bit 63
dep r4 = 0,r4,63,1;; // zero the bit 63
add sp = r0, r7 // transfer to the EFI stack in cache mode
mov ar.bspstore = r4 // switch to EFI BSP
invala // change of ar.bspstore needs invala.
mov r19 = RSC_KERNEL_LAZ;; // RSC enabled, Lazy mode
mov ar.rsc = r19;; // turn rse on, in kernel mode
#endif
DoneCARTermination::
// allocate a stack frame:
alloc r11=0,2,2,0 ;; // alloc outs going to ensuing DXE IPL service
// on the new stack
mov out0 = r5;;
mov out1 = r6;;
mov r16 = b1;;
mov b6 = r16;;
br.call.sptk.few b0=b6;; // Call the continuation function
NESTED_RETURN
PROCEDURE_EXIT(SwitchCoreStacks)
//-----------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
//++
// GetHandOffStatus
//
// This routine is called by all processors simultaneously, to get some hand-off
// status that has been captured by IPF dispatcher and recorded in kernel registers.
//
// Arguments :
//
// On Entry : None.
//
// Return Value: Lid, R20Status.
//
//--
//----------------------------------------------------------------------------------
PROCEDURE_ENTRY (GetHandOffStatus)
NESTED_SETUP (0,2+0,0,0)
mov r8 = ar.k6 // Health Status (Self test params)
mov r9 = ar.k4 // LID bits
mov r10 = ar.k3;; // SAL_E entry state
mov r11 = ar.k7 // Return address to PAL
NESTED_RETURN
PROCEDURE_EXIT (GetHandOffStatus)
//----------------------------------------------------------------------------------

View File

@@ -0,0 +1,76 @@
/*++
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:
SwitchToCacheMode.c
Abstract:
Ipf CAR specific function used to switch to cache mode for the later memory access
Revision History
--*/
#include <PeiMain.h>
#include "IpfCpuCore.i"
extern
SAL_RETURN_REGS
GetHandOffStatus (
VOID
);
VOID
SwitchToCacheMode (
IN PEI_CORE_INSTANCE *CoreData
)
/*++
Routine Description:
Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR.
Arguments:
CoreData - The PEI core Private Data
Returns:
--*/
{
EFI_HOB_HANDOFF_INFO_TABLE *Phit;
if (CoreData == NULL) {
//
// the first call with CoreData as NULL.
//
return;
}
if ((GetHandOffStatus().r10 & 0xFF) == RecoveryFn) {
CoreData->StackBase = CoreData->StackBase & CACHE_MODE_ADDRESS_MASK;
CoreData->HobList.Raw = (UINT8 *)((UINTN)CoreData->HobList.Raw & CACHE_MODE_ADDRESS_MASK);
//
// Change the PHIT pointer value to cache mode
//
Phit = CoreData->HobList.HandoffInformationTable;
Phit->EfiMemoryTop = Phit->EfiMemoryTop & CACHE_MODE_ADDRESS_MASK;
Phit->EfiFreeMemoryTop = Phit->EfiFreeMemoryTop & CACHE_MODE_ADDRESS_MASK;
Phit->EfiMemoryBottom = Phit->EfiMemoryBottom & CACHE_MODE_ADDRESS_MASK;
Phit->EfiFreeMemoryBottom = Phit->EfiFreeMemoryBottom & CACHE_MODE_ADDRESS_MASK;
Phit->EfiEndOfHobList = Phit->EfiEndOfHobList & CACHE_MODE_ADDRESS_MASK;
}
return;
}

View File

@@ -0,0 +1,314 @@
/*++
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:
MemoryServices.c
Abstract:
EFI PEI Core memory services
--*/
#include <PeiMain.h>
VOID
InitializeMemoryServices (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
IN PEI_CORE_INSTANCE *OldCoreData
)
/*++
Routine Description:
Initialize the memory services.
Arguments:
PeiServices - The PEI core services table.
PeiStartupDescriptor - Information and services provided by SEC phase.
OldCoreData - Pointer to the PEI Core data.
NULL if being run in non-permament memory mode.
Returns:
None
--*/
{
PEI_CORE_INSTANCE *PrivateData;
UINT64 SizeOfCarHeap;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
PrivateData->SwitchStackSignal = FALSE;
if (OldCoreData == NULL) {
PrivateData->PeiMemoryInstalled = FALSE;
PrivateData->BottomOfCarHeap = (VOID *) (((UINTN)(VOID *)(&PrivateData))
& (~((PeiStartupDescriptor->SizeOfCacheAsRam) - 1)));
PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + PeiStartupDescriptor->SizeOfCacheAsRam);
//
// SizeOfCarHeap is 1/2 (arbitrary) of CacheAsRam Size.
//
SizeOfCarHeap = (UINT64) PeiStartupDescriptor->SizeOfCacheAsRam;
SizeOfCarHeap = RShiftU64 (SizeOfCarHeap, 1);
DEBUG_CODE (
PrivateData->SizeOfCacheAsRam = PeiStartupDescriptor->SizeOfCacheAsRam;
PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) SizeOfCarHeap);
);
PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap;
PeiCoreBuildHobHandoffInfoTable (
BOOT_WITH_FULL_CONFIGURATION,
(EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap,
(UINTN) SizeOfCarHeap
);
//
// Copy PeiServices from ROM to Cache in PrivateData
//
CopyMem (&(PrivateData->ServiceTableShadow), *PeiServices, sizeof (EFI_PEI_SERVICES));
//
// Set PS to point to ServiceTableShadow in Cache
//
PrivateData->PS = &(PrivateData->ServiceTableShadow);
} else {
//
// Set PS to point to ServiceTableShadow in Cache one time after the
// stack switched to main memory
//
PrivateData->PS = &(PrivateData->ServiceTableShadow);
}
return;
}
EFI_STATUS
EFIAPI
PeiInstallPeiMemory (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PHYSICAL_ADDRESS MemoryBegin,
IN UINT64 MemoryLength
)
/*++
Routine Description:
Install the permanent memory is now available.
Creates HOB (PHIT and Stack).
Arguments:
PeiServices - The PEI core services table.
MemoryBegin - Start of memory address.
MemoryLength - Length of memory.
Returns:
Status - EFI_SUCCESS
--*/
{
PEI_CORE_INSTANCE *PrivateData;
EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob;
EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob;
UINT64 PeiStackSize;
UINT64 EfiFreeMemorySize;
EFI_PHYSICAL_ADDRESS PhysicalAddressOfOldHob;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
PrivateData->SwitchStackSignal = TRUE;
PrivateData->PeiMemoryInstalled = TRUE;
PrivateData->StackBase = MemoryBegin;
PeiStackSize = RShiftU64 (MemoryLength, 1);
if (PEI_STACK_SIZE > PeiStackSize) {
PrivateData->StackSize = PeiStackSize;
} else {
PrivateData->StackSize = PEI_STACK_SIZE;
}
OldHandOffHob = PrivateData->HobList.HandoffInformationTable;
PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize));
NewHandOffHob = PrivateData->HobList.HandoffInformationTable;
PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob;
EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob;
DEBUG ((EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob));
DEBUG ((EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob));
CopyMem (
NewHandOffHob,
OldHandOffHob,
(UINTN)EfiFreeMemorySize
);
NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength;
NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop;
NewHandOffHob->EfiMemoryBottom = MemoryBegin;
NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize;
NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob +
(OldHandOffHob->EfiEndOfHobList -
PhysicalAddressOfOldHob);
ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob);
BuildStackHob (PrivateData->StackBase, PrivateData->StackSize);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PeiAllocatePages (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
OUT EFI_PHYSICAL_ADDRESS *Memory
)
/*++
Routine Description:
Memory allocation service on permanent memory,
not usable prior to the memory installation.
Arguments:
PeiServices - The PEI core services table.
MemoryType - Type of memory to allocate.
Pages - Number of pages to allocate.
Memory - Pointer of memory allocated.
Returns:
Status - EFI_SUCCESS The allocation was successful
EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported.
EFI_NOT_AVAILABLE_YET Called with permanent memory not available
EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement
to allocate the number of pages.
--*/
{
PEI_CORE_INSTANCE *PrivateData;
EFI_PEI_HOB_POINTERS Hob;
EFI_PHYSICAL_ADDRESS Offset;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
//
// Check if Hob already available
//
if (!PrivateData->PeiMemoryInstalled) {
return EFI_NOT_AVAILABLE_YET;
}
Hob.Raw = PrivateData->HobList.Raw;
//
// Check to see if on 4k boundary
//
Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF;
//
// If not aligned, make the allocation aligned.
//
if (Offset != 0) {
Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset;
}
//
// Verify that there is sufficient memory to satisfy the allocation
//
if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) <
Hob.HandoffInformationTable->EfiFreeMemoryBottom) {
return EFI_OUT_OF_RESOURCES;
} else {
//
// Update the PHIT to reflect the memory usage
//
Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;
//
// Update the value for the caller
//
*Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop;
//
// Create a memory allocation HOB.
//
BuildMemoryAllocationHob (
Hob.HandoffInformationTable->EfiFreeMemoryTop,
Pages * EFI_PAGE_SIZE + Offset,
MemoryType
);
return EFI_SUCCESS;
}
}
EFI_STATUS
EFIAPI
PeiAllocatePool (
IN EFI_PEI_SERVICES **PeiServices,
IN UINTN Size,
OUT VOID **Buffer
)
/*++
Routine Description:
Memory allocation service on the CAR.
Arguments:
PeiServices - The PEI core services table.
Size - Amount of memory required
Buffer - Address of pointer to the buffer
Returns:
Status - EFI_SUCCESS The allocation was successful
EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement
to allocate the requested size.
--*/
{
EFI_STATUS Status;
EFI_HOB_MEMORY_POOL *Hob;
Status = PeiCoreCreateHob (
EFI_HOB_TYPE_PEI_MEMORY_POOL,
(UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),
(VOID **)&Hob
);
*Buffer = Hob+1;
return Status;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
<?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.
-->
<ModuleBuildDescription 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">
<MbdHeader>
<BaseName>PeiMain</BaseName>
<Guid>52C05B14-0B98-496c-BC3B-04B50211D680</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:18</Modified>
</MbdHeader>
<Libraries>
<Library>PeiCoreEntryPoint</Library>
<Library>BaseLib</Library>
<Library>BaseMemoryLib</Library>
<Library>PeiServicesTablePointerLib</Library>
<Library>PeiCoreLib</Library>
<Library>PeiHobLib</Library>
<Library>PeiReportStatusCodeLib</Library>
<Library>BaseDebugLibReportStatusCode</Library>
<Library>BasePerformanceLibNull</Library>
<Arch ArchType="IA32">
<Library OverrideID="6666">BasePeCoffGetEntryPointLib</Library>
</Arch>
<Arch ArchType="X64">
<Library>BasePeCoffGetEntryPointLib</Library>
</Arch>
<Arch ArchType="IPF">
<Library>BasePeCoffGetEntryPointLib</Library>
</Arch>
<Arch ArchType="EBC">
<Library>BasePeCoffGetEntryPointLib</Library>
</Arch>
</Libraries>
</ModuleBuildDescription>

View File

@@ -0,0 +1,91 @@
<?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.
-->
<ModuleSurfaceArea 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">
<MsaHeader>
<BaseName>PeiMain</BaseName>
<ModuleType>PEI_CORE</ModuleType>
<ComponentType>PEI_CORE</ComponentType>
<Guid>52C05B14-0B98-496c-BC3B-04B50211D680</Guid>
<Version>0</Version>
<Abstract>Component description file for PeiMain module</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:18</Updated>
</MsaHeader>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreEntryPoint</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PeCoffGetEntryPointLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">TimerLib</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>PeiMain.h</Filename>
<Filename>BootMode\BootMode.c</Filename>
<Filename>Dependency\Dependency.c</Filename>
<Filename>Dispatcher\Dispatcher.c</Filename>
<Filename>FwVol\FwVol.c</Filename>
<Filename>Hob\Hob.c</Filename>
<Filename>Image\Image.c</Filename>
<Filename>Memory\MemoryServices.c</Filename>
<Filename>PeiMain\PeiMain.c</Filename>
<Filename>Ppi\Ppi.c</Filename>
<Filename>Reset\Reset.c</Filename>
<Filename>Security\Security.c</Filename>
<Filename>StatusCode\StatusCode.c</Filename>
<Arch ArchType="IPF">
<Filename>ipf\SwitchToCacheMode.c</Filename>
<Filename>ipf\IpfCpuCore.i</Filename>
<Filename>ipf\IpfCpuCore.s</Filename>
</Arch>
</SourceFiles>
<Includes>
<PackageName>MdePkg</PackageName>
<PackageName>EdkModulePkg</PackageName>
</Includes>
<Hobs>
<Hob Usage="ALWAYS_PRODUCED" HobType="PHIT"></Hob>
<Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
<C_Name>gPeiPerformanceHobGuid</C_Name>
<Guid>0xec4df5af, 0x4395, 0x4cc9, 0x94, 0xde, 0x77, 0x50, 0x6d, 0x12, 0xc7, 0xb8</Guid>
</Hob>
</Hobs>
<PPIs>
<Ppi Usage="ALWAYS_PRODUCED">MemoryDiscovered</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">FindFv</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">FvFileLoader</Ppi>
<Ppi Usage="ALWAYS_CONSUMED">DxeIpl</Ppi>
<Ppi Usage="SOMETIMES_CONSUMED">Reset</Ppi>
<Ppi Usage="SOMETIMES_CONSUMED">StatusCode</Ppi>
<PpiNotify Usage="SOMETIMES_CONSUMED">Security</PpiNotify>
</PPIs>
<Externs>
<Extern>
<ModuleEntryPoint>PeiCore</ModuleEntryPoint>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@@ -0,0 +1,243 @@
/*++
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:
PeiMain.c
Abstract:
Pei Core Main Entry Point
Revision History
--*/
#include <PeiMain.h>
//
//CAR is filled with this initial value during SEC phase
//
#define INIT_CAR_VALUE 0x5AA55AA5
static EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiMemoryDiscoveredPpiGuid,
NULL
};
//
// Pei Core Module Variables
//
//
static EFI_PEI_SERVICES mPS = {
{
PEI_SERVICES_SIGNATURE,
PEI_SERVICES_REVISION,
sizeof (EFI_PEI_SERVICES),
0,
0
},
PeiInstallPpi,
PeiReInstallPpi,
PeiLocatePpi,
PeiNotifyPpi,
PeiGetBootMode,
PeiSetBootMode,
PeiGetHobList,
PeiCreateHob,
PeiFvFindNextVolume,
PeiFfsFindNextFile,
PeiFfsFindSectionData,
PeiInstallPeiMemory,
PeiAllocatePages,
PeiAllocatePool,
(EFI_PEI_COPY_MEM)CopyMem,
(EFI_PEI_SET_MEM)SetMem,
PeiReportStatusCode,
PeiResetSystem
};
EFI_STATUS
EFIAPI
PeiCore (
IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
IN PEI_CORE_INSTANCE *OldCoreData
)
/*++
Routine Description:
The entry routine to Pei Core, invoked by PeiMain during transition
from SEC to PEI. After switching stack in the PEI core, it will restart
with the old core data.
Arguments:
PeiStartupDescriptor - Information and services provided by SEC phase.
OldCoreData - Pointer to old core data that is used to initialize the
core's data areas.
Returns:
This function never returns
EFI_NOT_FOUND - Never reach
--*/
{
PEI_CORE_INSTANCE PrivateData;
EFI_STATUS Status;
PEI_CORE_TEMP_POINTERS TempPtr;
PEI_CORE_DISPATCH_DATA *DispatchData;
UINT64 mTick;
mTick = 0;
#ifdef EFI_PEI_PERFORMANCE
if (OldCoreData == NULL) {
mTick = GetPerformanceCounter ();
}
#endif
//
// For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory()
// the 63-bit of address is set to 1.
//
SWITCH_TO_CACHE_MODE (OldCoreData);
if (OldCoreData != NULL) {
CopyMem (&PrivateData, OldCoreData, sizeof (PEI_CORE_INSTANCE));
} else {
ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE));
}
PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
PrivateData.PS = &mPS;
//
// Initialize libraries that the PeiCore is linked against
// BUGBUG: The FfsHeader is passed in as NULL. Do we look it up or remove it from the lib init?
//
ProcessLibraryConstructorList (NULL, &PrivateData.PS);
InitializeMemoryServices (&PrivateData.PS, PeiStartupDescriptor, OldCoreData);
InitializePpiServices (&PrivateData.PS, OldCoreData);
InitializeSecurityServices (&PrivateData.PS, OldCoreData);
InitializeDispatcherData (&PrivateData.PS, OldCoreData, PeiStartupDescriptor);
if (OldCoreData != NULL) {
PERF_END (NULL,"PreMem", NULL, 0);
PERF_START (NULL,"PostMem", NULL, 0);
//
// The following code dumps out interesting cache as RAM usage information
// so we can keep tabs on how the cache as RAM is being utilized. The
// DEBUG_CODE macro is used to prevent this code from being compiled
// on a debug build.
//
DEBUG_CODE (
UINTN *StackPointer;
UINTN StackValue;
StackValue = INIT_CAR_VALUE;
for (StackPointer = (UINTN *) OldCoreData->MaxTopOfCarHeap;
((UINTN) StackPointer < ((UINTN) OldCoreData->BottomOfCarHeap + OldCoreData->SizeOfCacheAsRam))
&& StackValue == INIT_CAR_VALUE;
StackPointer++) {
StackValue = *StackPointer;
}
DEBUG ((EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", OldCoreData->SizeOfCacheAsRam));
DEBUG ((EFI_D_INFO, " CAR stack ever used: %d bytes.\n",
((UINTN) OldCoreData->TopOfCarHeap - (UINTN) StackPointer)
));
DEBUG ((EFI_D_INFO, " CAR heap used: %d bytes.\n",
((UINTN) OldCoreData->HobList.HandoffInformationTable->EfiFreeMemoryBottom -
(UINTN) OldCoreData->HobList.Raw)
));
);
//
// Alert any listeners that there is permanent memory available
//
PERF_START (NULL,"DisMem", NULL, 0);
Status = PeiCoreInstallPpi (&mMemoryDiscoveredPpi);
PERF_END (NULL,"DisMem", NULL, 0);
} else {
//
// Report Status Code EFI_SW_PC_INIT
//
REPORT_STATUS_CODE (
EFI_PROGRESS_CODE,
EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT
);
//
// If first pass, start performance measurement.
//
PERF_START (NULL,"PreMem", NULL, mTick);
//
// If SEC provided any PPI services to PEI, install them.
//
if (PeiStartupDescriptor->DispatchTable != NULL) {
Status = PeiCoreInstallPpi (PeiStartupDescriptor->DispatchTable);
ASSERT_EFI_ERROR (Status);
}
}
DispatchData = &PrivateData.DispatchData;
//
// Call PEIM dispatcher
//
PeiDispatcher (PeiStartupDescriptor, &PrivateData, DispatchData);
//
// Check if InstallPeiMemory service was called.
//
ASSERT(PrivateData.PeiMemoryInstalled == TRUE);
PERF_END (NULL, "PostMem", NULL, 0);
Status = PeiCoreLocatePpi (
&gEfiDxeIplPpiGuid,
0,
NULL,
(VOID **)&TempPtr.DxeIpl
);
ASSERT_EFI_ERROR (Status);
DEBUG ((EFI_D_INFO, "DXE IPL Entry\n"));
Status = TempPtr.DxeIpl->Entry (
TempPtr.DxeIpl,
&PrivateData.PS,
PrivateData.HobList
);
ASSERT_EFI_ERROR (Status);
return EFI_NOT_FOUND;
}

View File

@@ -0,0 +1,658 @@
/*++
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:
Ppi.c
Abstract:
EFI PEI Core PPI services
Revision History
--*/
#include <PeiMain.h>
VOID
InitializePpiServices (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_CORE_INSTANCE *OldCoreData
)
/*++
Routine Description:
Initialize PPI services.
Arguments:
PeiServices - The PEI core services table.
OldCoreData - Pointer to the PEI Core data.
NULL if being run in non-permament memory mode.
Returns:
Nothing
--*/
{
PEI_CORE_INSTANCE *PrivateData;
if (OldCoreData == NULL) {
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1;
PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1;
PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1;
}
return;
}
VOID
ConvertPpiPointers (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob,
IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob
)
/*++
Routine Description:
Migrate the Hob list from the CAR stack to PEI installed memory.
Arguments:
PeiServices - The PEI core services table.
OldHandOffHob - The old handoff HOB list.
NewHandOffHob - The new handoff HOB list.
Returns:
--*/
{
PEI_CORE_INSTANCE *PrivateData;
UINT8 Index;
PEI_PPI_LIST_POINTERS *PpiPointer;
UINTN Fixup;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
Fixup = (UINTN)NewHandOffHob - (UINTN)OldHandOffHob;
for (Index = 0; Index < MAX_PPI_DESCRIPTORS; Index++) {
if (Index < PrivateData->PpiData.PpiListEnd ||
Index > PrivateData->PpiData.NotifyListEnd) {
PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index];
if (((UINTN)PpiPointer->Raw < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) &&
((UINTN)PpiPointer->Raw >= (UINTN)OldHandOffHob)) {
//
// Convert the pointer to the PEIM descriptor from the old HOB heap
// to the relocated HOB heap.
//
PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup);
//
// Only when the PEIM descriptor is in the old HOB should it be necessary
// to try to convert the pointers in the PEIM descriptor
//
if (((UINTN)PpiPointer->Ppi->Guid < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) &&
((UINTN)PpiPointer->Ppi->Guid >= (UINTN)OldHandOffHob)) {
//
// Convert the pointer to the GUID in the PPI or NOTIFY descriptor
// from the old HOB heap to the relocated HOB heap.
//
PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup);
}
//
// Assume that no code is located in the temporary memory, so the pointer to
// the notification function in the NOTIFY descriptor needs not be converted.
//
if (Index < PrivateData->PpiData.PpiListEnd &&
(UINTN)PpiPointer->Ppi->Ppi < (UINTN)OldHandOffHob->EfiFreeMemoryBottom &&
(UINTN)PpiPointer->Ppi->Ppi >= (UINTN)OldHandOffHob) {
//
// Convert the pointer to the PPI interface structure in the PPI descriptor
// from the old HOB heap to the relocated HOB heap.
//
PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup);
}
}
}
}
}
EFI_STATUS
EFIAPI
PeiInstallPpi (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_PPI_DESCRIPTOR *PpiList
)
/*++
Routine Description:
Install PPI services.
Arguments:
PeiServices - Pointer to the PEI Service Table
PpiList - Pointer to a list of PEI PPI Descriptors.
Returns:
EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
EFI_INVALID_PARAMETER - if PpiList is NULL pointer
EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
--*/
{
PEI_CORE_INSTANCE *PrivateData;
INTN Index;
INTN LastCallbackInstall;
if (PpiList == NULL) {
return EFI_INVALID_PARAMETER;
}
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
Index = PrivateData->PpiData.PpiListEnd;
LastCallbackInstall = Index;
//
// This is loop installs all PPI descriptors in the PpiList. It is terminated
// by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
// EFI_PEI_PPI_DESCRIPTOR in the list.
//
for (;;) {
//
// Since PpiData is used for NotifyList and InstallList, max resource
// is reached if the Install reaches the NotifyList
//
if (Index == PrivateData->PpiData.NotifyListEnd + 1) {
return EFI_OUT_OF_RESOURCES;
}
//
// Check if it is a valid PPI.
// If not, rollback list to exclude all in this list.
// Try to indicate which item failed.
//
if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
PrivateData->PpiData.PpiListEnd = LastCallbackInstall;
DEBUG((EFI_D_INFO, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi));
return EFI_INVALID_PARAMETER;
}
DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));
PrivateData->PpiData.PpiListPtrs[Index].Ppi = PpiList;
PrivateData->PpiData.PpiListEnd++;
//
// Continue until the end of the PPI List.
//
if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
break;
}
PpiList++;
Index++;
}
//
// Dispatch any callback level notifies for newly installed PPIs.
//
DispatchNotify (
PeiServices,
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
LastCallbackInstall,
PrivateData->PpiData.PpiListEnd,
PrivateData->PpiData.DispatchListEnd,
PrivateData->PpiData.NotifyListEnd
);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PeiReInstallPpi (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_PPI_DESCRIPTOR *OldPpi,
IN EFI_PEI_PPI_DESCRIPTOR *NewPpi
)
/*++
Routine Description:
Re-Install PPI services.
Arguments:
PeiServices - Pointer to the PEI Service Table
OldPpi - Pointer to the old PEI PPI Descriptors.
NewPpi - Pointer to the new PEI PPI Descriptors.
Returns:
EFI_SUCCESS - if the operation was successful
EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
EFI_INVALID_PARAMETER - if NewPpi is not valid
EFI_NOT_FOUND - if the PPI was not in the database
--*/
{
PEI_CORE_INSTANCE *PrivateData;
INTN Index;
if ((OldPpi == NULL) || (NewPpi == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
return EFI_INVALID_PARAMETER;
}
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
//
// Find the old PPI instance in the database. If we can not find it,
// return the EFI_NOT_FOUND error.
//
for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {
break;
}
}
if (Index == PrivateData->PpiData.PpiListEnd) {
return EFI_NOT_FOUND;
}
//
// Remove the old PPI from the database, add the new one.
//
DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));
PrivateData->PpiData.PpiListPtrs[Index].Ppi = NewPpi;
//
// Dispatch any callback level notifies for the newly installed PPI.
//
DispatchNotify (
PeiServices,
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
Index,
Index+1,
PrivateData->PpiData.DispatchListEnd,
PrivateData->PpiData.NotifyListEnd
);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PeiLocatePpi (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_GUID *Guid,
IN UINTN Instance,
IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
IN OUT VOID **Ppi
)
/*++
Routine Description:
Locate a given named PPI.
Arguments:
PeiServices - Pointer to the PEI Service Table
Guid - Pointer to GUID of the PPI.
Instance - Instance Number to discover.
PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
returns a pointer to the descriptor (includes flags, etc)
Ppi - Pointer to reference the found PPI
Returns:
Status - EFI_SUCCESS if the PPI is in the database
EFI_NOT_FOUND if the PPI is not in the database
--*/
{
PEI_CORE_INSTANCE *PrivateData;
INTN Index;
EFI_GUID *CheckGuid;
EFI_PEI_PPI_DESCRIPTOR *TempPtr;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
//
// Search the data base for the matching instance of the GUIDed PPI.
//
for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;
CheckGuid = TempPtr->Guid;
//
// Don't use CompareGuid function here for performance reasons.
// Instead we compare the GUID as INT32 at a time and branch
// on the first failed comparison.
//
if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&
(((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&
(((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&
(((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {
if (Instance == 0) {
if (PpiDescriptor != NULL) {
*PpiDescriptor = TempPtr;
}
if (Ppi != NULL) {
*Ppi = TempPtr->Ppi;
}
return EFI_SUCCESS;
}
Instance--;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
EFIAPI
PeiNotifyPpi (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList
)
/*++
Routine Description:
Install a notification for a given PPI.
Arguments:
PeiServices - Pointer to the PEI Service Table
NotifyList - Pointer to list of Descriptors to notify upon.
Returns:
Status - EFI_SUCCESS if successful
EFI_OUT_OF_RESOURCES if no space in the database
EFI_INVALID_PARAMETER if not a good decriptor
--*/
{
PEI_CORE_INSTANCE *PrivateData;
INTN Index;
INTN NotifyIndex;
INTN LastCallbackNotify;
EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr;
UINTN NotifyDispatchCount;
NotifyDispatchCount = 0;
if (NotifyList == NULL) {
return EFI_INVALID_PARAMETER;
}
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
Index = PrivateData->PpiData.NotifyListEnd;
LastCallbackNotify = Index;
//
// This is loop installs all Notify descriptors in the NotifyList. It is
// terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
// EFI_PEI_NOTIFY_DESCRIPTOR in the list.
//
for (;;) {
//
// Since PpiData is used for NotifyList and InstallList, max resource
// is reached if the Install reaches the PpiList
//
if (Index == PrivateData->PpiData.PpiListEnd - 1) {
return EFI_OUT_OF_RESOURCES;
}
//
// If some of the PPI data is invalid restore original Notify PPI database value
//
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {
PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;
DEBUG((EFI_D_INFO, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify));
return EFI_INVALID_PARAMETER;
}
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
NotifyDispatchCount ++;
}
PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyList;
PrivateData->PpiData.NotifyListEnd--;
DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
break;
}
//
// Go the next descriptor. Remember the NotifyList moves down.
//
NotifyList++;
Index--;
}
//
// If there is Dispatch Notify PPI installed put them on the bottom
//
if (NotifyDispatchCount > 0) {
for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {
if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;
for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){
PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;
}
PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;
PrivateData->PpiData.DispatchListEnd--;
}
}
LastCallbackNotify -= NotifyDispatchCount;
}
//
// Dispatch any callback level notifies for all previously installed PPIs.
//
DispatchNotify (
PeiServices,
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
0,
PrivateData->PpiData.PpiListEnd,
LastCallbackNotify,
PrivateData->PpiData.NotifyListEnd
);
return EFI_SUCCESS;
}
VOID
ProcessNotifyList (
IN EFI_PEI_SERVICES **PeiServices
)
/*++
Routine Description:
Process the Notify List at dispatch level.
Arguments:
PeiServices - Pointer to the PEI Service Table
Returns:
--*/
{
PEI_CORE_INSTANCE *PrivateData;
INTN TempValue;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
while (TRUE) {
//
// Check if the PEIM that was just dispatched resulted in any
// Notifies getting installed. If so, go process any dispatch
// level Notifies that match the previouly installed PPIs.
// Use "while" instead of "if" since DispatchNotify can modify
// DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
//
while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {
TempValue = PrivateData->PpiData.DispatchListEnd;
DispatchNotify (
PeiServices,
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
0,
PrivateData->PpiData.LastDispatchedInstall,
PrivateData->PpiData.LastDispatchedNotify,
PrivateData->PpiData.DispatchListEnd
);
PrivateData->PpiData.LastDispatchedNotify = TempValue;
}
//
// Check if the PEIM that was just dispatched resulted in any
// PPIs getting installed. If so, go process any dispatch
// level Notifies that match the installed PPIs.
// Use "while" instead of "if" since DispatchNotify can modify
// PpiListEnd (with InstallPpi) so we have to iterate until the same.
//
while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {
TempValue = PrivateData->PpiData.PpiListEnd;
DispatchNotify (
PeiServices,
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
PrivateData->PpiData.LastDispatchedInstall,
PrivateData->PpiData.PpiListEnd,
MAX_PPI_DESCRIPTORS-1,
PrivateData->PpiData.DispatchListEnd
);
PrivateData->PpiData.LastDispatchedInstall = TempValue;
}
if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {
break;
}
}
return;
}
VOID
DispatchNotify (
IN EFI_PEI_SERVICES **PeiServices,
IN UINTN NotifyType,
IN INTN InstallStartIndex,
IN INTN InstallStopIndex,
IN INTN NotifyStartIndex,
IN INTN NotifyStopIndex
)
/*++
Routine Description:
Dispatch notifications.
Arguments:
PeiServices - Pointer to the PEI Service Table
NotifyType - Type of notify to fire.
InstallStartIndex - Install Beginning index.
InstallStopIndex - Install Ending index.
NotifyStartIndex - Notify Beginning index.
NotifyStopIndex - Notify Ending index.
Returns: None
--*/
{
PEI_CORE_INSTANCE *PrivateData;
INTN Index1;
INTN Index2;
EFI_GUID *SearchGuid;
EFI_GUID *CheckGuid;
EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
//
// Remember that Installs moves up and Notifies moves down.
//
for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {
NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;
CheckGuid = NotifyDescriptor->Guid;
for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {
SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;
//
// Don't use CompareGuid function here for performance reasons.
// Instead we compare the GUID as INT32 at a time and branch
// on the first failed comparison.
//
if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&
(((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&
(((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&
(((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {
DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
SearchGuid,
NotifyDescriptor->Notify
));
NotifyDescriptor->Notify (
PeiServices,
NotifyDescriptor,
(PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi
);
}
}
}
return;
}

View File

@@ -0,0 +1,68 @@
/*++
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:
Reset.c
Abstract:
Pei Core Reset System Support
Revision History
--*/
#include <PeiMain.h>
EFI_STATUS
EFIAPI
PeiResetSystem (
IN EFI_PEI_SERVICES **PeiServices
)
/*++
Routine Description:
Core version of the Reset System
Arguments:
PeiServices - The PEI core services table.
Returns:
Status - EFI_NOT_AVAILABLE_YET. PPI not available yet.
- EFI_DEVICE_ERROR. Did not reset system.
Otherwise, resets the system.
--*/
{
EFI_STATUS Status;
EFI_PEI_RESET_PPI *ResetPpi;
Status = PeiCoreLocatePpi (
&gEfiPeiResetPpiGuid,
0,
NULL,
(VOID **)&ResetPpi
);
//
// LocatePpi returns EFI_NOT_FOUND on error
//
if (!EFI_ERROR (Status)) {
return ResetPpi->ResetSystem (PeiServices);
}
return EFI_NOT_AVAILABLE_YET;
}

View File

@@ -0,0 +1,192 @@
/*++
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:
Security.c
Abstract:
EFI PEI Core Security services
--*/
#include <PeiMain.h>
EFI_STATUS
EFIAPI
SecurityPpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
);
static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
&gEfiPeiSecurityPpiGuid,
SecurityPpiNotifyCallback
};
VOID
InitializeSecurityServices (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_CORE_INSTANCE *OldCoreData
)
/*++
Routine Description:
Initialize the security services.
Arguments:
PeiServices - The PEI core services table.
OldCoreData - Pointer to the old core data.
NULL if being run in non-permament memory mode.
Returns:
None
--*/
{
if (OldCoreData == NULL) {
PeiCoreNotifyPpi (&mNotifyList);
}
return;
}
EFI_STATUS
EFIAPI
SecurityPpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
/*++
Routine Description:
Provide a callback for when the security PPI is installed.
Arguments:
PeiServices - The PEI core services table.
NotifyDescriptor - The descriptor for the notification event.
Ppi - Pointer to the PPI in question.
Returns:
EFI_SUCCESS - The function is successfully processed.
--*/
{
PEI_CORE_INSTANCE *PrivateData;
//
// Get PEI Core private data
//
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
//
// If there isn't a security PPI installed, use the one from notification
//
if (PrivateData->PrivateSecurityPpi == NULL) {
PrivateData->PrivateSecurityPpi = (EFI_PEI_SECURITY_PPI *)Ppi;
}
return EFI_SUCCESS;
}
EFI_STATUS
VerifyPeim (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_FFS_FILE_HEADER *CurrentPeimAddress
)
/*++
Routine Description:
Provide a callout to the security verification service.
Arguments:
PeiServices - The PEI core services table.
CurrentPeimAddress - Pointer to the Firmware File under investigation.
Returns:
EFI_SUCCESS - Image is OK
EFI_SECURITY_VIOLATION - Image is illegal
--*/
{
PEI_CORE_INSTANCE *PrivateData;
EFI_STATUS Status;
UINT32 AuthenticationStatus;
BOOLEAN StartCrisisRecovery;
//
// Set a default authentication state
//
AuthenticationStatus = 0;
//
// get security PPI instance from PEI private data
//
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
if (PrivateData->PrivateSecurityPpi == NULL) {
Status = EFI_NOT_FOUND;
} else {
//
// Check to see if the image is OK
//
Status = PrivateData->PrivateSecurityPpi->AuthenticationState (
PeiServices,
PrivateData->PrivateSecurityPpi,
AuthenticationStatus,
CurrentPeimAddress,
&StartCrisisRecovery
);
if (StartCrisisRecovery) {
Status = EFI_SECURITY_VIOLATION;
}
}
return Status;
}
EFI_STATUS
VerifyFv (
IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress
)
/*++
Routine Description:
Verify a Firmware volume
Arguments:
CurrentFvAddress - Pointer to the current Firmware Volume under consideration
Returns:
EFI_SUCCESS - Firmware Volume is legal
EFI_SECURITY_VIOLATION - Firmware Volume fails integrity test
--*/
{
//
// Right now just pass the test. Future can authenticate and/or check the
// FV-header or other metric for goodness of binary.
//
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,95 @@
/*++
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:
StatusCode.c
Abstract:
Pei Core Status Code Support
Revision History
--*/
#include <PeiMain.h>
EFI_STATUS
EFIAPI
PeiReportStatusCode (
IN EFI_PEI_SERVICES **PeiServices,
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:
Core version of the Status Code reporter
Arguments:
PeiServices - The PEI core services table.
CodeType - Type of Status Code.
Value - Value to output for Status Code.
Instance - Instance Number of this status code.
CallerId - ID of the caller of this status code.
Data - Optional data associated with this status code.
Returns:
Status - EFI_SUCCESS if status code is successfully reported
- EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed
--*/
{
EFI_STATUS Status;
EFI_PEI_PROGRESS_CODE_PPI *StatusCodePpi;
//
//Locate StatusCode Ppi.
//
Status = PeiCoreLocatePpi (
&gEfiPeiStatusCodePpiGuid,
0,
NULL,
(VOID **)&StatusCodePpi
);
if (!EFI_ERROR (Status)) {
Status = StatusCodePpi->ReportStatusCode (
PeiServices,
CodeType,
Value,
Instance,
CallerId,
Data
);
return Status;
}
return EFI_NOT_AVAILABLE_YET;
}

View File

@@ -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="PeiMain"><!--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="Core\Pei"/>
<property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
<property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
<target name="PeiMain">
<GenBuild baseName="PeiMain" mbdFilename="${MODULE_DIR}\PeiMain.mbd" msaFilename="${MODULE_DIR}\PeiMain.msa"/>
</target>
<target depends="PeiMain_clean" name="clean"/>
<target depends="PeiMain_cleanall" name="cleanall"/>
<target name="PeiMain_clean">
<OutputDirSetup baseName="PeiMain" mbdFilename="${MODULE_DIR}\PeiMain.mbd" msaFilename="${MODULE_DIR}\PeiMain.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\PeiMain_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\PeiMain_build.xml" target="clean"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
</target>
<target name="PeiMain_cleanall">
<OutputDirSetup baseName="PeiMain" mbdFilename="${MODULE_DIR}\PeiMain.mbd" msaFilename="${MODULE_DIR}\PeiMain.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\PeiMain_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\PeiMain_build.xml" target="cleanall"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}"/>
<delete dir="${DEST_DIR_DEBUG}"/>
<delete>
<fileset dir="${BIN_DIR}" includes="**PeiMain*"/>
</delete>
</target>
</project>