123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116 |
- /*++
- Copyright (c) 2014 Minoca Corp. All Rights Reserved
- Module Name:
- fvsect.c
- Abstract:
- This module implements section extraction support for UEFI firmware
- volumes.
- Author:
- Evan Green 11-Mar-2014
- Environment:
- Firmware
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "ueficore.h"
- #include "fwvolp.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define EFI_SECTION_STREAM_NODE_MAGIC 0x6D727453 // 'mrtS'
- #define EFI_SECTION_STREAM_CHILD_MAGIC 0x72745343 // 'rtSC'
- #define NULL_STREAM_HANDLE 0
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure defines EFI firmware volume section stream data.
- Members:
- Magic - Stores the magic value EFI_SECTION_STREAM_CHILD_MAGIC.
- ListEntry - Stores pointers to the next and previous child nodes in the
- stream.
- Type - Stores the type of child section.
- Size - Stores the size of the child section.
- OffsetInStream - Stores the offset from the beginning of the stream base to
- the section header in the stream.
- EncapsulatedStreamHandle - Stores 0 if the section is not an
- encapsulating section. Otherwise, it contains the stream handle of the
- encapsulated stream. This handle is always produced any time an
- encapsulating child is encountered, irrespective of whether or not the
- encapsulated stream is processed further.
- EncapsulationGuid - Stores the GUID of the encapsulation protocol.
- Event - Stores the event used to register for notification of the
- GUIDed extraction protocol arrival.
- --*/
- typedef struct _EFI_SECTION_CHILD_NODE {
- ULONG Magic;
- LIST_ENTRY ListEntry;
- UINT32 Type;
- UINT32 Size;
- UINT32 OffsetInStream;
- UINTN EncapsulatedStreamHandle;
- EFI_GUID *EncapsulationGuid;
- EFI_EVENT Event;
- } EFI_SECTION_CHILD_NODE, *PEFI_SECTION_CHILD_NODE;
- /*++
- Structure Description:
- This structure defines EFI firmware volume section stream data.
- Members:
- Magic - Stores the magic value EFI_SECTION_STREAM_NODE_MAGIC.
- ListEntry - Stores pointers to the next and previous stream nodes in the
- global list.
- StreamHandle - Stores the stream handle value.
- StreamBuffer - Stores a pointer to the stream data.
- StreamLength - Stores the size of the stream data in bytes.
- ChildList - Stores the list of child sections.
- AuthenticationStatus - Stores the authentication status for GUIDed
- extractions.
- --*/
- typedef struct _EFI_SECTION_STREAM_NODE {
- ULONG Magic;
- LIST_ENTRY ListEntry;
- UINTN StreamHandle;
- UINT8 *StreamBuffer;
- UINTN StreamLength;
- LIST_ENTRY ChildList;
- UINT32 AuthenticationStatus;
- } EFI_SECTION_STREAM_NODE, *PEFI_SECTION_STREAM_NODE;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- EFIAPI
- EFI_STATUS
- EfipFvOpenSectionStream (
- UINTN SectionStreamLength,
- VOID *SectionStream,
- BOOLEAN AllocateBuffer,
- UINT32 AuthenticationStatus,
- UINTN *SectionStreamHandle
- );
- EFI_STATUS
- EfipFvCreateChildNode (
- PEFI_SECTION_STREAM_NODE Stream,
- UINT32 ChildOffset,
- PEFI_SECTION_CHILD_NODE *ChildNode
- );
- EFI_STATUS
- EfipFvFindChildNode (
- PEFI_SECTION_STREAM_NODE SourceStream,
- EFI_SECTION_TYPE SearchType,
- UINTN *SectionInstance,
- EFI_GUID *SectionDefinitionGuid,
- PEFI_SECTION_CHILD_NODE *FoundChild,
- PEFI_SECTION_STREAM_NODE *FoundStream,
- UINT32 *AuthenticationStatus
- );
- BOOLEAN
- EfipFvIsValidSectionStream (
- VOID *SectionStream,
- UINTN SectionStreamLength
- );
- EFI_STATUS
- EfipFvFindStreamNode (
- UINTN SearchHandle,
- PEFI_SECTION_STREAM_NODE *FoundStream
- );
- BOOLEAN
- EfipFvChildIsType (
- PEFI_SECTION_STREAM_NODE Stream,
- PEFI_SECTION_CHILD_NODE Child,
- EFI_SECTION_TYPE SearchType,
- EFI_GUID *SectionDefinitionGuid
- );
- VOID
- EfipFvFreeChildNode (
- PEFI_SECTION_CHILD_NODE ChildNode
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- LIST_ENTRY EfiStreamRoot;
- //
- // ------------------------------------------------------------------ Functions
- //
- EFIAPI
- EFI_STATUS
- EfiFvInitializeSectionExtraction (
- EFI_HANDLE ImageHandle,
- EFI_SYSTEM_TABLE *SystemTable
- )
- /*++
- Routine Description:
- This routine initializes the section extraction support for firmware
- volumes.
- Arguments:
- ImageHandle - Supplies a pointer to the image handle.
- SystemTable - Supplies a pointer to the EFI system table.
- Return Value:
- EFI status code.
- --*/
- {
- INITIALIZE_LIST_HEAD(&EfiStreamRoot);
- return EFI_SUCCESS;
- }
- EFIAPI
- EFI_STATUS
- EfiFvOpenSectionStream (
- UINTN SectionStreamLength,
- VOID *SectionStream,
- UINTN *SectionStreamHandle
- )
- /*++
- Routine Description:
- This routine creates and returns a new section stream handle to represent
- a new section stream.
- Arguments:
- SectionStreamLength - Supplies the size in bytes of the section stream.
- SectionStream - Supplies the section stream.
- SectionStreamHandle - Supplies a pointer where a handle to the stream will
- be returned.
- Return Value:
- EFI_SUCCESS on success.
- EFI_OUT_OF_RESOURCES if memory allocation failed.
- EFI_INVALID_PARAMETER if the section stream does not end noincidentally to
- the end of the previous section.
- --*/
- {
- EFI_STATUS Status;
- if (EfipFvIsValidSectionStream(SectionStream, SectionStreamLength) ==
- FALSE) {
- return EFI_INVALID_PARAMETER;
- }
- Status = EfipFvOpenSectionStream(SectionStreamLength,
- SectionStream,
- TRUE,
- 0,
- SectionStreamHandle);
- return Status;
- }
- EFIAPI
- EFI_STATUS
- EfiFvCloseSectionStream (
- UINTN StreamHandle
- )
- /*++
- Routine Description:
- This routine closes an open section stream handle.
- Arguments:
- StreamHandle - Supplies the stream handle previously returned.
- Return Value:
- EFI status code.
- --*/
- {
- PEFI_SECTION_CHILD_NODE ChildNode;
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- PEFI_SECTION_STREAM_NODE StreamNode;
- OldTpl = EfiCoreRaiseTpl(TPL_NOTIFY);
- Status = EfipFvFindStreamNode(StreamHandle, &StreamNode);
- if (!EFI_ERROR(Status)) {
- LIST_REMOVE(&(StreamNode->ListEntry));
- while (LIST_EMPTY(&(StreamNode->ChildList)) == FALSE) {
- ChildNode = LIST_VALUE(StreamNode->ChildList.Next,
- EFI_SECTION_CHILD_NODE,
- ListEntry);
- EfipFvFreeChildNode(ChildNode);
- }
- EfiCoreFreePool(StreamNode->StreamBuffer);
- EfiCoreFreePool(StreamNode);
- Status = EFI_SUCCESS;
- } else {
- Status = EFI_INVALID_PARAMETER;
- }
- EfiCoreRestoreTpl(OldTpl);
- return Status;
- }
- EFIAPI
- EFI_STATUS
- EfiFvGetSection (
- UINTN SectionStreamHandle,
- EFI_SECTION_TYPE *SectionType,
- EFI_GUID *SectionDefinitionGuid,
- UINTN SectionInstance,
- VOID **Buffer,
- UINTN *BufferSize,
- UINT32 *AuthenticationStatus,
- BOOLEAN IsFfs3Fv
- )
- /*++
- Routine Description:
- This routine reads a section from a given section stream.
- Arguments:
- SectionStreamHandle - Supplies the stream handle of the stream to get the
- section from.
- SectionType - Supplies a pointer that on input contains the type of section
- to search for. On output, this will return the type of the section
- found.
- SectionDefinitionGuid - Supplies a pointer to the GUID of the section to
- search for if the section type indicates EFI_SECTION_GUID_DEFINED.
- SectionInstance - Supplies the instance of the requested section to
- return.
- Buffer - Supplies a pointer to a buffer value. If the value of the buffer
- is NULL, then the buffer is callee-allocated. If it is not NULL, then
- the supplied buffer is used.
- BufferSize - Supplies a pointer that on input contains the size of the
- buffer, if supplied. On output, the size of the section will be
- returned.
- AuthenticationStatus - Supplies a pointer where the authentication status
- will be returned.
- IsFfs3Fv - Supplies a boolean indicating if the firmware file system is
- version 3 (TRUE) or version 2 (FALSE).
- Return Value:
- EFI_SUCCESS on success.
- EFI_PROTOCOL_ERROR if a GUIDed section was encountered but no extraction
- protocol was found.
- EFI_NOT_FOUND if an error occurred while parsing the section stream, or the
- requested section does not exist.
- EFI_OUT_OF_RESOURCES on allocation failure.
- EFI_INVALID_PARAMETER if the given section stream handle does not exist.
- EFI_WARN_TOO_SMALL if a buffer value was supplied but it was not big enough
- to hold the requested section.
- --*/
- {
- PEFI_SECTION_CHILD_NODE ChildNode;
- PEFI_SECTION_STREAM_NODE ChildStreamNode;
- UINT8 *CopyBuffer;
- UINTN CopySize;
- UINT32 ExtractedAuthenticationStatus;
- UINTN Instance;
- EFI_TPL OldTpl;
- EFI_COMMON_SECTION_HEADER *Section;
- UINTN SectionSize;
- EFI_STATUS Status;
- PEFI_SECTION_STREAM_NODE StreamNode;
- OldTpl = EfiCoreRaiseTpl(TPL_NOTIFY);
- Instance = SectionInstance + 1;
- Status = EfipFvFindStreamNode(SectionStreamHandle, &StreamNode);
- if (EFI_ERROR(Status)) {
- Status = EFI_INVALID_PARAMETER;
- goto FvGetSectionEnd;
- }
- //
- // Locate and return the appropriate section. If the section type is NULL,
- // return the whole stream.
- //
- if (SectionType == NULL) {
- CopySize = StreamNode->StreamLength;
- CopyBuffer = StreamNode->StreamBuffer;
- *AuthenticationStatus = StreamNode->AuthenticationStatus;
- } else {
- Status = EfipFvFindChildNode(StreamNode,
- *SectionType,
- &Instance,
- SectionDefinitionGuid,
- &ChildNode,
- &ChildStreamNode,
- &ExtractedAuthenticationStatus);
- if (EFI_ERROR(Status)) {
- goto FvGetSectionEnd;
- }
- Section = (EFI_COMMON_SECTION_HEADER *)(ChildStreamNode->StreamBuffer +
- ChildNode->OffsetInStream);
- if (EFI_IS_SECTION2(Section)) {
- ASSERT(EFI_SECTION2_SIZE(Section) > 0x00FFFFFF);
- if (IsFfs3Fv == FALSE) {
- RtlDebugPrint("Error: FFS3 section in FFS2 volume.\n");
- Status = EFI_NOT_FOUND;
- goto FvGetSectionEnd;
- }
- CopySize = EFI_SECTION2_SIZE(Section) -
- sizeof(EFI_COMMON_SECTION_HEADER2);
- CopyBuffer = (UINT8 *)Section + sizeof(EFI_COMMON_SECTION_HEADER2);
- } else {
- CopySize = EFI_SECTION_SIZE(Section) -
- sizeof(EFI_COMMON_SECTION_HEADER);
- CopyBuffer = (UINT8 *)Section + sizeof(EFI_COMMON_SECTION_HEADER);
- }
- *AuthenticationStatus = ExtractedAuthenticationStatus;
- }
- SectionSize = CopySize;
- if (*Buffer != NULL) {
- if (*BufferSize < CopySize) {
- Status = EFI_WARN_BUFFER_TOO_SMALL;
- CopySize = *BufferSize;
- }
- } else {
- *Buffer = EfiCoreAllocateBootPool(CopySize);
- if (*Buffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto FvGetSectionEnd;
- }
- }
- EfiCoreCopyMemory(*Buffer, CopyBuffer, CopySize);
- *BufferSize = SectionSize;
- FvGetSectionEnd:
- EfiCoreRestoreTpl(OldTpl);
- return Status;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- EFIAPI
- EFI_STATUS
- EfipFvOpenSectionStream (
- UINTN SectionStreamLength,
- VOID *SectionStream,
- BOOLEAN AllocateBuffer,
- UINT32 AuthenticationStatus,
- UINTN *SectionStreamHandle
- )
- /*++
- Routine Description:
- This routine creates and returns a new section stream handle to represent
- a new section stream.
- Arguments:
- SectionStreamLength - Supplies the size in bytes of the section stream.
- SectionStream - Supplies the section stream.
- AllocateBuffer - Supplies a boolean indicating whether to copy the stream
- buffer (TRUE) or use the buffer in-place (FALSE).
- AuthenticationStatus - Supplies the authentication status.
- SectionStreamHandle - Supplies a pointer where a handle to the stream will
- be returned.
- Return Value:
- EFI_SUCCESS on success.
- EFI_OUT_OF_RESOURCES if memory allocation failed.
- EFI_INVALID_PARAMETER if the section stream does not end noincidentally to
- the end of the previous section.
- --*/
- {
- PEFI_SECTION_STREAM_NODE NewStream;
- EFI_TPL OldTpl;
- NewStream = EfiCoreAllocateBootPool(sizeof(EFI_SECTION_STREAM_NODE));
- if (NewStream == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- EfiCoreSetMemory(NewStream, sizeof(EFI_SECTION_STREAM_NODE), 0);
- if (AllocateBuffer != FALSE) {
- if (SectionStreamLength > 0) {
- NewStream->StreamBuffer =
- EfiCoreAllocateBootPool(SectionStreamLength);
- if (NewStream->StreamBuffer == NULL) {
- EfiCoreFreePool(NewStream);
- return EFI_OUT_OF_RESOURCES;
- }
- EfiCoreCopyMemory(NewStream->StreamBuffer,
- SectionStream,
- SectionStreamLength);
- }
- //
- // The caller supplied the buffer, use it directly.
- //
- } else {
- NewStream->StreamBuffer = SectionStream;
- }
- NewStream->Magic = EFI_SECTION_STREAM_NODE_MAGIC;
- NewStream->StreamHandle = (UINTN)NewStream;
- NewStream->StreamLength = SectionStreamLength;
- INITIALIZE_LIST_HEAD(&(NewStream->ChildList));
- NewStream->AuthenticationStatus = AuthenticationStatus;
- //
- // Add this shiny new stream to the list.
- //
- OldTpl = EfiCoreRaiseTpl(TPL_NOTIFY);
- INSERT_BEFORE(&(NewStream->ListEntry), &EfiStreamRoot);
- EfiCoreRestoreTpl(OldTpl);
- *SectionStreamHandle = NewStream->StreamHandle;
- return EFI_SUCCESS;
- }
- EFI_STATUS
- EfipFvCreateChildNode (
- PEFI_SECTION_STREAM_NODE Stream,
- UINT32 ChildOffset,
- PEFI_SECTION_CHILD_NODE *ChildNode
- )
- /*++
- Routine Description:
- This routine parses and creates a new child node.
- Arguments:
- Stream - Supplies a pointer to the stream to parse.
- ChildOffset - Supplies the offset within the stream to parse from.
- ChildNode - Supplies a pointer where a pointer to the newly created child
- will be returned.
- Return Value:
- EFI_SUCCESS on success.
- EFI_PROTOCOL_ERROR if the GUIDed extraction protocol needed does not
- exist.
- --*/
- {
- PEFI_SECTION_CHILD_NODE Node;
- EFI_COMMON_SECTION_HEADER *SectionHeader;
- EFI_STATUS Status;
- SectionHeader = (EFI_COMMON_SECTION_HEADER *)(Stream->StreamBuffer +
- ChildOffset);
- *ChildNode = EfiCoreAllocateBootPool(sizeof(EFI_SECTION_CHILD_NODE));
- if (*ChildNode == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Node = *ChildNode;
- EfiCoreSetMemory(Node, sizeof(EFI_SECTION_CHILD_NODE), 0);
- Node->Magic = EFI_SECTION_STREAM_CHILD_MAGIC;
- Node->Type = SectionHeader->Elements.Type;
- if (EFI_IS_SECTION2(SectionHeader)) {
- Node->Size = EFI_SECTION2_SIZE(SectionHeader);
- } else {
- Node->Size = EFI_SECTION_SIZE(SectionHeader);
- }
- Node->OffsetInStream = ChildOffset;
- Node->EncapsulatedStreamHandle = NULL_STREAM_HANDLE;
- Node->EncapsulationGuid = NULL;
- switch (Node->Type) {
- //
- // Handle compressed encapsulation sections.
- //
- case EFI_SECTION_COMPRESSION:
- Status = EFI_SUCCESS;
- break;
- //
- // Handle GUIDed encapsulation sections.
- //
- case EFI_SECTION_GUID_DEFINED:
- Status = EFI_SUCCESS;
- break;
- //
- // No processing is needed on leaf nodes.
- //
- default:
- Status = EFI_SUCCESS;
- break;
- }
- INSERT_BEFORE(&(Node->ListEntry), &(Stream->ChildList));
- return Status;
- }
- EFI_STATUS
- EfipFvFindChildNode (
- PEFI_SECTION_STREAM_NODE SourceStream,
- EFI_SECTION_TYPE SearchType,
- UINTN *SectionInstance,
- EFI_GUID *SectionDefinitionGuid,
- PEFI_SECTION_CHILD_NODE *FoundChild,
- PEFI_SECTION_STREAM_NODE *FoundStream,
- UINT32 *AuthenticationStatus
- )
- /*++
- Routine Description:
- This routine recursively searches for and builds the section stream
- database looking for the requested section.
- Arguments:
- SourceStream - Supplies a pointer to the stream to search.
- SearchType - Supplies the type of section to search for.
- SectionInstance - Supplies a pointer to the section instance to find. This
- is an in/out parameter to handle recursion.
- SectionDefinitionGuid - Supplies a pointer where the GUID of the section
- will be returned.
- FoundChild - Supplies a pointer where the child node will be returned on
- success.
- FoundStream - Supplies a pointer where the stream corresponding with the
- child will be returned on success.
- AuthenticationStatus - Supplies a pointer to the authentication status.
- Return Value:
- EFI_SUCCESS on success.
- EFI_NOT_FOUND if the requested child node does not exist.
- EFI_PROTOCOL_ERROR if a required GUIDed section extraction protocol does
- not exist.
- --*/
- {
- PEFI_SECTION_CHILD_NODE CurrentChildNode;
- VOID *EncapsulatedStream;
- EFI_STATUS ErrorStatus;
- BOOLEAN Match;
- UINT32 NextChildOffset;
- PEFI_SECTION_CHILD_NODE RecursedChildNode;
- PEFI_SECTION_STREAM_NODE RecursedFoundStream;
- EFI_STATUS Status;
- CurrentChildNode = NULL;
- ErrorStatus = EFI_NOT_FOUND;
- if (SourceStream->StreamLength == 0) {
- return EFI_NOT_FOUND;
- }
- //
- // If the stream exists but not child nodes have been parsed out yet, then
- // extract the first child.
- //
- if ((LIST_EMPTY(&(SourceStream->ChildList)) != FALSE) &&
- (SourceStream->StreamLength >= sizeof(EFI_COMMON_SECTION_HEADER))) {
- Status = EfipFvCreateChildNode(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 the
- // stream ends.
- //
- CurrentChildNode = LIST_VALUE(SourceStream->ChildList.Next,
- EFI_SECTION_CHILD_NODE,
- ListEntry);
- while (TRUE) {
- ASSERT((CurrentChildNode != NULL) &&
- (CurrentChildNode->Magic == EFI_SECTION_STREAM_CHILD_MAGIC));
- Match = EfipFvChildIsType(SourceStream,
- CurrentChildNode,
- SearchType,
- SectionDefinitionGuid);
- if (Match != FALSE) {
- *SectionInstance -= 1;
- if (*SectionInstance == 0) {
- *FoundChild = CurrentChildNode;
- *FoundStream = SourceStream;
- *AuthenticationStatus = SourceStream->AuthenticationStatus;
- return EFI_SUCCESS;
- }
- }
- //
- // If the current node is an encapsulating node, recurse into it.
- //
- if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
- EncapsulatedStream =
- (VOID *)(CurrentChildNode->EncapsulatedStreamHandle);
- Status = EfipFvFindChildNode(
- (PEFI_SECTION_STREAM_NODE)EncapsulatedStream,
- SearchType,
- SectionInstance,
- SectionDefinitionGuid,
- &RecursedChildNode,
- &RecursedFoundStream,
- AuthenticationStatus);
- //
- // If the recursion was not successful, save the error code and
- // continue to find the requested child node in the rest of the
- // stream.
- //
- if (*SectionInstance == 0) {
- ASSERT(!EFI_ERROR(Status));
- *FoundChild = RecursedChildNode;
- *FoundStream = RecursedFoundStream;
- return Status;
- } else {
- ErrorStatus = Status;
- }
- //
- // If the node type is GUIDed, but the node has no encapsulating data,
- // node data should not be parsed because a required GUIDed section
- // extraction protocol does not exist.
- //
- } else if ((CurrentChildNode->Type == EFI_SECTION_GUID_DEFINED) &&
- (SearchType != EFI_SECTION_GUID_DEFINED)) {
- ErrorStatus = EFI_PROTOCOL_ERROR;
- }
- //
- // If there are more parsed nodes, go look through them.
- //
- if (CurrentChildNode->ListEntry.Next != &(SourceStream->ChildList)) {
- CurrentChildNode = LIST_VALUE(CurrentChildNode->ListEntry.Next,
- EFI_SECTION_CHILD_NODE,
- ListEntry);
- //
- // This is the end of the list of parsed nodes. See if there's any more
- // data and continue parsing out more children if there is.
- //
- } else {
- NextChildOffset = CurrentChildNode->OffsetInStream +
- CurrentChildNode->Size;
- NextChildOffset = ALIGN_VALUE(NextChildOffset, 4);
- if (NextChildOffset <=
- (SourceStream->StreamLength -
- sizeof(EFI_COMMON_SECTION_HEADER))) {
- Status = EfipFvCreateChildNode(SourceStream,
- NextChildOffset,
- &CurrentChildNode);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- } else {
- ASSERT(EFI_ERROR(ErrorStatus));
- return ErrorStatus;
- }
- }
- }
- //
- // Execution should never actually get here.
- //
- ASSERT(FALSE);
- return EFI_NOT_FOUND;
- }
- BOOLEAN
- EfipFvIsValidSectionStream (
- VOID *SectionStream,
- UINTN SectionStreamLength
- )
- /*++
- Routine Description:
- This routine determines whether or not a stream is valid.
- Arguments:
- SectionStream - Supplies the section stream to check.
- SectionStreamLength - Supplies the size in bytes of the section stream.
- Return Value:
- TRUE if the section stream is valid.
- FALSE if the section stream is invalid.
- --*/
- {
- EFI_COMMON_SECTION_HEADER *NextSectionHeader;
- EFI_COMMON_SECTION_HEADER *SectionHeader;
- UINTN SectionLength;
- UINTN TotalLength;
- TotalLength = 0;
- SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream;
- while (TotalLength < SectionStreamLength) {
- if (EFI_IS_SECTION2(SectionHeader)) {
- SectionLength = EFI_SECTION2_SIZE(SectionHeader);
- } else {
- SectionLength = EFI_SECTION_SIZE(SectionHeader);
- }
- TotalLength += SectionLength;
- if (TotalLength == SectionStreamLength) {
- return TRUE;
- }
- //
- // Move to the next byte following the section, and figure out where
- // the next section begins.
- //
- SectionHeader = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)SectionHeader +
- SectionLength);
- NextSectionHeader = ALIGN_POINTER(SectionHeader, 4);
- TotalLength += (UINTN)NextSectionHeader - (UINTN)SectionHeader;
- SectionHeader = NextSectionHeader;
- }
- ASSERT(FALSE);
- return FALSE;
- }
- EFI_STATUS
- EfipFvFindStreamNode (
- UINTN SearchHandle,
- PEFI_SECTION_STREAM_NODE *FoundStream
- )
- /*++
- Routine Description:
- This routine finds the stream matching the given handle. This routine
- assumes the TPL has already been raised.
- Arguments:
- SearchHandle - Supplies the handle to search for.
- FoundStream - Supplies a pointer where a pointer to the stream will be
- returned on success.
- Return Value:
- EFI_SUCCESS on success.
- EFI_NOT_FOUND if a stream matching the given handle was not found.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PEFI_SECTION_STREAM_NODE Node;
- CurrentEntry = EfiStreamRoot.Next;
- while (CurrentEntry != &EfiStreamRoot) {
- Node = LIST_VALUE(CurrentEntry, EFI_SECTION_STREAM_NODE, ListEntry);
- ASSERT(Node->Magic == EFI_SECTION_STREAM_NODE_MAGIC);
- if (Node->StreamHandle == SearchHandle) {
- *FoundStream = Node;
- return EFI_SUCCESS;
- }
- CurrentEntry = CurrentEntry->Next;
- }
- *FoundStream = NULL;
- return EFI_NOT_FOUND;
- }
- BOOLEAN
- EfipFvChildIsType (
- PEFI_SECTION_STREAM_NODE Stream,
- PEFI_SECTION_CHILD_NODE Child,
- EFI_SECTION_TYPE SearchType,
- EFI_GUID *SectionDefinitionGuid
- )
- /*++
- Routine Description:
- This routine determines if the given input stream and child matches the
- input type.
- Arguments:
- Stream - Supplies a pointer to the section stream associated with the child.
- Child - Supplies a pointer to the child to check.
- SearchType - Supplies the type of section to check for.
- SectionDefinitionGuid - Supplies the GUID to check against if the search
- type is EFI_SECTION_GUID_DEFINED.
- Return Value:
- TRUE if the section matches the parameters.
- FALSE if the section does not match.
- --*/
- {
- EFI_GUID_DEFINED_SECTION *GuidedSection;
- EFI_GUID_DEFINED_SECTION2 *GuidedSection2;
- EFI_GUID *SectionGuid;
- if (SearchType == EFI_SECTION_ALL) {
- return TRUE;
- }
- if (SearchType != Child->Type) {
- return FALSE;
- }
- if ((SearchType != EFI_SECTION_GUID_DEFINED) ||
- (SectionDefinitionGuid == NULL)) {
- return TRUE;
- }
- GuidedSection = (EFI_GUID_DEFINED_SECTION *)(Stream->StreamBuffer +
- Child->OffsetInStream);
- if (EFI_IS_SECTION2(GuidedSection)) {
- GuidedSection2 = (EFI_GUID_DEFINED_SECTION2 *)GuidedSection;
- SectionGuid = &(GuidedSection2->SectionDefinitionGuid);
- } else {
- SectionGuid = &(GuidedSection->SectionDefinitionGuid);
- }
- if (EfiCoreCompareGuids(SectionGuid, SectionDefinitionGuid) != FALSE) {
- return TRUE;
- }
- return FALSE;
- }
- VOID
- EfipFvFreeChildNode (
- PEFI_SECTION_CHILD_NODE ChildNode
- )
- /*++
- Routine Description:
- This routine destroys a firmware volume section child node.
- Arguments:
- ChildNode - Supplies the child node to destroy.
- Return Value:
- None.
- --*/
- {
- ASSERT(ChildNode->Magic == EFI_SECTION_STREAM_CHILD_MAGIC);
- LIST_REMOVE(&(ChildNode->ListEntry));
- if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
- EfiFvCloseSectionStream(ChildNode->EncapsulatedStreamHandle);
- }
- if (ChildNode->Event != NULL) {
- EfiCloseEvent(ChildNode->Event);
- }
- ChildNode->Magic = 0;
- EfiCoreFreePool(ChildNode);
- return;
- }
|