📄 coresectionextraction.c
字号:
SEP member function. Retrieves requested section from section stream.
Arguments:
This: Pointer to SEP instance.
SectionStreamHandle: The section stream from which to extract the requested
section.
SectionType: A pointer to the type of section to search for.
SectionDefinitionGuid: If the section type is EFI_SECTION_GUID_DEFINED, then
SectionDefinitionGuid indicates which of these types
of sections to search for.
SectionInstance: Indicates which instance of the requested section to
return.
Buffer: Double indirection to buffer. If *Buffer is non-null on
input, then the buffer is caller allocated. If
*Buffer is NULL, then the buffer is callee allocated.
In either case, the requried buffer size is returned
in *BufferSize.
BufferSize: On input, indicates the size of *Buffer if *Buffer is
non-null on input. On output, indicates the required
size (allocated size if callee allocated) of *Buffer.
AuthenticationStatus: Indicates the authentication status of the retrieved
section.
Returns:
EFI_SUCCESS: Section was retrieved successfully
EFI_PROTOCOL_ERROR: A GUID defined section was encountered in the section
stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED
bit set, but there was no corresponding GUIDed Section
Extraction Protocol in the handle database. *Buffer is
unmodified.
EFI_NOT_FOUND: An error was encountered when parsing the SectionStream.
This indicates the SectionStream is not correctly
formatted.
EFI_NOT_FOUND: The requested section does not exist.
EFI_OUT_OF_RESOURCES: The system has insufficient resources to process the
request.
EFI_INVALID_PARAMETER: The SectionStreamHandle does not exist.
EFI_WARN_TOO_SMALL: The size of the caller allocated input buffer is
insufficient to contain the requested section. The
input buffer is filled and contents are section contents
are truncated.
--*/
{
CORE_SECTION_STREAM_NODE *StreamNode;
EFI_TPL OldTpl;
EFI_STATUS Status;
CORE_SECTION_CHILD_NODE *ChildNode;
CORE_SECTION_STREAM_NODE *ChildStreamNode;
UINTN CopySize;
UINT32 ExtractedAuthenticationStatus;
UINTN Instance;
UINT8 *CopyBuffer;
UINTN SectionSize;
OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
Instance = SectionInstance + 1;
//
// Locate target stream
//
Status = FindStreamNode (SectionStreamHandle, &StreamNode);
if (EFI_ERROR (Status)) {
Status = EFI_INVALID_PARAMETER;
goto GetSection_Done;
}
//
// Found the stream, now locate and return the appropriate section
//
if (SectionType == NULL) {
//
// SectionType == NULL means return the WHOLE section stream...
//
CopySize = StreamNode->StreamLength;
CopyBuffer = StreamNode->StreamBuffer;
*AuthenticationStatus = StreamNode->AuthenticationStatus;
} else {
//
// There's a requested section type, so go find it and return it...
//
Status = FindChildNode (
StreamNode,
*SectionType,
&Instance,
SectionDefinitionGuid,
&ChildNode,
&ChildStreamNode,
&ExtractedAuthenticationStatus
);
if (EFI_ERROR (Status)) {
goto GetSection_Done;
}
CopySize = ChildNode->Size - sizeof (EFI_COMMON_SECTION_HEADER);
CopyBuffer = ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream + sizeof (EFI_COMMON_SECTION_HEADER);
*AuthenticationStatus = ExtractedAuthenticationStatus;
}
SectionSize = CopySize;
if (*Buffer != NULL) {
//
// Caller allocated buffer. Fill to size and return required size...
//
if (*BufferSize < CopySize) {
Status = EFI_WARN_BUFFER_TOO_SMALL;
CopySize = *BufferSize;
}
} else {
//
// Callee allocated buffer. Allocate buffer and return size.
//
*Buffer = CoreAllocateBootServicesPool (CopySize);
if (*Buffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto GetSection_Done;
}
}
EfiCommonLibCopyMem (*Buffer, CopyBuffer, CopySize);
*BufferSize = SectionSize;
GetSection_Done:
CoreRestoreTpl (OldTpl);
return Status;
}
EFI_STATUS
EFIAPI
CloseSectionStream (
IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
IN UINTN StreamHandleToClose
)
/*++
Routine Description:
SEP member function. Deletes an existing section stream
Arguments:
This - Indicates the calling context.
StreamHandleToClose - Indicates the stream to close
Returns:
EFI_SUCCESS
EFI_OUT_OF_RESOURCES - memory allocation failed.
EFI_INVALID_PARAMETER - section stream does not end concident with end of
last section.
--*/
{
CORE_SECTION_STREAM_NODE *StreamNode;
EFI_TPL OldTpl;
EFI_STATUS Status;
EFI_LIST *Link;
CORE_SECTION_CHILD_NODE *ChildNode;
OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
//
// Locate target stream
//
Status = FindStreamNode (StreamHandleToClose, &StreamNode);
if (!EFI_ERROR (Status)) {
//
// Found the stream, so close it
//
RemoveEntryList (&StreamNode->Link);
while (!IsListEmpty (&StreamNode->Children)) {
Link = GetFirstNode (&StreamNode->Children);
ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link);
FreeChildNode (ChildNode);
}
CoreFreePool (StreamNode->StreamBuffer);
CoreFreePool (StreamNode);
Status = EFI_SUCCESS;
} else {
Status = EFI_INVALID_PARAMETER;
}
CoreRestoreTpl (OldTpl);
return Status;
}
STATIC
BOOLEAN
ChildIsType (
IN CORE_SECTION_STREAM_NODE *Stream,
IN CORE_SECTION_CHILD_NODE *Child,
IN EFI_SECTION_TYPE SearchType,
IN EFI_GUID *SectionDefinitionGuid
)
/*++
Routine Description:
Worker function. Determine if the input stream:child matches the input type.
Arguments:
Stream - Indicates the section stream associated with the child
Child - Indicates the child to check
SearchType - Indicates the type of section to check against for
SectionDefinitionGuid - Indicates the GUID to check against if the type is
EFI_SECTION_GUID_DEFINED
Returns:
TRUE - The child matches
FALSE - The child doesn't match
--*/
{
EFI_GUID_DEFINED_SECTION *GuidedSection;
if (SearchType == EFI_SECTION_ALL) {
return TRUE;
}
if (Child->Type != SearchType) {
return FALSE;
}
if (SearchType != EFI_SECTION_GUID_DEFINED) {
return TRUE;
}
GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);
return EfiCompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid);
}
STATIC
EFI_STATUS
FindChildNode (
IN CORE_SECTION_STREAM_NODE *SourceStream,
IN EFI_SECTION_TYPE SearchType,
IN OUT UINTN *SectionInstance,
IN EFI_GUID *SectionDefinitionGuid,
OUT CORE_SECTION_CHILD_NODE **FoundChild,
OUT CORE_SECTION_STREAM_NODE **FoundStream,
OUT UINT32 *AuthenticationStatus
)
/*++
Routine Description:
Worker function Recursively searches / builds section stream database
looking for requested section.
Arguments:
SourceStream - Indicates the section stream in which to do the search.
SearchType - Indicates the type of section to search for.
SectionInstance - Indicates which instance of section to find. This is
an in/out parameter to deal with recursions.
SectionDefinitionGuid - Guid of section definition
FoundChild - Output indicating the child node that is found.
FoundStream - Output indicating which section stream the child was
found in. If this stream was generated as a result of
an encapsulation section, the streamhandle is visible
within the SEP driver only.
AuthenticationStatus- Indicates the authentication status of the found section.
Returns:
EFI_SUCCESS - Child node was found and returned.
EFI_OUT_OF_RESOURCES- Memory allocation failed.
EFI_NOT_FOUND - Requested child node does not exist.
EFI_PROTOCOL_ERROR - a required GUIDED section extraction protocol does not
exist
--*/
{
CORE_SECTION_CHILD_NODE *CurrentChildNode;
CORE_SECTION_CHILD_NODE *RecursedChildNode;
CORE_SECTION_STREAM_NODE *RecursedFoundStream;
UINT32 NextChildOffset;
EFI_STATUS ErrorStatus;
EFI_STATUS Status;
CurrentChildNode = NULL;
ErrorStatus = EFI_NOT_FOUND;
if (SourceStream->StreamLength == 0) {
return EFI_NOT_FOUND;
}
if (IsListEmpty (&SourceStream->Children) &&
SourceStream->StreamLength > sizeof (EFI_COMMON_SECTION_HEADER)) {
//
// This occurs when a section stream exists, but no child sections
// have been parsed out yet. Therefore, extract the first child and add it
// to the list of children so we can get started.
//
Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// At least one child has been parsed out of the section stream. So, walk
// through the sections that have already been parsed out looking for the
// requested section, if necessary, continue parsing section stream and
// adding children until either the requested section is found, or we run
// out of data
//
CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children));
for (;;) {
if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) {
//
// The type matches, so check the instance count to see if it's the one we want
//
(*SectionInstance)--;
if (*SectionInstance == 0) {
//
// Got it!
//
*FoundChild = CurrentChildNode;
*FoundStream = SourceStream;
*AuthenticationStatus = SourceStream->AuthenticationStatus;
return EFI_SUCCESS;
}
}
if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
//
// If the current node is an encapsulating node, recurse into it...
//
Status = FindChildNode (
(CORE_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle,
SearchType,
SectionInstance,
SectionDefinitionGuid,
&RecursedChildNode,
&RecursedFoundStream,
AuthenticationStatus
);
//
// If the status is not EFI_SUCCESS, just save the error code and continue
// to find the request child node in the rest stream.
//
if (*SectionInstance == 0) {
ASSERT_EFI_ERROR (Status);
*FoundChild = RecursedChildNode;
*FoundStream = RecursedFoundStream;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -