} RPN_EVENT_CONTEXT;\r
\r
\r
-\r
-//\r
-// Local prototypes\r
-//\r
-/**\r
- Worker function. Determine if the input stream:child matches the input type.\r
-\r
- @param Stream Indicates the section stream associated with the\r
- child\r
- @param Child Indicates the child to check\r
- @param SearchType Indicates the type of section to check against\r
- for\r
- @param SectionDefinitionGuid Indicates the GUID to check against if the type\r
- is EFI_SECTION_GUID_DEFINED\r
-\r
- @retval TRUE The child matches\r
- @retval FALSE The child doesn't match\r
-\r
-**/\r
-BOOLEAN\r
-ChildIsType (\r
- IN CORE_SECTION_STREAM_NODE *Stream,\r
- IN CORE_SECTION_CHILD_NODE *Child,\r
- IN EFI_SECTION_TYPE SearchType,\r
- IN EFI_GUID *SectionDefinitionGuid\r
- );\r
-\r
-\r
-/**\r
- Worker function. Search stream database for requested stream handle.\r
-\r
- @param SearchHandle Indicates which stream to look for.\r
- @param FoundStream Output pointer to the found stream.\r
-\r
- @retval EFI_SUCCESS StreamHandle was found and *FoundStream contains\r
- the stream node.\r
- @retval EFI_NOT_FOUND SearchHandle was not found in the stream\r
- database.\r
-\r
-**/\r
-EFI_STATUS\r
-FindStreamNode (\r
- IN UINTN SearchHandle,\r
- OUT CORE_SECTION_STREAM_NODE **FoundStream\r
- );\r
-\r
-\r
-/**\r
- Worker function Recursively searches / builds section stream database\r
- looking for requested section.\r
-\r
- @param SourceStream Indicates the section stream in which to do the\r
- search.\r
- @param SearchType Indicates the type of section to search for.\r
- @param SectionInstance Indicates which instance of section to find.\r
- This is an in/out parameter to deal with\r
- recursions.\r
- @param SectionDefinitionGuid Guid of section definition\r
- @param FoundChild Output indicating the child node that is found.\r
- @param FoundStream Output indicating which section stream the child\r
- was found in. If this stream was generated as a\r
- result of an encapsulation section, the\r
- streamhandle is visible within the SEP driver\r
- only.\r
- @param AuthenticationStatus Indicates the authentication status of the found section.\r
-\r
- @retval EFI_SUCCESS Child node was found and returned.\r
- EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
- @retval EFI_NOT_FOUND Requested child node does not exist.\r
- @retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol\r
- does not exist\r
-\r
-**/\r
-EFI_STATUS\r
-FindChildNode (\r
- IN CORE_SECTION_STREAM_NODE *SourceStream,\r
- IN EFI_SECTION_TYPE SearchType,\r
- IN OUT UINTN *SectionInstance,\r
- IN EFI_GUID *SectionDefinitionGuid,\r
- OUT CORE_SECTION_CHILD_NODE **FoundChild,\r
- OUT CORE_SECTION_STREAM_NODE **FoundStream,\r
- OUT UINT32 *AuthenticationStatus\r
- );\r
-\r
-\r
-/**\r
- Worker function. Constructor for new child nodes.\r
-\r
- @param Stream Indicates the section stream in which to add the\r
- child.\r
- @param ChildOffset Indicates the offset in Stream that is the\r
- beginning of the child section.\r
- @param ChildNode Indicates the Callee allocated and initialized\r
- child.\r
-\r
- @retval EFI_SUCCESS Child node was found and returned.\r
- EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
- @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream\r
- handles when the child node is created. If the\r
- section type is GUID defined, and the extraction\r
- GUID does not exist, and producing the stream\r
- requires the GUID, then a protocol error is\r
- generated and no child is produced. Values\r
- returned by OpenSectionStreamEx.\r
-\r
-**/\r
-EFI_STATUS\r
-CreateChildNode (\r
- IN CORE_SECTION_STREAM_NODE *Stream,\r
- IN UINT32 ChildOffset,\r
- OUT CORE_SECTION_CHILD_NODE **ChildNode\r
- );\r
-\r
-\r
-/**\r
- Worker function. Destructor for child nodes.\r
-\r
- @param ChildNode Indicates the node to destroy\r
-\r
-**/\r
-VOID\r
-FreeChildNode (\r
- IN CORE_SECTION_CHILD_NODE *ChildNode\r
- );\r
-\r
-\r
-/**\r
- Worker function. Constructor for section streams.\r
-\r
- @param SectionStreamLength Size in bytes of the section stream.\r
- @param SectionStream Buffer containing the new section stream.\r
- @param AllocateBuffer Indicates whether the stream buffer is to be\r
- copied or the input buffer is to be used in\r
- place. AuthenticationStatus- Indicates the\r
- default authentication status for the new\r
- stream.\r
- @param AuthenticationStatus A pointer to a caller-allocated UINT32 that\r
- indicates the authentication status of the\r
- output buffer. If the input section's\r
- GuidedSectionHeader.Attributes field\r
- has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID\r
- bit as clear, AuthenticationStatus must return\r
- zero. Both local bits (19:16) and aggregate\r
- bits (3:0) in AuthenticationStatus are returned\r
- by ExtractSection(). These bits reflect the\r
- status of the extraction operation. The bit\r
- pattern in both regions must be the same, as\r
- the local and aggregate authentication statuses\r
- have equivalent meaning at this level. If the\r
- function returns anything other than\r
- EFI_SUCCESS, the value of *AuthenticationStatus\r
- is undefined.\r
- @param SectionStreamHandle A pointer to a caller allocated section stream\r
- handle.\r
-\r
- @retval EFI_SUCCESS Stream was added to stream database.\r
- @retval EFI_OUT_OF_RESOURCES memory allocation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-OpenSectionStreamEx (\r
- IN UINTN SectionStreamLength,\r
- IN VOID *SectionStream,\r
- IN BOOLEAN AllocateBuffer,\r
- IN UINT32 AuthenticationStatus,\r
- OUT UINTN *SectionStreamHandle\r
- );\r
-\r
-\r
-/**\r
- Check if a stream is valid.\r
-\r
- @param SectionStream The section stream to be checked\r
- @param SectionStreamLength The length of section stream\r
-\r
- @return A boolean value indicating the validness of the section stream.\r
-\r
-**/\r
-BOOLEAN\r
-IsValidSectionStream (\r
- IN VOID *SectionStream,\r
- IN UINTN SectionStreamLength\r
- );\r
-\r
-\r
/**\r
The ExtractSection() function processes the input section and\r
allocates a buffer from the pool in which it returns the section\r
\r
\r
/**\r
- SEP member function. This function creates and returns a new section stream\r
- handle to represent the new section stream.\r
+ Check if a stream is valid.\r
\r
- @param SectionStreamLength Size in bytes of the section stream.\r
- @param SectionStream Buffer containing the new section stream.\r
- @param SectionStreamHandle A pointer to a caller allocated UINTN that on\r
- output contains the new section stream handle.\r
+ @param SectionStream The section stream to be checked\r
+ @param SectionStreamLength The length of section stream\r
\r
- @retval EFI_SUCCESS The section stream is created successfully.\r
- @retval EFI_OUT_OF_RESOURCES memory allocation failed.\r
- @retval EFI_INVALID_PARAMETER Section stream does not end concident with end\r
- of last section.\r
+ @return A boolean value indicating the validness of the section stream.\r
\r
**/\r
-EFI_STATUS\r
-EFIAPI\r
-OpenSectionStream (\r
- IN UINTN SectionStreamLength,\r
- IN VOID *SectionStream,\r
- OUT UINTN *SectionStreamHandle\r
+BOOLEAN\r
+IsValidSectionStream (\r
+ IN VOID *SectionStream,\r
+ IN UINTN SectionStreamLength\r
)\r
{\r
- //\r
- // Check to see section stream looks good...\r
- //\r
- if (!IsValidSectionStream (SectionStream, SectionStreamLength)) {\r
- return EFI_INVALID_PARAMETER;\r
+ UINTN TotalLength;\r
+ UINTN SectionLength;\r
+ EFI_COMMON_SECTION_HEADER *SectionHeader;\r
+ EFI_COMMON_SECTION_HEADER *NextSectionHeader;\r
+\r
+ TotalLength = 0;\r
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream;\r
+\r
+ while (TotalLength < SectionStreamLength) {\r
+ SectionLength = SECTION_SIZE (SectionHeader);\r
+ TotalLength += SectionLength;\r
+\r
+ if (TotalLength == SectionStreamLength) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Move to the next byte following the section...\r
+ //\r
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);\r
+\r
+ //\r
+ // Figure out where the next section begins\r
+ //\r
+ NextSectionHeader = ALIGN_POINTER(SectionHeader, 4);\r
+ TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;\r
+ SectionHeader = NextSectionHeader;\r
}\r
\r
- return OpenSectionStreamEx (\r
- SectionStreamLength,\r
- SectionStream,\r
- TRUE,\r
- 0,\r
- SectionStreamHandle\r
- );\r
+ ASSERT (FALSE);\r
+ return FALSE;\r
}\r
\r
\r
/**\r
- SEP member function. Retrieves requested section from section stream.\r
+ Worker function. Constructor for section streams.\r
\r
- @param SectionStreamHandle The section stream from which to extract the\r
- requested section.\r
- @param SectionType A pointer to the type of section to search for.\r
- @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED,\r
- then SectionDefinitionGuid indicates which of\r
- these types of sections to search for.\r
- @param SectionInstance Indicates which instance of the requested\r
- section to return.\r
- @param Buffer Double indirection to buffer. If *Buffer is\r
- non-null on input, then the buffer is caller\r
- allocated. If Buffer is NULL, then the buffer\r
- is callee allocated. In either case, the\r
- requried buffer size is returned in *BufferSize.\r
- @param BufferSize On input, indicates the size of *Buffer if\r
- *Buffer is non-null on input. On output,\r
- indicates the required size (allocated size if\r
- callee allocated) of *Buffer.\r
- @param AuthenticationStatus A pointer to a caller-allocated UINT32 that\r
- indicates the authentication status of the\r
- output buffer. If the input section's\r
- GuidedSectionHeader.Attributes field\r
- has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID\r
- bit as clear, AuthenticationStatus must return\r
- zero. Both local bits (19:16) and aggregate\r
- bits (3:0) in AuthenticationStatus are returned\r
- by ExtractSection(). These bits reflect the\r
- status of the extraction operation. The bit\r
- pattern in both regions must be the same, as\r
- the local and aggregate authentication statuses\r
- have equivalent meaning at this level. If the\r
- function returns anything other than\r
- EFI_SUCCESS, the value of *AuthenticationStatus\r
- is undefined.\r
+ @param SectionStreamLength Size in bytes of the section stream.\r
+ @param SectionStream Buffer containing the new section stream.\r
+ @param AllocateBuffer Indicates whether the stream buffer is to be\r
+ copied or the input buffer is to be used in\r
+ place. AuthenticationStatus- Indicates the\r
+ default authentication status for the new\r
+ stream.\r
+ @param AuthenticationStatus A pointer to a caller-allocated UINT32 that\r
+ indicates the authentication status of the\r
+ output buffer. If the input section's\r
+ GuidedSectionHeader.Attributes field\r
+ has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID\r
+ bit as clear, AuthenticationStatus must return\r
+ zero. Both local bits (19:16) and aggregate\r
+ bits (3:0) in AuthenticationStatus are returned\r
+ by ExtractSection(). These bits reflect the\r
+ status of the extraction operation. The bit\r
+ pattern in both regions must be the same, as\r
+ the local and aggregate authentication statuses\r
+ have equivalent meaning at this level. If the\r
+ function returns anything other than\r
+ EFI_SUCCESS, the value of *AuthenticationStatus\r
+ is undefined.\r
+ @param SectionStreamHandle A pointer to a caller allocated section stream\r
+ handle.\r
\r
- @retval EFI_SUCCESS Section was retrieved successfully\r
- @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the\r
- section stream with its\r
- EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set,\r
- but there was no corresponding GUIDed Section\r
- Extraction Protocol in the handle database.\r
- *Buffer is unmodified.\r
- @retval EFI_NOT_FOUND An error was encountered when parsing the\r
- SectionStream. This indicates the SectionStream\r
- is not correctly formatted.\r
- @retval EFI_NOT_FOUND The requested section does not exist.\r
- @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process\r
- the request.\r
- @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist.\r
- @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is\r
- insufficient to contain the requested section.\r
- The input buffer is filled and section contents\r
- are truncated.\r
+ @retval EFI_SUCCESS Stream was added to stream database.\r
+ @retval EFI_OUT_OF_RESOURCES memory allocation failed.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-GetSection (\r
- IN UINTN SectionStreamHandle,\r
- IN EFI_SECTION_TYPE *SectionType,\r
- IN EFI_GUID *SectionDefinitionGuid,\r
- IN UINTN SectionInstance,\r
- IN VOID **Buffer,\r
- IN OUT UINTN *BufferSize,\r
- OUT UINT32 *AuthenticationStatus\r
+OpenSectionStreamEx (\r
+ IN UINTN SectionStreamLength,\r
+ IN VOID *SectionStream,\r
+ IN BOOLEAN AllocateBuffer,\r
+ IN UINT32 AuthenticationStatus,\r
+ OUT UINTN *SectionStreamHandle\r
)\r
{\r
- CORE_SECTION_STREAM_NODE *StreamNode;\r
- EFI_TPL OldTpl;\r
- EFI_STATUS Status;\r
- CORE_SECTION_CHILD_NODE *ChildNode;\r
- CORE_SECTION_STREAM_NODE *ChildStreamNode;\r
- UINTN CopySize;\r
- UINT32 ExtractedAuthenticationStatus;\r
- UINTN Instance;\r
- UINT8 *CopyBuffer;\r
- UINTN SectionSize;\r
-\r
-\r
- OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
- Instance = SectionInstance + 1;\r
-\r
- //\r
- // Locate target stream\r
- //\r
- Status = FindStreamNode (SectionStreamHandle, &StreamNode);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto GetSection_Done;\r
- }\r
+ CORE_SECTION_STREAM_NODE *NewStream;\r
+ EFI_TPL OldTpl;\r
\r
//\r
- // Found the stream, now locate and return the appropriate section\r
+ // Allocate a new stream\r
//\r
- if (SectionType == NULL) {\r
- //\r
- // SectionType == NULL means return the WHOLE section stream...\r
- //\r
- CopySize = StreamNode->StreamLength;\r
- CopyBuffer = StreamNode->StreamBuffer;\r
- *AuthenticationStatus = StreamNode->AuthenticationStatus;\r
- } else {\r
- //\r
- // There's a requested section type, so go find it and return it...\r
- //\r
- Status = FindChildNode (\r
- StreamNode,\r
- *SectionType,\r
- &Instance,\r
- SectionDefinitionGuid,\r
- &ChildNode,\r
- &ChildStreamNode,\r
- &ExtractedAuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto GetSection_Done;\r
- }\r
- CopySize = ChildNode->Size - sizeof (EFI_COMMON_SECTION_HEADER);\r
- CopyBuffer = ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream + sizeof (EFI_COMMON_SECTION_HEADER);\r
- *AuthenticationStatus = ExtractedAuthenticationStatus;\r
+ NewStream = AllocatePool (sizeof (CORE_SECTION_STREAM_NODE));\r
+ if (NewStream == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- SectionSize = CopySize;\r
- if (*Buffer != NULL) {\r
+ if (AllocateBuffer) {\r
//\r
- // Caller allocated buffer. Fill to size and return required size...\r
+ // if we're here, we're double buffering, allocate the buffer and copy the\r
+ // data in\r
//\r
- if (*BufferSize < CopySize) {\r
- Status = EFI_WARN_BUFFER_TOO_SMALL;\r
- CopySize = *BufferSize;\r
+ if (SectionStreamLength > 0) {\r
+ NewStream->StreamBuffer = AllocatePool (SectionStreamLength);\r
+ if (NewStream->StreamBuffer == NULL) {\r
+ CoreFreePool (NewStream);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Copy in stream data\r
+ //\r
+ CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength);\r
+ } else {\r
+ //\r
+ // It's possible to have a zero length section stream.\r
+ //\r
+ NewStream->StreamBuffer = NULL;\r
}\r
} else {\r
//\r
- // Callee allocated buffer. Allocate buffer and return size.\r
+ // If were here, the caller has supplied the buffer (it's an internal call)\r
+ // so just assign the buffer. This happens when we open section streams\r
+ // as a result of expanding an encapsulating section.\r
//\r
- *Buffer = AllocatePool (CopySize);\r
- if (*Buffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto GetSection_Done;\r
- }\r
+ NewStream->StreamBuffer = SectionStream;\r
}\r
- CopyMem (*Buffer, CopyBuffer, CopySize);\r
- *BufferSize = SectionSize;\r
\r
-GetSection_Done:\r
+ //\r
+ // Initialize the rest of the section stream\r
+ //\r
+ NewStream->Signature = CORE_SECTION_STREAM_SIGNATURE;\r
+ NewStream->StreamHandle = (UINTN) NewStream;\r
+ NewStream->StreamLength = SectionStreamLength;\r
+ InitializeListHead (&NewStream->Children);\r
+ NewStream->AuthenticationStatus = AuthenticationStatus;\r
+\r
+ //\r
+ // Add new stream to stream list\r
+ //\r
+ OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
+ InsertTailList (&mStreamRoot, &NewStream->Link);\r
CoreRestoreTpl (OldTpl);\r
\r
- return Status;\r
-}\r
+ *SectionStreamHandle = NewStream->StreamHandle;\r
\r
+ return EFI_SUCCESS;\r
+}\r
\r
\r
/**\r
- SEP member function. Deletes an existing section stream\r
+ SEP member function. This function creates and returns a new section stream\r
+ handle to represent the new section stream.\r
\r
- @param StreamHandleToClose Indicates the stream to close\r
+ @param SectionStreamLength Size in bytes of the section stream.\r
+ @param SectionStream Buffer containing the new section stream.\r
+ @param SectionStreamHandle A pointer to a caller allocated UINTN that on\r
+ output contains the new section stream handle.\r
\r
- @retval EFI_SUCCESS The section stream is closed sucessfully.\r
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_SUCCESS The section stream is created successfully.\r
+ @retval EFI_OUT_OF_RESOURCES memory allocation failed.\r
@retval EFI_INVALID_PARAMETER Section stream does not end concident with end\r
of last section.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-CloseSectionStream (\r
- IN UINTN StreamHandleToClose\r
+OpenSectionStream (\r
+ IN UINTN SectionStreamLength,\r
+ IN VOID *SectionStream,\r
+ OUT UINTN *SectionStreamHandle\r
)\r
{\r
- CORE_SECTION_STREAM_NODE *StreamNode;\r
- EFI_TPL OldTpl;\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- CORE_SECTION_CHILD_NODE *ChildNode;\r
-\r
- OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
-\r
//\r
- // Locate target stream\r
+ // Check to see section stream looks good...\r
//\r
- Status = FindStreamNode (StreamHandleToClose, &StreamNode);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Found the stream, so close it\r
- //\r
- RemoveEntryList (&StreamNode->Link);\r
- while (!IsListEmpty (&StreamNode->Children)) {\r
- Link = GetFirstNode (&StreamNode->Children);\r
- ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link);\r
- FreeChildNode (ChildNode);\r
- }\r
- CoreFreePool (StreamNode->StreamBuffer);\r
- CoreFreePool (StreamNode);\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = EFI_INVALID_PARAMETER;\r
+ if (!IsValidSectionStream (SectionStream, SectionStreamLength)) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- CoreRestoreTpl (OldTpl);\r
- return Status;\r
+ return OpenSectionStreamEx (\r
+ SectionStreamLength,\r
+ SectionStream,\r
+ TRUE,\r
+ 0,\r
+ SectionStreamHandle\r
+ );\r
}\r
\r
\r
}\r
\r
\r
-/**\r
- Worker function Recursively searches / builds section stream database\r
- looking for requested section.\r
-\r
- @param SourceStream Indicates the section stream in which to do the\r
- search.\r
- @param SearchType Indicates the type of section to search for.\r
- @param SectionInstance Indicates which instance of section to find.\r
- This is an in/out parameter to deal with\r
- recursions.\r
- @param SectionDefinitionGuid Guid of section definition\r
- @param FoundChild Output indicating the child node that is found.\r
- @param FoundStream Output indicating which section stream the child\r
- was found in. If this stream was generated as a\r
- result of an encapsulation section, the\r
- streamhandle is visible within the SEP driver\r
- only.\r
- @param AuthenticationStatus Indicates the authentication status of the found section.\r
-\r
- @retval EFI_SUCCESS Child node was found and returned.\r
- EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
- @retval EFI_NOT_FOUND Requested child node does not exist.\r
- @retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol\r
- does not exist\r
-\r
-**/\r
-EFI_STATUS\r
-FindChildNode (\r
- IN CORE_SECTION_STREAM_NODE *SourceStream,\r
- IN EFI_SECTION_TYPE SearchType,\r
- IN OUT UINTN *SectionInstance,\r
- IN EFI_GUID *SectionDefinitionGuid,\r
- OUT CORE_SECTION_CHILD_NODE **FoundChild,\r
- OUT CORE_SECTION_STREAM_NODE **FoundStream,\r
- OUT UINT32 *AuthenticationStatus\r
- )\r
-{\r
- CORE_SECTION_CHILD_NODE *CurrentChildNode;\r
- CORE_SECTION_CHILD_NODE *RecursedChildNode;\r
- CORE_SECTION_STREAM_NODE *RecursedFoundStream;\r
- UINT32 NextChildOffset;\r
- EFI_STATUS ErrorStatus;\r
- EFI_STATUS Status;\r
-\r
- CurrentChildNode = NULL;\r
- ErrorStatus = EFI_NOT_FOUND;\r
-\r
- if (SourceStream->StreamLength == 0) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- if (IsListEmpty (&SourceStream->Children) &&\r
- SourceStream->StreamLength >= sizeof (EFI_COMMON_SECTION_HEADER)) {\r
- //\r
- // This occurs when a section stream exists, but no child sections\r
- // have been parsed out yet. Therefore, extract the first child and add it\r
- // to the list of children so we can get started.\r
- // Section stream may contain an array of zero or more bytes.\r
- // So, its size should be >= the size of commen section header.\r
- //\r
- Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- //\r
- // At least one child has been parsed out of the section stream. So, walk\r
- // through the sections that have already been parsed out looking for the\r
- // requested section, if necessary, continue parsing section stream and\r
- // adding children until either the requested section is found, or we run\r
- // out of data\r
- //\r
- CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children));\r
-\r
- for (;;) {\r
- if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) {\r
- //\r
- // The type matches, so check the instance count to see if it's the one we want\r
- //\r
- (*SectionInstance)--;\r
- if (*SectionInstance == 0) {\r
- //\r
- // Got it!\r
- //\r
- *FoundChild = CurrentChildNode;\r
- *FoundStream = SourceStream;\r
- *AuthenticationStatus = SourceStream->AuthenticationStatus;\r
- return EFI_SUCCESS;\r
- }\r
- }\r
-\r
- if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {\r
- //\r
- // If the current node is an encapsulating node, recurse into it...\r
- //\r
- Status = FindChildNode (\r
- (CORE_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle,\r
- SearchType,\r
- SectionInstance,\r
- SectionDefinitionGuid,\r
- &RecursedChildNode,\r
- &RecursedFoundStream,\r
- AuthenticationStatus\r
- );\r
- //\r
- // If the status is not EFI_SUCCESS, just save the error code and continue\r
- // to find the request child node in the rest stream.\r
- //\r
- if (*SectionInstance == 0) {\r
- ASSERT_EFI_ERROR (Status);\r
- *FoundChild = RecursedChildNode;\r
- *FoundStream = RecursedFoundStream;\r
- return EFI_SUCCESS;\r
- } else {\r
- ErrorStatus = Status;\r
- }\r
- }\r
-\r
- if (!IsNodeAtEnd (&SourceStream->Children, &CurrentChildNode->Link)) {\r
- //\r
- // We haven't found the child node we're interested in yet, but there's\r
- // still more nodes that have already been parsed so get the next one\r
- // and continue searching..\r
- //\r
- CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream->Children, &CurrentChildNode->Link));\r
- } else {\r
- //\r
- // We've exhausted children that have already been parsed, so see if\r
- // there's any more data and continue parsing out more children if there\r
- // is.\r
- //\r
- NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size;\r
- //\r
- // Round up to 4 byte boundary\r
- //\r
- NextChildOffset += 3;\r
- NextChildOffset &= ~(UINTN) 3;\r
- if (NextChildOffset <= SourceStream->StreamLength - sizeof (EFI_COMMON_SECTION_HEADER)) {\r
- //\r
- // There's an unparsed child remaining in the stream, so create a new child node\r
- //\r
- Status = CreateChildNode (SourceStream, NextChildOffset, &CurrentChildNode);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- } else {\r
- ASSERT (EFI_ERROR (ErrorStatus));\r
- return ErrorStatus;\r
- }\r
- }\r
- }\r
-}\r
-\r
-\r
/**\r
Worker function. Constructor for new child nodes.\r
\r
\r
\r
/**\r
- Worker function. Destructor for child nodes.\r
+ Worker function Recursively searches / builds section stream database\r
+ looking for requested section.\r
\r
- @param ChildNode Indicates the node to destroy\r
+ @param SourceStream Indicates the section stream in which to do the\r
+ search.\r
+ @param SearchType Indicates the type of section to search for.\r
+ @param SectionInstance Indicates which instance of section to find.\r
+ This is an in/out parameter to deal with\r
+ recursions.\r
+ @param SectionDefinitionGuid Guid of section definition\r
+ @param FoundChild Output indicating the child node that is found.\r
+ @param FoundStream Output indicating which section stream the child\r
+ was found in. If this stream was generated as a\r
+ result of an encapsulation section, the\r
+ streamhandle is visible within the SEP driver\r
+ only.\r
+ @param AuthenticationStatus Indicates the authentication status of the found section.\r
+\r
+ @retval EFI_SUCCESS Child node was found and returned.\r
+ EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
+ @retval EFI_NOT_FOUND Requested child node does not exist.\r
+ @retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol\r
+ does not exist\r
\r
**/\r
-VOID\r
-FreeChildNode (\r
- IN CORE_SECTION_CHILD_NODE *ChildNode\r
+EFI_STATUS\r
+FindChildNode (\r
+ IN CORE_SECTION_STREAM_NODE *SourceStream,\r
+ IN EFI_SECTION_TYPE SearchType,\r
+ IN OUT UINTN *SectionInstance,\r
+ IN EFI_GUID *SectionDefinitionGuid,\r
+ OUT CORE_SECTION_CHILD_NODE **FoundChild,\r
+ OUT CORE_SECTION_STREAM_NODE **FoundStream,\r
+ OUT UINT32 *AuthenticationStatus\r
)\r
{\r
- ASSERT (ChildNode->Signature == CORE_SECTION_CHILD_SIGNATURE);\r
- //\r
- // Remove the child from it's list\r
- //\r
- RemoveEntryList (&ChildNode->Link);\r
+ CORE_SECTION_CHILD_NODE *CurrentChildNode;\r
+ CORE_SECTION_CHILD_NODE *RecursedChildNode;\r
+ CORE_SECTION_STREAM_NODE *RecursedFoundStream;\r
+ UINT32 NextChildOffset;\r
+ EFI_STATUS ErrorStatus;\r
+ EFI_STATUS Status;\r
\r
- if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {\r
+ CurrentChildNode = NULL;\r
+ ErrorStatus = EFI_NOT_FOUND;\r
+\r
+ if (SourceStream->StreamLength == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (IsListEmpty (&SourceStream->Children) &&\r
+ SourceStream->StreamLength >= sizeof (EFI_COMMON_SECTION_HEADER)) {\r
//\r
- // If it's an encapsulating section, we close the resulting section stream.\r
- // CloseSectionStream will free all memory associated with the stream.\r
+ // This occurs when a section stream exists, but no child sections\r
+ // have been parsed out yet. Therefore, extract the first child and add it\r
+ // to the list of children so we can get started.\r
+ // Section stream may contain an array of zero or more bytes.\r
+ // So, its size should be >= the size of commen section header.\r
//\r
- CloseSectionStream (ChildNode->EncapsulatedStreamHandle);\r
+ Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
+\r
//\r
- // Last, free the child node itself\r
+ // At least one child has been parsed out of the section stream. So, walk\r
+ // through the sections that have already been parsed out looking for the\r
+ // requested section, if necessary, continue parsing section stream and\r
+ // adding children until either the requested section is found, or we run\r
+ // out of data\r
//\r
- CoreFreePool (ChildNode);\r
-}\r
-\r
-\r
+ CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children));\r
\r
-/**\r
- Worker function. Constructor for section streams.\r
+ for (;;) {\r
+ if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) {\r
+ //\r
+ // The type matches, so check the instance count to see if it's the one we want\r
+ //\r
+ (*SectionInstance)--;\r
+ if (*SectionInstance == 0) {\r
+ //\r
+ // Got it!\r
+ //\r
+ *FoundChild = CurrentChildNode;\r
+ *FoundStream = SourceStream;\r
+ *AuthenticationStatus = SourceStream->AuthenticationStatus;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
\r
- @param SectionStreamLength Size in bytes of the section stream.\r
- @param SectionStream Buffer containing the new section stream.\r
- @param AllocateBuffer Indicates whether the stream buffer is to be\r
- copied or the input buffer is to be used in\r
- place. AuthenticationStatus- Indicates the\r
- default authentication status for the new\r
- stream.\r
- @param AuthenticationStatus A pointer to a caller-allocated UINT32 that\r
- indicates the authentication status of the\r
- output buffer. If the input section's\r
- GuidedSectionHeader.Attributes field\r
- has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID\r
- bit as clear, AuthenticationStatus must return\r
- zero. Both local bits (19:16) and aggregate\r
- bits (3:0) in AuthenticationStatus are returned\r
- by ExtractSection(). These bits reflect the\r
- status of the extraction operation. The bit\r
- pattern in both regions must be the same, as\r
- the local and aggregate authentication statuses\r
- have equivalent meaning at this level. If the\r
- function returns anything other than\r
- EFI_SUCCESS, the value of *AuthenticationStatus\r
- is undefined.\r
- @param SectionStreamHandle A pointer to a caller allocated section stream\r
- handle.\r
-\r
- @retval EFI_SUCCESS Stream was added to stream database.\r
- @retval EFI_OUT_OF_RESOURCES memory allocation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-OpenSectionStreamEx (\r
- IN UINTN SectionStreamLength,\r
- IN VOID *SectionStream,\r
- IN BOOLEAN AllocateBuffer,\r
- IN UINT32 AuthenticationStatus,\r
- OUT UINTN *SectionStreamHandle\r
- )\r
-{\r
- CORE_SECTION_STREAM_NODE *NewStream;\r
- EFI_TPL OldTpl;\r
-\r
- //\r
- // Allocate a new stream\r
- //\r
- NewStream = AllocatePool (sizeof (CORE_SECTION_STREAM_NODE));\r
- if (NewStream == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- if (AllocateBuffer) {\r
- //\r
- // if we're here, we're double buffering, allocate the buffer and copy the\r
- // data in\r
- //\r
- if (SectionStreamLength > 0) {\r
- NewStream->StreamBuffer = AllocatePool (SectionStreamLength);\r
- if (NewStream->StreamBuffer == NULL) {\r
- CoreFreePool (NewStream);\r
- return EFI_OUT_OF_RESOURCES;\r
+ if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {\r
+ //\r
+ // If the current node is an encapsulating node, recurse into it...\r
+ //\r
+ Status = FindChildNode (\r
+ (CORE_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle,\r
+ SearchType,\r
+ SectionInstance,\r
+ SectionDefinitionGuid,\r
+ &RecursedChildNode,\r
+ &RecursedFoundStream,\r
+ AuthenticationStatus\r
+ );\r
+ //\r
+ // If the status is not EFI_SUCCESS, just save the error code and continue\r
+ // to find the request child node in the rest stream.\r
+ //\r
+ if (*SectionInstance == 0) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ *FoundChild = RecursedChildNode;\r
+ *FoundStream = RecursedFoundStream;\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ ErrorStatus = Status;\r
}\r
+ }\r
+\r
+ if (!IsNodeAtEnd (&SourceStream->Children, &CurrentChildNode->Link)) {\r
//\r
- // Copy in stream data\r
+ // We haven't found the child node we're interested in yet, but there's\r
+ // still more nodes that have already been parsed so get the next one\r
+ // and continue searching..\r
//\r
- CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength);\r
+ CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream->Children, &CurrentChildNode->Link));\r
} else {\r
//\r
- // It's possible to have a zero length section stream.\r
+ // We've exhausted children that have already been parsed, so see if\r
+ // there's any more data and continue parsing out more children if there\r
+ // is.\r
//\r
- NewStream->StreamBuffer = NULL;\r
+ NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size;\r
+ //\r
+ // Round up to 4 byte boundary\r
+ //\r
+ NextChildOffset += 3;\r
+ NextChildOffset &= ~(UINTN) 3;\r
+ if (NextChildOffset <= SourceStream->StreamLength - sizeof (EFI_COMMON_SECTION_HEADER)) {\r
+ //\r
+ // There's an unparsed child remaining in the stream, so create a new child node\r
+ //\r
+ Status = CreateChildNode (SourceStream, NextChildOffset, &CurrentChildNode);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ ASSERT (EFI_ERROR (ErrorStatus));\r
+ return ErrorStatus;\r
+ }\r
}\r
- } else {\r
- //\r
- // If were here, the caller has supplied the buffer (it's an internal call)\r
- // so just assign the buffer. This happens when we open section streams\r
- // as a result of expanding an encapsulating section.\r
- //\r
- NewStream->StreamBuffer = SectionStream;\r
}\r
-\r
- //\r
- // Initialize the rest of the section stream\r
- //\r
- NewStream->Signature = CORE_SECTION_STREAM_SIGNATURE;\r
- NewStream->StreamHandle = (UINTN) NewStream;\r
- NewStream->StreamLength = SectionStreamLength;\r
- InitializeListHead (&NewStream->Children);\r
- NewStream->AuthenticationStatus = AuthenticationStatus;\r
-\r
- //\r
- // Add new stream to stream list\r
- //\r
- OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
- InsertTailList (&mStreamRoot, &NewStream->Link);\r
- CoreRestoreTpl (OldTpl);\r
-\r
- *SectionStreamHandle = NewStream->StreamHandle;\r
-\r
- return EFI_SUCCESS;\r
}\r
\r
\r
-\r
/**\r
Worker function. Search stream database for requested stream handle.\r
\r
\r
\r
/**\r
- Check if a stream is valid.\r
+ SEP member function. Retrieves requested section from section stream.\r
\r
- @param SectionStream The section stream to be checked\r
- @param SectionStreamLength The length of section stream\r
+ @param SectionStreamHandle The section stream from which to extract the\r
+ requested section.\r
+ @param SectionType A pointer to the type of section to search for.\r
+ @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED,\r
+ then SectionDefinitionGuid indicates which of\r
+ these types of sections to search for.\r
+ @param SectionInstance Indicates which instance of the requested\r
+ section to return.\r
+ @param Buffer Double indirection to buffer. If *Buffer is\r
+ non-null on input, then the buffer is caller\r
+ allocated. If Buffer is NULL, then the buffer\r
+ is callee allocated. In either case, the\r
+ requried buffer size is returned in *BufferSize.\r
+ @param BufferSize On input, indicates the size of *Buffer if\r
+ *Buffer is non-null on input. On output,\r
+ indicates the required size (allocated size if\r
+ callee allocated) of *Buffer.\r
+ @param AuthenticationStatus A pointer to a caller-allocated UINT32 that\r
+ indicates the authentication status of the\r
+ output buffer. If the input section's\r
+ GuidedSectionHeader.Attributes field\r
+ has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID\r
+ bit as clear, AuthenticationStatus must return\r
+ zero. Both local bits (19:16) and aggregate\r
+ bits (3:0) in AuthenticationStatus are returned\r
+ by ExtractSection(). These bits reflect the\r
+ status of the extraction operation. The bit\r
+ pattern in both regions must be the same, as\r
+ the local and aggregate authentication statuses\r
+ have equivalent meaning at this level. If the\r
+ function returns anything other than\r
+ EFI_SUCCESS, the value of *AuthenticationStatus\r
+ is undefined.\r
\r
- @return A boolean value indicating the validness of the section stream.\r
+ @retval EFI_SUCCESS Section was retrieved successfully\r
+ @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the\r
+ section stream with its\r
+ EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set,\r
+ but there was no corresponding GUIDed Section\r
+ Extraction Protocol in the handle database.\r
+ *Buffer is unmodified.\r
+ @retval EFI_NOT_FOUND An error was encountered when parsing the\r
+ SectionStream. This indicates the SectionStream\r
+ is not correctly formatted.\r
+ @retval EFI_NOT_FOUND The requested section does not exist.\r
+ @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process\r
+ the request.\r
+ @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist.\r
+ @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is\r
+ insufficient to contain the requested section.\r
+ The input buffer is filled and section contents\r
+ are truncated.\r
\r
**/\r
-BOOLEAN\r
-IsValidSectionStream (\r
- IN VOID *SectionStream,\r
- IN UINTN SectionStreamLength\r
+EFI_STATUS\r
+EFIAPI\r
+GetSection (\r
+ IN UINTN SectionStreamHandle,\r
+ IN EFI_SECTION_TYPE *SectionType,\r
+ IN EFI_GUID *SectionDefinitionGuid,\r
+ IN UINTN SectionInstance,\r
+ IN VOID **Buffer,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT UINT32 *AuthenticationStatus\r
)\r
{\r
- UINTN TotalLength;\r
- UINTN SectionLength;\r
- EFI_COMMON_SECTION_HEADER *SectionHeader;\r
- EFI_COMMON_SECTION_HEADER *NextSectionHeader;\r
+ CORE_SECTION_STREAM_NODE *StreamNode;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ CORE_SECTION_CHILD_NODE *ChildNode;\r
+ CORE_SECTION_STREAM_NODE *ChildStreamNode;\r
+ UINTN CopySize;\r
+ UINT32 ExtractedAuthenticationStatus;\r
+ UINTN Instance;\r
+ UINT8 *CopyBuffer;\r
+ UINTN SectionSize;\r
\r
- TotalLength = 0;\r
- SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream;\r
\r
- while (TotalLength < SectionStreamLength) {\r
- SectionLength = SECTION_SIZE (SectionHeader);\r
- TotalLength += SectionLength;\r
+ OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
+ Instance = SectionInstance + 1;\r
\r
- if (TotalLength == SectionStreamLength) {\r
- return TRUE;\r
+ //\r
+ // Locate target stream\r
+ //\r
+ Status = FindStreamNode (SectionStreamHandle, &StreamNode);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto GetSection_Done;\r
+ }\r
+\r
+ //\r
+ // Found the stream, now locate and return the appropriate section\r
+ //\r
+ if (SectionType == NULL) {\r
+ //\r
+ // SectionType == NULL means return the WHOLE section stream...\r
+ //\r
+ CopySize = StreamNode->StreamLength;\r
+ CopyBuffer = StreamNode->StreamBuffer;\r
+ *AuthenticationStatus = StreamNode->AuthenticationStatus;\r
+ } else {\r
+ //\r
+ // There's a requested section type, so go find it and return it...\r
+ //\r
+ Status = FindChildNode (\r
+ StreamNode,\r
+ *SectionType,\r
+ &Instance,\r
+ SectionDefinitionGuid,\r
+ &ChildNode,\r
+ &ChildStreamNode,\r
+ &ExtractedAuthenticationStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto GetSection_Done;\r
}\r
+ CopySize = ChildNode->Size - sizeof (EFI_COMMON_SECTION_HEADER);\r
+ CopyBuffer = ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream + sizeof (EFI_COMMON_SECTION_HEADER);\r
+ *AuthenticationStatus = ExtractedAuthenticationStatus;\r
+ }\r
\r
+ SectionSize = CopySize;\r
+ if (*Buffer != NULL) {\r
//\r
- // Move to the next byte following the section...\r
+ // Caller allocated buffer. Fill to size and return required size...\r
//\r
- SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);\r
+ if (*BufferSize < CopySize) {\r
+ Status = EFI_WARN_BUFFER_TOO_SMALL;\r
+ CopySize = *BufferSize;\r
+ }\r
+ } else {\r
+ //\r
+ // Callee allocated buffer. Allocate buffer and return size.\r
+ //\r
+ *Buffer = AllocatePool (CopySize);\r
+ if (*Buffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto GetSection_Done;\r
+ }\r
+ }\r
+ CopyMem (*Buffer, CopyBuffer, CopySize);\r
+ *BufferSize = SectionSize;\r
+\r
+GetSection_Done:\r
+ CoreRestoreTpl (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Worker function. Destructor for child nodes.\r
+\r
+ @param ChildNode Indicates the node to destroy\r
\r
+**/\r
+VOID\r
+FreeChildNode (\r
+ IN CORE_SECTION_CHILD_NODE *ChildNode\r
+ )\r
+{\r
+ ASSERT (ChildNode->Signature == CORE_SECTION_CHILD_SIGNATURE);\r
+ //\r
+ // Remove the child from it's list\r
+ //\r
+ RemoveEntryList (&ChildNode->Link);\r
+\r
+ if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {\r
//\r
- // Figure out where the next section begins\r
+ // If it's an encapsulating section, we close the resulting section stream.\r
+ // CloseSectionStream will free all memory associated with the stream.\r
//\r
- NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) SectionHeader + 3);\r
- NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader & ~(UINTN)3);\r
- TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;\r
- SectionHeader = NextSectionHeader;\r
+ CloseSectionStream (ChildNode->EncapsulatedStreamHandle);\r
}\r
+ //\r
+ // Last, free the child node itself\r
+ //\r
+ CoreFreePool (ChildNode);\r
+}\r
\r
- ASSERT (FALSE);\r
- return FALSE;\r
+\r
+/**\r
+ SEP member function. Deletes an existing section stream\r
+\r
+ @param StreamHandleToClose Indicates the stream to close\r
+\r
+ @retval EFI_SUCCESS The section stream is closed sucessfully.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER Section stream does not end concident with end\r
+ of last section.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CloseSectionStream (\r
+ IN UINTN StreamHandleToClose\r
+ )\r
+{\r
+ CORE_SECTION_STREAM_NODE *StreamNode;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ CORE_SECTION_CHILD_NODE *ChildNode;\r
+\r
+ OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
+\r
+ //\r
+ // Locate target stream\r
+ //\r
+ Status = FindStreamNode (StreamHandleToClose, &StreamNode);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Found the stream, so close it\r
+ //\r
+ RemoveEntryList (&StreamNode->Link);\r
+ while (!IsListEmpty (&StreamNode->Children)) {\r
+ Link = GetFirstNode (&StreamNode->Children);\r
+ ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link);\r
+ FreeChildNode (ChildNode);\r
+ }\r
+ CoreFreePool (StreamNode->StreamBuffer);\r
+ CoreFreePool (StreamNode);\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CoreRestoreTpl (OldTpl);\r
+ return Status;\r
}\r
\r
\r
return Status;\r
}\r
\r
- if (ScratchBufferSize != 0) {\r
+ if (ScratchBufferSize > 0) {\r
//\r
// Allocate scratch buffer\r
//\r
//\r
AllocatedOutputBuffer = AllocatePool (OutputBufferSize);\r
if (AllocatedOutputBuffer == NULL) {\r
+ FreePool (ScratchBuffer);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
*OutputBuffer = AllocatedOutputBuffer;\r