-/**@file\r
+/** @file\r
Section Extraction Protocol implementation.\r
\r
Stream database is implemented as a linked list of section streams,\r
3) A support protocol is not found, and the data is not available to be read\r
without it. This results in EFI_PROTOCOL_ERROR.\r
\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
\r
-#include "SectionExtraction.h"\r
+#include <FrameworkDxe.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Protocol/Decompress.h>\r
+#include <Protocol/GuidedSectionExtraction.h>\r
+#include <Protocol/SectionExtraction.h>\r
\r
//\r
// Local defines and typedefs\r
//\r
-#define CORE_SECTION_CHILD_SIGNATURE EFI_SIGNATURE_32('S','X','C','S')\r
+#define FRAMEWORK_SECTION_CHILD_SIGNATURE SIGNATURE_32('S','X','F','S')\r
#define CHILD_SECTION_NODE_FROM_LINK(Node) \\r
- CR (Node, CORE_SECTION_CHILD_NODE, Link, CORE_SECTION_CHILD_SIGNATURE)\r
+ CR (Node, FRAMEWORK_SECTION_CHILD_NODE, Link, FRAMEWORK_SECTION_CHILD_SIGNATURE)\r
\r
typedef struct {\r
UINT32 Signature;\r
//\r
UINTN EncapsulatedStreamHandle;\r
EFI_GUID *EncapsulationGuid;\r
-} CORE_SECTION_CHILD_NODE;\r
+ //\r
+ // If the section REQUIRES an extraction protocol, register for RPN \r
+ // when the required GUIDed extraction protocol becomes available.\r
+ //\r
+ EFI_EVENT Event;\r
+} FRAMEWORK_SECTION_CHILD_NODE;\r
\r
-#define CORE_SECTION_STREAM_SIGNATURE EFI_SIGNATURE_32('S','X','S','S')\r
+#define FRAMEWORK_SECTION_STREAM_SIGNATURE SIGNATURE_32('S','X','S','S')\r
#define STREAM_NODE_FROM_LINK(Node) \\r
- CR (Node, CORE_SECTION_STREAM_NODE, Link, CORE_SECTION_STREAM_SIGNATURE)\r
+ CR (Node, FRAMEWORK_SECTION_STREAM_NODE, Link, FRAMEWORK_SECTION_STREAM_SIGNATURE)\r
\r
typedef struct {\r
UINT32 Signature;\r
// Authentication status is from GUIDed encapsulations.\r
//\r
UINT32 AuthenticationStatus;\r
-} CORE_SECTION_STREAM_NODE;\r
+} FRAMEWORK_SECTION_STREAM_NODE;\r
\r
#define NULL_STREAM_HANDLE 0\r
\r
typedef struct {\r
- CORE_SECTION_CHILD_NODE *ChildNode;\r
- CORE_SECTION_STREAM_NODE *ParentStream;\r
- VOID *Registration;\r
- EFI_EVENT Event;\r
+ FRAMEWORK_SECTION_CHILD_NODE *ChildNode;\r
+ FRAMEWORK_SECTION_STREAM_NODE *ParentStream;\r
+ VOID *Registration;\r
} RPN_EVENT_CONTEXT;\r
- \r
- \r
-EFI_EVENT\r
-CoreCreateProtocolNotifyEvent (\r
- IN EFI_GUID *ProtocolGuid,\r
- IN EFI_TPL NotifyTpl,\r
- IN EFI_EVENT_NOTIFY NotifyFunction,\r
- IN VOID *NotifyContext,\r
- OUT VOID **Registration,\r
- IN BOOLEAN SignalFlag\r
- );\r
-\r
-//\r
-// Local prototypes\r
-//\r
\r
-STATIC\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
+ SEP member function. This function creates and returns a new section stream\r
+ handle to represent the new section stream.\r
\r
-STATIC\r
-VOID\r
-EFIAPI\r
-NotifyGuidedExtraction (\r
- IN EFI_EVENT Event,\r
- IN VOID *RpnContext\r
- );\r
+ @param This Indicates the calling context.\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 output\r
+ contains the new section stream handle.\r
\r
-STATIC\r
-VOID\r
-CreateGuidedExtractionRpnEvent (\r
- IN CORE_SECTION_STREAM_NODE *ParentStream,\r
- IN CORE_SECTION_CHILD_NODE *ChildNode\r
- );\r
+ @retval EFI_SUCCESS Section wase opened successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of\r
+ last section.\r
\r
-STATIC\r
+**/\r
EFI_STATUS\r
EFIAPI\r
OpenSectionStream (\r
- IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\r
- IN UINTN SectionStreamLength,\r
- IN VOID *SectionStream,\r
- OUT UINTN *SectionStreamHandle\r
- );\r
- \r
-STATIC\r
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\r
+ IN UINTN SectionStreamLength,\r
+ IN VOID *SectionStream,\r
+ OUT UINTN *SectionStreamHandle\r
+ )\r
+;\r
+\r
+/**\r
+ SEP member function. Retrieves requested section from section stream.\r
+\r
+ @param This Pointer to SEP instance.\r
+ @param SectionStreamHandle The section stream from which to extract the requested\r
+ 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, then\r
+ SectionDefinitionGuid indicates which of these types\r
+ of sections to search for.\r
+ @param SectionInstance Indicates which instance of the requested section to\r
+ return.\r
+ @param Buffer Double indirection to buffer. If *Buffer is non-null on\r
+ input, then the buffer is caller allocated. If\r
+ *Buffer is NULL, then the buffer is callee allocated.\r
+ In either case, the required buffer size is returned\r
+ in *BufferSize.\r
+ @param BufferSize On input, indicates the size of *Buffer if *Buffer is\r
+ non-null on input. On output, indicates the required\r
+ size (allocated size if callee allocated) of *Buffer.\r
+ @param AuthenticationStatus Indicates the authentication status of the retrieved\r
+ section.\r
+\r
+ \r
+ @retval EFI_SUCCESS Section was retrieved successfully\r
+ @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the section \r
+ stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED\r
+ bit set, but there was no corresponding GUIDed Section \r
+ Extraction Protocol in the handle database. *Buffer is \r
+ unmodified.\r
+ @retval EFI_NOT_FOUND An error was encountered when parsing the SectionStream.\r
+ This indicates the SectionStream is not correctly \r
+ 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 the \r
+ 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. The \r
+ input buffer is filled and contents are section contents\r
+ are truncated.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
GetSection (\r
- IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\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
-STATIC\r
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\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
+\r
+/**\r
+ SEP member function. Deletes an existing section stream\r
+\r
+ @param This Indicates the calling context.\r
+ @param StreamHandleToClose Indicates the stream to close\r
+\r
+ @retval EFI_SUCCESS Section stream was closed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of\r
+ last section.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
CloseSectionStream (\r
- IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\r
- IN UINTN StreamHandleToClose\r
- );\r
- \r
-STATIC\r
-EFI_STATUS\r
-FindStreamNode (\r
- IN UINTN SearchHandle,\r
- OUT CORE_SECTION_STREAM_NODE **FoundStream\r
- );\r
- \r
-STATIC\r
-EFI_STATUS\r
-FindChildNode (\r
- IN CORE_SECTION_STREAM_NODE *SourceStream,\r
- IN EFI_SECTION_TYPE SearchType,\r
- IN 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
-STATIC\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
-STATIC\r
-VOID\r
-FreeChildNode (\r
- IN CORE_SECTION_CHILD_NODE *ChildNode\r
- );\r
- \r
-STATIC\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
-STATIC\r
-BOOLEAN\r
-IsValidSectionStream (\r
- IN VOID *SectionStream,\r
- IN UINTN SectionStreamLength\r
- );\r
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\r
+ IN UINTN StreamHandleToClose\r
+ )\r
+;\r
\r
//\r
// Module globals\r
Entry point of the section extraction code. Initializes an instance of the \r
section extraction interface and installs it on a new handle.\r
\r
- @param ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver\r
- @param SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table \r
+ @param ImageHandle A handle for the image that is initializing this driver\r
+ @param SystemTable A pointer to the EFI system table \r
\r
@retval EFI_SUCCESS Driver initialized successfully\r
@retval EFI_OUT_OF_RESOURCES Could not allocate needed resources\r
return Status;\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
+ 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
+ if (IS_SECTION2 (SectionHeader)) {\r
+ SectionLength = SECTION2_SIZE (SectionHeader);\r
+ } else {\r
+ SectionLength = SECTION_SIZE (SectionHeader);\r
+ }\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
+ ASSERT (FALSE);\r
+ return FALSE;\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 copied\r
+ or the input buffer is to be used in place.\r
+ @param AuthenticationStatus Indicates the default authentication status for the\r
+ new stream.\r
+ @param SectionStreamHandle A pointer to a caller allocated section stream 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
+ FRAMEWORK_SECTION_STREAM_NODE *NewStream;\r
+ EFI_TPL OldTpl;\r
+ \r
+ //\r
+ // Allocate a new stream\r
+ //\r
+ NewStream = AllocatePool (sizeof (FRAMEWORK_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
+ FreePool (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
+ // 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 = FRAMEWORK_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 = gBS->RaiseTPL (TPL_NOTIFY);\r
+ InsertTailList (&mStreamRoot, &NewStream->Link);\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ *SectionStreamHandle = NewStream->StreamHandle;\r
+ \r
+ return EFI_SUCCESS;\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
@param SectionStreamHandle A pointer to a caller allocated UINTN that on output\r
contains the new section stream handle.\r
\r
- @retval EFI_SUCCESS\r
- @retval EFI_OUT_OF_RESOURCES memory allocation failed.\r
- @retval EFI_INVALID_PARAMETER section stream does not end concident with end of\r
+ @retval EFI_SUCCESS Section wase opened successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of\r
last section.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
EFIAPI\r
OpenSectionStream (\r
SectionStreamHandle\r
);\r
}\r
- \r
+\r
/**\r
- SEP member function. Retrieves requested section from section stream.\r
+ Worker function. Determine if the input stream:child matches the input type.\r
\r
- @param This: Pointer to SEP instance.\r
- @param SectionStreamHandle: The section stream from which to extract the requested\r
- 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, then\r
- SectionDefinitionGuid indicates which of these types\r
- of sections to search for.\r
- @param SectionInstance: Indicates which instance of the requested section to\r
- return.\r
- @param Buffer: Double indirection to buffer. If *Buffer is non-null on\r
- input, then the buffer is caller allocated. If\r
- *Buffer is NULL, then the buffer is callee allocated.\r
- In either case, the requried buffer size is returned\r
- in *BufferSize.\r
- @param BufferSize: On input, indicates the size of *Buffer if *Buffer is\r
- non-null on input. On output, indicates the required\r
- size (allocated size if callee allocated) of *Buffer.\r
- @param AuthenticationStatus: Indicates the authentication status of the retrieved\r
- section.\r
+ @param Stream Indicates the section stream associated with the child\r
+ @param Child Indicates the child to check\r
+ @param SearchType Indicates the type of section to check against for\r
+ @param SectionDefinitionGuid Indicates the GUID to check against if the type is\r
+ EFI_SECTION_GUID_DEFINED\r
\r
- \r
- @retval EFI_SUCCESS: Section was retrieved successfully\r
- @retval EFI_PROTOCOL_ERROR: A GUID defined section was encountered in the section \r
- stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED\r
- bit set, but there was no corresponding GUIDed Section \r
- Extraction Protocol in the handle database. *Buffer is \r
- unmodified.\r
- @retval EFI_NOT_FOUND: An error was encountered when parsing the SectionStream.\r
- This indicates the SectionStream is not correctly \r
- 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 the \r
- 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. The \r
- input buffer is filled and contents are section contents\r
- are truncated.\r
-\r
-**/ \r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-GetSection (\r
- IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\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
+ @retval TRUE The child matches\r
+ @retval FALSE The child doesn't match\r
\r
+**/\r
+BOOLEAN\r
+ChildIsType (\r
+ IN FRAMEWORK_SECTION_STREAM_NODE *Stream,\r
+ IN FRAMEWORK_SECTION_CHILD_NODE *Child,\r
+ IN EFI_SECTION_TYPE SearchType,\r
+ IN EFI_GUID *SectionDefinitionGuid\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 = gBS->RaiseTPL (TPL_NOTIFY);\r
- Instance = SectionInstance + 1;\r
+ EFI_GUID_DEFINED_SECTION *GuidedSection;\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
+ if (SearchType == EFI_SECTION_ALL) {\r
+ return TRUE;\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
- // Caller allocated buffer. Fill to size and return required size...\r
- //\r
- if (*BufferSize < CopySize) {\r
- Status = EFI_WARN_BUFFER_TOO_SMALL;\r
- CopySize = *BufferSize;\r
- }\r
+ if (Child->Type != SearchType) {\r
+ return FALSE;\r
+ }\r
+ if ((SearchType != EFI_SECTION_GUID_DEFINED) || (SectionDefinitionGuid == NULL)) {\r
+ return TRUE;\r
+ }\r
+ GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);\r
+ if (IS_SECTION2 (GuidedSection)) {\r
+ return CompareGuid (&(((EFI_GUID_DEFINED_SECTION2 *) GuidedSection)->SectionDefinitionGuid), SectionDefinitionGuid);\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
+ return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid);\r
}\r
- CopyMem (*Buffer, CopyBuffer, CopySize);\r
- *BufferSize = SectionSize;\r
- \r
-GetSection_Done:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
}\r
\r
/**\r
- SEP member function. Deletes an existing section stream\r
+ Create a protocol notification event and return it.\r
\r
- @param This - Indicates the calling context.\r
- @param StreamHandleToClose - Indicates the stream to close\r
+ @param ProtocolGuid Protocol to register notification event on.\r
+ @param NotifyTpl Maximum TPL to signal the NotifyFunction.\r
+ @param NotifyFunction EFI notification routine.\r
+ @param NotifyContext Context passed into Event when it is created.\r
+ @param Registration Registration key returned from RegisterProtocolNotify().\r
+ @param SignalFlag Boolean value to decide whether kick the event after register or not.\r
\r
- @retval EFI_SUCCESS\r
- @retval EFI_OUT_OF_RESOURCES - memory allocation failed.\r
- @retval EFI_INVALID_PARAMETER - section stream does not end concident with end of\r
- last section.\r
+ @return The EFI_EVENT that has been registered to be signaled when a ProtocolGuid\r
+ is added to the system.\r
\r
**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-CloseSectionStream (\r
- IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\r
- IN UINTN StreamHandleToClose\r
+EFI_EVENT\r
+CreateProtocolNotifyEvent (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ IN EFI_TPL NotifyTpl,\r
+ IN EFI_EVENT_NOTIFY NotifyFunction,\r
+ IN VOID *NotifyContext,\r
+ OUT VOID **Registration,\r
+ IN BOOLEAN SignalFlag\r
)\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 = gBS->RaiseTPL (TPL_NOTIFY);\r
- \r
+ EFI_STATUS Status;\r
+ EFI_EVENT Event;\r
+\r
//\r
- // Locate target stream\r
+ // Create the event\r
//\r
- Status = FindStreamNode (StreamHandleToClose, &StreamNode);\r
- if (!EFI_ERROR (Status)) {\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ NotifyTpl,\r
+ NotifyFunction,\r
+ NotifyContext,\r
+ &Event\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register for protocol notifactions on this event\r
+ //\r
+\r
+ Status = gBS->RegisterProtocolNotify (\r
+ ProtocolGuid,\r
+ Event,\r
+ Registration\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (SignalFlag) {\r
//\r
- // Found the stream, so close it\r
+ // Kick the event so we will perform an initial pass of\r
+ // current installed drivers\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
- gBS->FreePool (StreamNode->StreamBuffer);\r
- gBS->FreePool (StreamNode);\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = EFI_INVALID_PARAMETER;\r
+ gBS->SignalEvent (Event);\r
}\r
- \r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
+\r
+ return Event;\r
}\r
\r
/**\r
- Worker function. Determine if the input stream:child matches the input type.\r
+ Verify the Guided Section GUID by checking if there is the Guided Section GUID configuration table recorded the GUID itself.\r
\r
- @param Stream - Indicates the section stream associated with the child\r
- @param Child - Indicates the child to check\r
- @param SearchType - Indicates the type of section to check against for\r
- @param SectionDefinitionGuid - Indicates the GUID to check against if the type is\r
- EFI_SECTION_GUID_DEFINED\r
+ @param GuidedSectionGuid The Guided Section GUID.\r
+ @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Protocol\r
+ for the Guided Section.\r
\r
- @retval TRUE - The child matches\r
- @retval FALSE - The child doesn't match\r
+ @return TRUE The GuidedSectionGuid could be identified, and the pointer to\r
+ the Guided Section Extraction Protocol will be returned to *GuidedSectionExtraction.\r
+ @return FALSE The GuidedSectionGuid could not be identified, or \r
+ the Guided Section Extraction Protocol has not been installed yet.\r
\r
**/\r
-STATIC\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
+VerifyGuidedSectionGuid (\r
+ IN EFI_GUID *GuidedSectionGuid,\r
+ OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL **GuidedSectionExtraction\r
)\r
{\r
- EFI_GUID_DEFINED_SECTION *GuidedSection;\r
- \r
- if (SearchType == EFI_SECTION_ALL) {\r
- return TRUE;\r
- }\r
- if (Child->Type != SearchType) {\r
- return FALSE;\r
- }\r
- if (SearchType != EFI_SECTION_GUID_DEFINED) {\r
- return TRUE;\r
+ EFI_GUID *GuidRecorded;\r
+ VOID *Interface;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check if there is the Guided Section GUID configuration table recorded the GUID itself.\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (GuidedSectionGuid, (VOID **) &GuidRecorded);\r
+ if (Status == EFI_SUCCESS) {\r
+ if (CompareGuid (GuidRecorded, GuidedSectionGuid)) {\r
+ //\r
+ // Found the recorded GuidedSectionGuid.\r
+ //\r
+ Status = gBS->LocateProtocol (GuidedSectionGuid, NULL, (VOID **) &Interface);\r
+ if (!EFI_ERROR (Status) && Interface != NULL) {\r
+ //\r
+ // Found the supported Guided Section Extraction Porotocol for the Guided Section.\r
+ //\r
+ *GuidedSectionExtraction = (EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *) Interface;\r
+ return TRUE;\r
+ }\r
+ return FALSE;\r
+ }\r
}\r
- GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);\r
- return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid);\r
+\r
+ return FALSE;\r
}\r
\r
/**\r
- Worker function Recursively searches / builds section stream database\r
- looking for requested section.\r
+ RPN callback function. \r
+ 1. Initialize the section stream when the GUIDED_SECTION_EXTRACTION_PROTOCOL is installed.\r
+ 2. Removes a stale section stream and re-initializes it with an updated AuthenticationStatus.\r
\r
-\r
- @param SourceStream - Indicates the section stream in which to do the search.\r
- @param SearchType - Indicates the type of section to search for.\r
- @param SectionInstance - Indicates which instance of section to find. This is\r
- an in/out parameter to deal with 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 was\r
- found in. If this stream was generated as a result of\r
- an encapsulation section, the streamhandle is visible\r
- within the SEP driver only.\r
- @param AuthenticationStatus- Indicates the authentication status of the found section.\r
-\r
- @retval EFI_SUCCESS - Child node was found and returned.\r
- @retval 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 does not\r
- exist\r
+ @param Event The event that fired\r
+ @param RpnContext A pointer to the context that allows us to identify\r
+ the relevent encapsulation.\r
\r
**/\r
-STATIC\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
+VOID\r
+EFIAPI\r
+NotifyGuidedExtraction (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *RpnContext\r
)\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
+ EFI_STATUS Status;\r
+ EFI_GUID_DEFINED_SECTION *GuidedHeader;\r
+ EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;\r
+ VOID *NewStreamBuffer;\r
+ UINTN NewStreamBufferSize;\r
+ UINT32 AuthenticationStatus;\r
+ RPN_EVENT_CONTEXT *Context;\r
\r
- if (SourceStream->StreamLength == 0) {\r
- return EFI_NOT_FOUND;\r
+ Context = RpnContext;\r
+ Status = EFI_SUCCESS;\r
+ if (Context->ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {\r
+ Status = CloseSectionStream (&mSectionExtraction, Context->ChildNode->EncapsulatedStreamHandle);\r
}\r
- \r
- if (IsListEmpty (&SourceStream->Children) && \r
- SourceStream->StreamLength > sizeof (EFI_COMMON_SECTION_HEADER)) {\r
+ if (!EFI_ERROR (Status)) {\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
+ // The stream is not initialized, open it. \r
+ // Or the stream closed successfully, so re-open the stream with correct AuthenticationStatus.\r
//\r
- Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ \r
+ GuidedHeader = (EFI_GUID_DEFINED_SECTION *) \r
+ (Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream);\r
+ ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED);\r
+ \r
+ if (!VerifyGuidedSectionGuid (Context->ChildNode->EncapsulationGuid, &GuidedExtraction)) {\r
+ return;\r
}\r
+\r
+ Status = GuidedExtraction->ExtractSection (\r
+ GuidedExtraction,\r
+ GuidedHeader,\r
+ &NewStreamBuffer,\r
+ &NewStreamBufferSize,\r
+ &AuthenticationStatus\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // OR in the parent stream's aggregate status.\r
+ //\r
+ AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL;\r
+ Status = OpenSectionStreamEx (\r
+ NewStreamBufferSize,\r
+ NewStreamBuffer,\r
+ FALSE,\r
+ AuthenticationStatus,\r
+ &Context->ChildNode->EncapsulatedStreamHandle\r
+ );\r
+ ASSERT_EFI_ERROR (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
+ // If above, the stream did not close successfully, it indicates it's\r
+ // already been closed by someone, so just destroy the event and be done with\r
+ // it.\r
//\r
- CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children));\r
+ \r
+ gBS->CloseEvent (Event);\r
+ Context->ChildNode->Event = NULL;\r
+ FreePool (Context);\r
+} \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
+ Worker function. Constructor for RPN event if needed to keep AuthenticationStatus\r
+ cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...\r
+\r
+ @param ParentStream Indicates the parent of the ecnapsulation section (child)\r
+ @param ChildNode Indicates the child node that is the encapsulation section.\r
+\r
+**/\r
+VOID\r
+CreateGuidedExtractionRpnEvent (\r
+ IN FRAMEWORK_SECTION_STREAM_NODE *ParentStream,\r
+ IN FRAMEWORK_SECTION_CHILD_NODE *ChildNode\r
+ )\r
+{\r
+ RPN_EVENT_CONTEXT *Context;\r
+ \r
+ //\r
+ // Allocate new event structure and context\r
+ //\r
+ Context = AllocatePool (sizeof (RPN_EVENT_CONTEXT));\r
+ ASSERT (Context != NULL);\r
+ \r
+ Context->ChildNode = ChildNode;\r
+ Context->ParentStream = ParentStream;\r
+ \r
+ Context->ChildNode->Event = CreateProtocolNotifyEvent (\r
+ Context->ChildNode->EncapsulationGuid,\r
+ TPL_NOTIFY,\r
+ NotifyGuidedExtraction,\r
+ Context,\r
+ &Context->Registration,\r
+ FALSE\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 child.\r
- @param ChildOffset - Indicates the offset in Stream that is the beginning\r
- of the child section.\r
- @param ChildNode - Indicates the Callee allocated and initialized child.\r
+ @param Stream Indicates the section stream in which to add the child.\r
+ @param ChildOffset Indicates the offset in Stream that is the beginning\r
+ of the child section.\r
+ @param ChildNode Indicates the Callee allocated and initialized child.\r
\r
- @retval EFI_SUCCESS - Child node was found and returned.\r
- @retval EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
- @retval EFI_PROTOCOL_ERROR - Encapsulation sections produce new stream handles when\r
- the child node is created. If the section type is GUID\r
- defined, and the extraction GUID does not exist, and\r
- producing the stream requires the GUID, then a protocol\r
- error is generated and no child is produced.\r
- Values returned by OpenSectionStreamEx.\r
+ @retval EFI_SUCCESS Child node was found and returned.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream handles when\r
+ the child node is created. If the section type is GUID\r
+ defined, and the extraction GUID does not exist, and\r
+ producing the stream requires the GUID, then a protocol\r
+ error is generated and no child is produced.\r
+ Values returned by OpenSectionStreamEx.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CreateChildNode (\r
- IN CORE_SECTION_STREAM_NODE *Stream,\r
- IN UINT32 ChildOffset,\r
- OUT CORE_SECTION_CHILD_NODE **ChildNode\r
+ IN FRAMEWORK_SECTION_STREAM_NODE *Stream,\r
+ IN UINT32 ChildOffset,\r
+ OUT FRAMEWORK_SECTION_CHILD_NODE **ChildNode\r
)\r
{\r
EFI_STATUS Status;\r
UINT32 ScratchSize;\r
UINTN NewStreamBufferSize;\r
UINT32 AuthenticationStatus;\r
- UINT32 SectionLength;\r
+ VOID *CompressionSource;\r
+ UINT32 CompressionSourceSize;\r
+ UINT32 UncompressedLength;\r
+ UINT8 CompressionType;\r
+ UINT16 GuidedSectionAttributes;\r
\r
- CORE_SECTION_CHILD_NODE *Node;\r
+ FRAMEWORK_SECTION_CHILD_NODE *Node;\r
\r
SectionHeader = (EFI_COMMON_SECTION_HEADER *) (Stream->StreamBuffer + ChildOffset);\r
\r
//\r
// Allocate a new node\r
//\r
- *ChildNode = AllocatePool (sizeof (CORE_SECTION_CHILD_NODE));\r
+ *ChildNode = AllocateZeroPool (sizeof (FRAMEWORK_SECTION_CHILD_NODE));\r
Node = *ChildNode;\r
if (Node == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
//\r
// Now initialize it\r
//\r
- Node->Signature = CORE_SECTION_CHILD_SIGNATURE;\r
+ Node->Signature = FRAMEWORK_SECTION_CHILD_SIGNATURE;\r
Node->Type = SectionHeader->Type;\r
- Node->Size = SECTION_SIZE (SectionHeader);\r
+ if (IS_SECTION2 (SectionHeader)) {\r
+ Node->Size = SECTION2_SIZE (SectionHeader);\r
+ } else {\r
+ Node->Size = SECTION_SIZE (SectionHeader);\r
+ }\r
Node->OffsetInStream = ChildOffset;\r
Node->EncapsulatedStreamHandle = NULL_STREAM_HANDLE;\r
Node->EncapsulationGuid = NULL;\r
//\r
// Get the CompressionSectionHeader\r
//\r
- ASSERT (Node->Size >= sizeof (EFI_COMPRESSION_SECTION));\r
- \r
+ if (Node->Size < sizeof (EFI_COMPRESSION_SECTION)) {\r
+ FreePool (Node);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
CompressionHeader = (EFI_COMPRESSION_SECTION *) SectionHeader;\r
- \r
+\r
+ if (IS_SECTION2 (CompressionHeader)) {\r
+ CompressionSource = (VOID *) ((UINT8 *) CompressionHeader + sizeof (EFI_COMPRESSION_SECTION2));\r
+ CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionHeader) - sizeof (EFI_COMPRESSION_SECTION2));\r
+ UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionHeader)->UncompressedLength;\r
+ CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionHeader)->CompressionType;\r
+ } else {\r
+ CompressionSource = (VOID *) ((UINT8 *) CompressionHeader + sizeof (EFI_COMPRESSION_SECTION));\r
+ CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionHeader) - sizeof (EFI_COMPRESSION_SECTION));\r
+ UncompressedLength = CompressionHeader->UncompressedLength;\r
+ CompressionType = CompressionHeader->CompressionType;\r
+ }\r
+\r
//\r
// Allocate space for the new stream\r
//\r
- if (CompressionHeader->UncompressedLength > 0) {\r
- NewStreamBufferSize = CompressionHeader->UncompressedLength;\r
+ if (UncompressedLength > 0) {\r
+ NewStreamBufferSize = UncompressedLength;\r
NewStreamBuffer = AllocatePool (NewStreamBufferSize);\r
if (NewStreamBuffer == NULL) {\r
- gBS->FreePool (Node);\r
+ FreePool (Node);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- if (CompressionHeader->CompressionType == EFI_NOT_COMPRESSED) {\r
+ if (CompressionType == EFI_NOT_COMPRESSED) {\r
//\r
// stream is not actually compressed, just encapsulated. So just copy it.\r
//\r
- CopyMem (NewStreamBuffer, CompressionHeader + 1, NewStreamBufferSize);\r
- } else if (CompressionHeader->CompressionType == EFI_STANDARD_COMPRESSION) {\r
+ CopyMem (NewStreamBuffer, CompressionSource, NewStreamBufferSize);\r
+ } else if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
//\r
// Only support the EFI_SATNDARD_COMPRESSION algorithm.\r
// \r
\r
Status = Decompress->GetInfo (\r
Decompress,\r
- CompressionHeader + 1,\r
- Node->Size - sizeof (EFI_COMPRESSION_SECTION),\r
+ CompressionSource,\r
+ CompressionSourceSize,\r
(UINT32 *)&NewStreamBufferSize,\r
&ScratchSize\r
);\r
- ASSERT_EFI_ERROR (Status);\r
- ASSERT (NewStreamBufferSize == CompressionHeader->UncompressedLength);\r
+ if (EFI_ERROR (Status) || (NewStreamBufferSize != UncompressedLength)) {\r
+ FreePool (Node);\r
+ FreePool (NewStreamBuffer);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = EFI_BAD_BUFFER_SIZE;\r
+ }\r
+ return Status;\r
+ }\r
\r
ScratchBuffer = AllocatePool (ScratchSize);\r
if (ScratchBuffer == NULL) {\r
- gBS->FreePool (Node);\r
- gBS->FreePool (NewStreamBuffer);\r
+ FreePool (Node);\r
+ FreePool (NewStreamBuffer);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
Status = Decompress->Decompress (\r
Decompress,\r
- CompressionHeader + 1,\r
- Node->Size - sizeof (EFI_COMPRESSION_SECTION),\r
+ CompressionSource,\r
+ CompressionSourceSize,\r
NewStreamBuffer,\r
(UINT32)NewStreamBufferSize,\r
ScratchBuffer,\r
ScratchSize\r
);\r
- ASSERT_EFI_ERROR (Status);\r
- gBS->FreePool (ScratchBuffer); \r
+ FreePool (ScratchBuffer); \r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Node);\r
+ FreePool (NewStreamBuffer);\r
+ return Status;\r
+ }\r
}\r
} else {\r
NewStreamBuffer = NULL;\r
&Node->EncapsulatedStreamHandle\r
);\r
if (EFI_ERROR (Status)) {\r
- gBS->FreePool (Node);\r
- gBS->FreePool (NewStreamBuffer);\r
+ FreePool (Node);\r
+ FreePool (NewStreamBuffer);\r
return Status;\r
}\r
break;\r
\r
case EFI_SECTION_GUID_DEFINED:\r
GuidedHeader = (EFI_GUID_DEFINED_SECTION *) SectionHeader;\r
- Node->EncapsulationGuid = &GuidedHeader->SectionDefinitionGuid;\r
- Status = gBS->LocateProtocol (Node->EncapsulationGuid, NULL, (VOID **)&GuidedExtraction);\r
- if (!EFI_ERROR (Status)) {\r
+ if (IS_SECTION2 (GuidedHeader)) {\r
+ Node->EncapsulationGuid = &(((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->SectionDefinitionGuid);\r
+ GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->Attributes;\r
+ } else {\r
+ Node->EncapsulationGuid = &GuidedHeader->SectionDefinitionGuid;\r
+ GuidedSectionAttributes = GuidedHeader->Attributes;\r
+ }\r
+ if (VerifyGuidedSectionGuid (Node->EncapsulationGuid, &GuidedExtraction)) {\r
//\r
// NewStreamBuffer is always allocated by ExtractSection... No caller\r
// allocation here.\r
&AuthenticationStatus\r
);\r
if (EFI_ERROR (Status)) {\r
- gBS->FreePool (*ChildNode);\r
+ FreePool (*ChildNode);\r
return EFI_PROTOCOL_ERROR;\r
}\r
\r
// Make sure we initialize the new stream with the correct \r
// authentication status for both aggregate and local status fields.\r
//\r
- if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {\r
+ if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {\r
//\r
// OR in the parent stream's aggregate status.\r
//\r
&Node->EncapsulatedStreamHandle\r
);\r
if (EFI_ERROR (Status)) {\r
- gBS->FreePool (*ChildNode);\r
- gBS->FreePool (NewStreamBuffer);\r
+ FreePool (*ChildNode);\r
+ FreePool (NewStreamBuffer);\r
return Status;\r
}\r
} else {\r
//\r
// There's no GUIDed section extraction protocol available.\r
//\r
- if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {\r
+ if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {\r
//\r
- // If the section REQUIRES an extraction protocol, then we're toast\r
+ // If the section REQUIRES an extraction protocol, register for RPN \r
+ // when the required GUIDed extraction protocol becomes available. \r
//\r
- gBS->FreePool (*ChildNode);\r
- return EFI_PROTOCOL_ERROR;\r
- }\r
- \r
- //\r
- // Figure out the proper authentication status\r
- //\r
- AuthenticationStatus = Stream->AuthenticationStatus;\r
- if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {\r
+ AuthenticationStatus = 0;\r
+ CreateGuidedExtractionRpnEvent (Stream, Node);\r
+ } else {\r
//\r
- // The local status of the new stream is contained in \r
- // AuthenticaionStatus. This value needs to be ORed into the\r
- // Aggregate bits also...\r
+ // Figure out the proper authentication status\r
//\r
+ AuthenticationStatus = Stream->AuthenticationStatus;\r
+ if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {\r
+ //\r
+ // The local status of the new stream is contained in \r
+ // AuthenticaionStatus. This value needs to be ORed into the\r
+ // Aggregate bits also...\r
+ //\r
+ \r
+ //\r
+ // Clear out and initialize the local status\r
+ //\r
+ AuthenticationStatus &= ~EFI_LOCAL_AUTH_STATUS_ALL;\r
+ AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED;\r
+ //\r
+ // OR local status into aggregate status\r
+ //\r
+ AuthenticationStatus |= AuthenticationStatus >> 16;\r
+ }\r
\r
- //\r
- // Clear out and initialize the local status\r
- //\r
- AuthenticationStatus &= ~EFI_LOCAL_AUTH_STATUS_ALL;\r
- AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED;\r
- //\r
- // OR local status into aggregate status\r
- //\r
- AuthenticationStatus |= AuthenticationStatus >> 16;\r
- }\r
- \r
- SectionLength = SECTION_SIZE (GuidedHeader);\r
- Status = OpenSectionStreamEx (\r
- SectionLength - GuidedHeader->DataOffset,\r
- (UINT8 *) GuidedHeader + GuidedHeader->DataOffset,\r
- TRUE,\r
- AuthenticationStatus,\r
- &Node->EncapsulatedStreamHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (Node);\r
- return Status;\r
+ if (IS_SECTION2 (GuidedHeader)) {\r
+ Status = OpenSectionStreamEx (\r
+ SECTION2_SIZE (GuidedHeader) - ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->DataOffset,\r
+ (UINT8 *) GuidedHeader + ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->DataOffset,\r
+ TRUE,\r
+ AuthenticationStatus,\r
+ &Node->EncapsulatedStreamHandle\r
+ );\r
+ } else {\r
+ Status = OpenSectionStreamEx (\r
+ SECTION_SIZE (GuidedHeader) - ((EFI_GUID_DEFINED_SECTION *) GuidedHeader)->DataOffset,\r
+ (UINT8 *) GuidedHeader + ((EFI_GUID_DEFINED_SECTION *) GuidedHeader)->DataOffset,\r
+ TRUE,\r
+ AuthenticationStatus,\r
+ &Node->EncapsulatedStreamHandle\r
+ );\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Node);\r
+ return Status;\r
+ }\r
}\r
}\r
\r
}\r
\r
/**\r
- Worker function. Constructor for RPN event if needed to keep AuthenticationStatus\r
- cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...\r
-\r
- @param ParentStream - Indicates the parent of the ecnapsulation section (child)\r
- @param ChildNode - Indicates the child node that is the encapsulation section.\r
+ Worker function Recursively searches / builds section stream database\r
+ looking for requested section.\r
\r
-**/\r
-STATIC\r
-VOID\r
-CreateGuidedExtractionRpnEvent (\r
- IN CORE_SECTION_STREAM_NODE *ParentStream,\r
- IN CORE_SECTION_CHILD_NODE *ChildNode\r
- )\r
-{\r
- RPN_EVENT_CONTEXT *Context;\r
- \r
- //\r
- // Allocate new event structure and context\r
- //\r
- Context = AllocatePool (sizeof (RPN_EVENT_CONTEXT));\r
- ASSERT (Context != NULL);\r
- \r
- Context->ChildNode = ChildNode;\r
- Context->ParentStream = ParentStream;\r
- \r
- Context->Event = CoreCreateProtocolNotifyEvent (\r
- Context->ChildNode->EncapsulationGuid,\r
- TPL_NOTIFY,\r
- NotifyGuidedExtraction,\r
- Context,\r
- &Context->Registration,\r
- FALSE\r
- );\r
-}\r
- \r
-/**\r
- RPN callback function. Removes a stale section stream and re-initializes it\r
- with an updated AuthenticationStatus.\r
\r
- @param Event - The event that fired\r
- @param RpnContext - A pointer to the context that allows us to identify\r
- the relevent encapsulation...\r
+ @param SourceStream Indicates the section stream in which to do the search.\r
+ @param SearchType Indicates the type of section to search for.\r
+ @param SectionInstance Indicates which instance of section to find. This is\r
+ an in/out parameter to deal with 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 was\r
+ found in. If this stream was generated as a result of\r
+ an encapsulation section, the streamhandle is visible\r
+ within the SEP driver only.\r
+ @param AuthenticationStatus Indicates the authentication status of the found section.\r
+\r
+ @retval EFI_SUCCESS Child node was found and returned.\r
+ @retval 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 does not\r
+ exist\r
\r
-**/ \r
-STATIC\r
-VOID\r
-EFIAPI\r
-NotifyGuidedExtraction (\r
- IN EFI_EVENT Event,\r
- IN VOID *RpnContext\r
+**/\r
+EFI_STATUS\r
+FindChildNode (\r
+ IN FRAMEWORK_SECTION_STREAM_NODE *SourceStream,\r
+ IN EFI_SECTION_TYPE SearchType,\r
+ IN OUT UINTN *SectionInstance,\r
+ IN EFI_GUID *SectionDefinitionGuid,\r
+ OUT FRAMEWORK_SECTION_CHILD_NODE **FoundChild,\r
+ OUT FRAMEWORK_SECTION_STREAM_NODE **FoundStream,\r
+ OUT UINT32 *AuthenticationStatus\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_GUID_DEFINED_SECTION *GuidedHeader;\r
- EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;\r
- VOID *NewStreamBuffer;\r
- UINTN NewStreamBufferSize;\r
- UINT32 AuthenticationStatus;\r
- RPN_EVENT_CONTEXT *Context;\r
- \r
- Context = RpnContext;\r
+ FRAMEWORK_SECTION_CHILD_NODE *CurrentChildNode;\r
+ FRAMEWORK_SECTION_CHILD_NODE *RecursedChildNode;\r
+ FRAMEWORK_SECTION_STREAM_NODE *RecursedFoundStream;\r
+ UINT32 NextChildOffset;\r
+ EFI_STATUS ErrorStatus;\r
+ EFI_STATUS Status;\r
\r
- Status = CloseSectionStream (&mSectionExtraction, Context->ChildNode->EncapsulatedStreamHandle);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // The stream closed successfully, so re-open the stream with correct AuthenticationStatus\r
- //\r
+ CurrentChildNode = NULL;\r
+ ErrorStatus = EFI_NOT_FOUND;\r
\r
- GuidedHeader = (EFI_GUID_DEFINED_SECTION *) \r
- (Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream);\r
- ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED);\r
- \r
- Status = gBS->LocateProtocol (Context->ChildNode->EncapsulationGuid, NULL, (VOID **)&GuidedExtraction);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- \r
- Status = GuidedExtraction->ExtractSection (\r
- GuidedExtraction,\r
- GuidedHeader,\r
- &NewStreamBuffer,\r
- &NewStreamBufferSize,\r
- &AuthenticationStatus\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- //\r
- // OR in the parent stream's aggregagate status.\r
- //\r
- AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL;\r
- Status = OpenSectionStreamEx (\r
- NewStreamBufferSize,\r
- NewStreamBuffer,\r
- FALSE,\r
- AuthenticationStatus,\r
- &Context->ChildNode->EncapsulatedStreamHandle\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ if (SourceStream->StreamLength == 0) {\r
+ return EFI_NOT_FOUND;\r
}\r
-\r
- //\r
- // If above, the stream did not close successfully, it indicates it's\r
- // alread been closed by someone, so just destroy the event and be done with\r
- // it.\r
- //\r
- \r
- gBS->CloseEvent (Event);\r
- gBS->FreePool (Context);\r
-} \r
\r
-/**\r
- Worker function. Destructor for child nodes.\r
-\r
- @param ChildNode - Indicates the node to destroy\r
-\r
-**/\r
-STATIC\r
-VOID\r
-FreeChildNode (\r
- IN CORE_SECTION_CHILD_NODE *ChildNode\r
- )\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
+ 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 (&mSectionExtraction, ChildNode->EncapsulatedStreamHandle);\r
+ Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
- //\r
- // Last, free the child node itself\r
- //\r
- gBS->FreePool (ChildNode);\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 copied\r
- or the input buffer is to be used in place.\r
- @param AuthenticationStatus- Indicates the default authentication status for the\r
- new stream.\r
- @param SectionStreamHandle - A pointer to a caller allocated section stream handle.\r
-\r
- \r
- @retval EFI_SUCCESS - Stream was added to stream database.\r
- @retval EFI_OUT_OF_RESOURCES - memory allocation failed.\r
-\r
-**/\r
-STATIC\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
- CORE_SECTION_STREAM_NODE *NewStream;\r
- EFI_TPL OldTpl;\r
\r
//\r
- // Allocate a new stream\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
- 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
- gBS->FreePool (NewStream);\r
- return EFI_OUT_OF_RESOURCES;\r
+ CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children));\r
+\r
+ for (;;) {\r
+ ASSERT (CurrentChildNode != NULL);\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
- // Copy in stream data\r
+ // If the current node is an encapsulating node, recurse into it...\r
//\r
- CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength);\r
+ Status = FindChildNode (\r
+ (FRAMEWORK_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
+ } else if ((CurrentChildNode->Type == EFI_SECTION_GUID_DEFINED) && (SearchType != EFI_SECTION_GUID_DEFINED)) {\r
+ //\r
+ // When Node Type is GUIDED section, but Node has no encapsulated data, Node data should not be parsed\r
+ // because a required GUIDED section extraction protocol does not exist.\r
+ // If SearchType is not GUIDED section, EFI_PROTOCOL_ERROR should return.\r
+ //\r
+ ErrorStatus = EFI_PROTOCOL_ERROR;\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
- // 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
+ NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size;\r
+ //\r
+ // Round up to 4 byte boundary\r
//\r
- NewStream->StreamBuffer = NULL;\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 = gBS->RaiseTPL (TPL_NOTIFY);\r
- InsertTailList (&mStreamRoot, &NewStream->Link);\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- *SectionStreamHandle = NewStream->StreamHandle;\r
- \r
- return EFI_SUCCESS;\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
+ @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 database.\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 database.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
FindStreamNode (\r
IN UINTN SearchHandle,\r
- OUT CORE_SECTION_STREAM_NODE **FoundStream\r
+ OUT FRAMEWORK_SECTION_STREAM_NODE **FoundStream\r
)\r
-\r
{ \r
- CORE_SECTION_STREAM_NODE *StreamNode;\r
+ FRAMEWORK_SECTION_STREAM_NODE *StreamNode;\r
\r
if (!IsListEmpty (&mStreamRoot)) {\r
StreamNode = STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot));\r
\r
return EFI_NOT_FOUND;\r
}\r
-\r
+ \r
/**\r
+ SEP member function. Retrieves requested section from section stream.\r
\r
- Check if a stream is valid.\r
+ @param This Pointer to SEP instance.\r
+ @param SectionStreamHandle The section stream from which to extract the requested\r
+ 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, then\r
+ SectionDefinitionGuid indicates which of these types\r
+ of sections to search for.\r
+ @param SectionInstance Indicates which instance of the requested section to\r
+ return.\r
+ @param Buffer Double indirection to buffer. If *Buffer is non-null on\r
+ input, then the buffer is caller allocated. If\r
+ *Buffer is NULL, then the buffer is callee allocated.\r
+ In either case, the required buffer size is returned\r
+ in *BufferSize.\r
+ @param BufferSize On input, indicates the size of *Buffer if *Buffer is\r
+ non-null on input. On output, indicates the required\r
+ size (allocated size if callee allocated) of *Buffer.\r
+ @param AuthenticationStatus Indicates the authentication status of the retrieved\r
+ section.\r
\r
- @param SectionStream - The section stream to be checked\r
- @param SectionStreamLength - The length of section stream\r
+ \r
+ @retval EFI_SUCCESS Section was retrieved successfully\r
+ @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the section \r
+ stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED\r
+ bit set, but there was no corresponding GUIDed Section \r
+ Extraction Protocol in the handle database. *Buffer is \r
+ unmodified.\r
+ @retval EFI_NOT_FOUND An error was encountered when parsing the SectionStream.\r
+ This indicates the SectionStream is not correctly \r
+ 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 the \r
+ 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. The \r
+ input buffer is filled and contents are section contents\r
+ are truncated.\r
\r
- @return if a stream is valid.\r
**/\r
-STATIC\r
-BOOLEAN\r
-IsValidSectionStream (\r
- IN VOID *SectionStream,\r
- IN UINTN SectionStreamLength\r
+EFI_STATUS\r
+EFIAPI\r
+GetSection (\r
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\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
{\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
+ FRAMEWORK_SECTION_STREAM_NODE *StreamNode;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ FRAMEWORK_SECTION_CHILD_NODE *ChildNode;\r
+ FRAMEWORK_SECTION_STREAM_NODE *ChildStreamNode;\r
+ UINTN CopySize;\r
+ UINT32 ExtractedAuthenticationStatus;\r
+ UINTN Instance;\r
+ UINT8 *CopyBuffer;\r
+ UINTN SectionSize;\r
+ EFI_COMMON_SECTION_HEADER *Section;\r
\r
- while (TotalLength < SectionStreamLength) {\r
- SectionLength = SECTION_SIZE (SectionHeader);\r
- TotalLength += SectionLength;\r
\r
- if (TotalLength == SectionStreamLength) {\r
- return TRUE; \r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ Instance = SectionInstance + 1;\r
+ ChildStreamNode = NULL;\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
+ \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
+ ASSERT (ChildNode != NULL);\r
+ ASSERT (ChildStreamNode != NULL);\r
+ Section = (EFI_COMMON_SECTION_HEADER *) (ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream);\r
\r
+ if (IS_SECTION2 (Section)) {\r
+ CopySize = SECTION2_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER2);\r
+ CopyBuffer = (UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2);\r
+ } else {\r
+ CopySize = SECTION_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER);\r
+ CopyBuffer = (UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER);\r
+ }\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
- \r
+ if (*BufferSize < CopySize) {\r
+ Status = EFI_WARN_BUFFER_TOO_SMALL;\r
+ CopySize = *BufferSize;\r
+ }\r
+ } else {\r
//\r
- // Figure out where the next section begins\r
+ // Callee allocated buffer. Allocate buffer and return size.\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
+ *Buffer = AllocatePool (CopySize);\r
+ if (*Buffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto GetSection_Done;\r
+ }\r
}\r
-\r
- ASSERT (FALSE);\r
- return FALSE;\r
+ CopyMem (*Buffer, CopyBuffer, CopySize);\r
+ *BufferSize = SectionSize;\r
+ \r
+GetSection_Done:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
}\r
\r
/**\r
- Create a protocol notification event and return it.\r
-\r
- @param ProtocolGuid - Protocol to register notification event on.\r
-\r
- @param NotifyTpl - Maximum TPL to signal the NotifyFunction.\r
-\r
- @param NotifyFuncition - EFI notification routine.\r
-\r
- @param NotifyContext - Context passed into Event when it is created.\r
-\r
- @param Registration - Registration key returned from RegisterProtocolNotify().\r
-\r
- @param SignalFlag - Boolean value to decide whether kick the event after register or not.\r
+ Worker function. Destructor for child nodes.\r
\r
- @Return The EFI_EVENT that has been registered to be signaled when a ProtocolGuid\r
- is added to the system.\r
+ @param ChildNode Indicates the node to destroy\r
\r
**/\r
-EFI_EVENT\r
-CoreCreateProtocolNotifyEvent (\r
- IN EFI_GUID *ProtocolGuid,\r
- IN EFI_TPL NotifyTpl,\r
- IN EFI_EVENT_NOTIFY NotifyFunction,\r
- IN VOID *NotifyContext,\r
- OUT VOID **Registration,\r
- IN BOOLEAN SignalFlag\r
+VOID\r
+FreeChildNode (\r
+ IN FRAMEWORK_SECTION_CHILD_NODE *ChildNode\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_EVENT Event;\r
-\r
+ ASSERT (ChildNode->Signature == FRAMEWORK_SECTION_CHILD_SIGNATURE);\r
//\r
- // Create the event\r
+ // Remove the child from it's list\r
//\r
+ RemoveEntryList (&ChildNode->Link);\r
+ \r
+ if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {\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
+ //\r
+ CloseSectionStream (&mSectionExtraction, ChildNode->EncapsulatedStreamHandle);\r
+ }\r
\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- NotifyTpl,\r
- NotifyFunction,\r
- NotifyContext,\r
- &Event\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ if (ChildNode->Event != NULL) {\r
+ gBS->CloseEvent (ChildNode->Event);\r
+ }\r
\r
//\r
- // Register for protocol notifactions on this event\r
+ // Last, free the child node itself\r
//\r
+ FreePool (ChildNode);\r
+} \r
\r
- Status = gBS->RegisterProtocolNotify (\r
- ProtocolGuid,\r
- Event,\r
- Registration\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+/**\r
+ SEP member function. Deletes an existing section stream\r
\r
- if (SignalFlag) {\r
+ @param This Indicates the calling context.\r
+ @param StreamHandleToClose Indicates the stream to close\r
+\r
+ @retval EFI_SUCCESS Section stream was closed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of\r
+ last section.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CloseSectionStream (\r
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,\r
+ IN UINTN StreamHandleToClose\r
+ )\r
+{\r
+ FRAMEWORK_SECTION_STREAM_NODE *StreamNode;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FRAMEWORK_SECTION_CHILD_NODE *ChildNode;\r
+ \r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ \r
+ //\r
+ // Locate target stream\r
+ //\r
+ Status = FindStreamNode (StreamHandleToClose, &StreamNode);\r
+ if (!EFI_ERROR (Status)) {\r
//\r
- // Kick the event so we will perform an initial pass of\r
- // current installed drivers\r
+ // Found the stream, so close it\r
//\r
- gBS->SignalEvent (Event);\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
+ FreePool (StreamNode->StreamBuffer);\r
+ FreePool (StreamNode);\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_INVALID_PARAMETER;\r
}\r
-\r
- return Event;\r
+ \r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
}\r
-\r
-\r