📄 coresectionextraction.c
字号:
ChildNode - Indicates the child node that is the encapsulation section.
Returns:
None
--*/
{
RPN_EVENT_CONTEXT *Context;
//
// Allocate new event structure and context
//
Context = CoreAllocateBootServicesPool (sizeof (RPN_EVENT_CONTEXT));
ASSERT (Context != NULL);
Context->ChildNode = ChildNode;
Context->ParentStream = ParentStream;
Context->Event = CoreCreateProtocolNotifyEvent (
Context->ChildNode->EncapsulationGuid,
EFI_TPL_NOTIFY,
NotifyGuidedExtraction,
Context,
&Context->Registration,
FALSE
);
}
STATIC
VOID
EFIAPI
NotifyGuidedExtraction (
IN EFI_EVENT Event,
IN VOID *RpnContext
)
/*++
Routine Description:
RPN callback function. Removes a stale section stream and re-initializes it
with an updated AuthenticationStatus.
Arguments:
Event - The event that fired
RpnContext - A pointer to the context that allows us to identify
the relevent encapsulation...
Returns:
None
--*/
{
EFI_STATUS Status;
EFI_GUID_DEFINED_SECTION *GuidedHeader;
EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;
VOID *NewStreamBuffer;
UINTN NewStreamBufferSize;
UINT32 AuthenticationStatus;
RPN_EVENT_CONTEXT *Context;
Context = RpnContext;
Status = CloseSectionStream (&mSectionExtraction, Context->ChildNode->EncapsulatedStreamHandle);
if (!EFI_ERROR (Status)) {
//
// The stream closed successfully, so re-open the stream with correct AuthenticationStatus
//
GuidedHeader = (EFI_GUID_DEFINED_SECTION *)
(Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream);
ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED);
Status = CoreLocateProtocol (Context->ChildNode->EncapsulationGuid, NULL, &GuidedExtraction);
ASSERT_EFI_ERROR (Status);
Status = GuidedExtraction->ExtractSection (
GuidedExtraction,
GuidedHeader,
&NewStreamBuffer,
&NewStreamBufferSize,
&AuthenticationStatus
);
ASSERT_EFI_ERROR (Status);
//
// OR in the parent stream's aggregagate status.
//
AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL;
Status = OpenSectionStreamEx (
NewStreamBufferSize,
NewStreamBuffer,
FALSE,
AuthenticationStatus,
&Context->ChildNode->EncapsulatedStreamHandle
);
ASSERT_EFI_ERROR (Status);
}
//
// If above, the stream did not close successfully, it indicates it's
// alread been closed by someone, so just destroy the event and be done with
// it.
//
CoreCloseEvent (Event);
CoreFreePool (Context);
}
STATIC
VOID
FreeChildNode (
IN CORE_SECTION_CHILD_NODE *ChildNode
)
/*++
Routine Description:
Worker function. Destructor for child nodes.
Arguments:
ChildNode - Indicates the node to destroy
Returns:
none
--*/
{
ASSERT (ChildNode->Signature == CORE_SECTION_CHILD_SIGNATURE);
//
// Remove the child from it's list
//
RemoveEntryList (&ChildNode->Link);
if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
//
// If it's an encapsulating section, we close the resulting section stream.
// CloseSectionStream will free all memory associated with the stream.
//
CloseSectionStream (&mSectionExtraction, ChildNode->EncapsulatedStreamHandle);
}
//
// Last, free the child node itself
//
CoreFreePool (ChildNode);
}
STATIC
EFI_STATUS
OpenSectionStreamEx (
IN UINTN SectionStreamLength,
IN VOID *SectionStream,
IN BOOLEAN AllocateBuffer,
IN UINT32 AuthenticationStatus,
OUT UINTN *SectionStreamHandle
)
/*++
Routine Description:
Worker function. Constructor for section streams.
Arguments:
SectionStreamLength - Size in bytes of the section stream.
SectionStream - Buffer containing the new section stream.
AllocateBuffer - Indicates whether the stream buffer is to be copied
or the input buffer is to be used in place.
AuthenticationStatus- Indicates the default authentication status for the
new stream.
SectionStreamHandle - A pointer to a caller allocated section stream handle.
Returns:
EFI_SUCCESS - Stream was added to stream database.
EFI_OUT_OF_RESOURCES - memory allocation failed.
--*/
{
CORE_SECTION_STREAM_NODE *NewStream;
EFI_TPL OldTpl;
//
// Allocate a new stream
//
NewStream = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_STREAM_NODE));
if (NewStream == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (AllocateBuffer) {
//
// if we're here, we're double buffering, allocate the buffer and copy the
// data in
//
if (SectionStreamLength > 0) {
NewStream->StreamBuffer = CoreAllocateBootServicesPool (SectionStreamLength);
if (NewStream->StreamBuffer == NULL) {
CoreFreePool (NewStream);
return EFI_OUT_OF_RESOURCES;
}
//
// Copy in stream data
//
EfiCommonLibCopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength);
} else {
//
// It's possible to have a zero length section stream.
//
NewStream->StreamBuffer = NULL;
}
} else {
//
// If were here, the caller has supplied the buffer (it's an internal call)
// so just assign the buffer. This happens when we open section streams
// as a result of expanding an encapsulating section.
//
NewStream->StreamBuffer = SectionStream;
}
//
// Initialize the rest of the section stream
//
NewStream->Signature = CORE_SECTION_STREAM_SIGNATURE;
NewStream->StreamHandle = (UINTN) NewStream;
NewStream->StreamLength = SectionStreamLength;
InitializeListHead (&NewStream->Children);
NewStream->AuthenticationStatus = AuthenticationStatus;
//
// Add new stream to stream list
//
OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
InsertTailList (&mStreamRoot, &NewStream->Link);
CoreRestoreTpl (OldTpl);
*SectionStreamHandle = NewStream->StreamHandle;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FindStreamNode (
IN UINTN SearchHandle,
OUT CORE_SECTION_STREAM_NODE **FoundStream
)
/*++
Routine Description:
Worker function. Search stream database for requested stream handle.
Arguments:
SearchHandle - Indicates which stream to look for.
FoundStream - Output pointer to the found stream.
Returns:
EFI_SUCCESS - StreamHandle was found and *FoundStream contains
the stream node.
EFI_NOT_FOUND - SearchHandle was not found in the stream database.
--*/
{
CORE_SECTION_STREAM_NODE *StreamNode;
if (!IsListEmpty (&mStreamRoot)) {
StreamNode = STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot));
for (;;) {
if (StreamNode->StreamHandle == SearchHandle) {
*FoundStream = StreamNode;
return EFI_SUCCESS;
} else if (IsNodeAtEnd (&mStreamRoot, &StreamNode->Link)) {
break;
} else {
StreamNode = STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot, &StreamNode->Link));
}
}
}
return EFI_NOT_FOUND;
}
STATIC
BOOLEAN
IsValidSectionStream (
IN VOID *SectionStream,
IN UINTN SectionStreamLength
)
/*++
Routine Description:
Check if a stream is valid.
Arguments:
SectionStream - The section stream to be checked
SectionStreamLength - The length of section stream
Returns:
TRUE
FALSE
--*/
{
UINTN TotalLength;
UINTN SectionLength;
EFI_COMMON_SECTION_HEADER *SectionHeader;
EFI_COMMON_SECTION_HEADER *NextSectionHeader;
TotalLength = 0;
SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream;
while (TotalLength < SectionStreamLength) {
SectionLength = SECTION_SIZE (SectionHeader);
TotalLength += SectionLength;
if (TotalLength == SectionStreamLength) {
return TRUE;
}
//
// Move to the next byte following the section...
//
SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);
//
// Figure out where the next section begins
//
NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) SectionHeader + 3);
NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader & ~(UINTN)3);
TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;
SectionHeader = NextSectionHeader;
}
ASSERT (FALSE);
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -