12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121 |
- /*++
- Copyright (c) 2014 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- 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;
- }
|