]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c
Fix a bug that FV->ReadSection cannot get the EFI_SECTION_GUID_DEFINED type section...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / SectionExtractionDxe / SectionExtraction.c
index d25e186fc00af5c537bada0729cb01a0fa74b56f..5d3bb50da7163a50f477ccae4527d8180cf6f573 100644 (file)
@@ -1,20 +1,4 @@
-/**@file\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
-\r
-Module Name:\r
-\r
-  SectionExtraction.c\r
-  \r
-Abstract:\r
-\r
+/** @file\r
   Section Extraction Protocol implementation.\r
   \r
   Stream database is implemented as a linked list of section streams,\r
@@ -42,17 +26,35 @@ Abstract:
      \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
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. <BR>\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
+\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 <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
@@ -73,11 +75,11 @@ typedef struct {
   //\r
   UINTN                       EncapsulatedStreamHandle;\r
   EFI_GUID                    *EncapsulationGuid;\r
-} CORE_SECTION_CHILD_NODE;\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
@@ -90,137 +92,119 @@ typedef struct {
   // 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
+  EFI_EVENT                        Event;\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 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
+\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
@@ -235,27 +219,23 @@ EFI_SECTION_EXTRACTION_PROTOCOL mSectionExtraction = {
   CloseSectionStream\r
 };\r
 \r
+/**\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             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
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 SectionExtractionEntryPoint (\r
   IN EFI_HANDLE                   ImageHandle,\r
   IN EFI_SYSTEM_TABLE             *SystemTable\r
   )\r
-/*++\r
-\r
-Routine Description: \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
-Arguments:  \r
-  ImageHandle   EFI_HANDLE: A handle for the image that is initializing this driver\r
-  SystemTable   EFI_SYSTEM_TABLE: A pointer to the EFI system table        \r
-\r
-Returns:  \r
-  EFI_SUCCESS:  Driver initialized successfully\r
-  EFI_OUT_OF_RESOURCES:   Could not allocate needed resources\r
-\r
---*/\r
 {\r
   EFI_STATUS                         Status;\r
 \r
@@ -273,35 +253,165 @@ Returns:
   return Status;\r
 }\r
 \r
-STATIC\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
+    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
+  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
-EFIAPI\r
-OpenSectionStream (\r
-  IN     EFI_SECTION_EXTRACTION_PROTOCOL           *This,\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
+  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
-Routine Description:\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
 \r
-Arguments:\r
-  This                - Indicates the calling context.\r
-  SectionStreamLength - Size in bytes of the section stream.\r
-  SectionStream       - Buffer containing the new section stream.\r
-  SectionStreamHandle - A pointer to a caller allocated UINTN that on output\r
-                        contains the new section stream handle.\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
-Returns:\r
-  EFI_SUCCESS\r
-  EFI_OUT_OF_RESOURCES - memory allocation failed.\r
-  EFI_INVALID_PARAMETER - section stream does not end concident with end of\r
-                          last section.\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
+**/\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
   //\r
   // Check to see section stream looks good...\r
@@ -318,433 +428,236 @@ Returns:
           SectionStreamHandle\r
           );\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
-/*++\r
 \r
-Routine Description:\r
-  SEP member function.  Retrieves requested section from section stream.\r
+/**\r
+  Worker function.  Determine if the input stream:child matches the input type.\r
 \r
-Arguments:  \r
-  This:                 Pointer to SEP instance.\r
-  SectionStreamHandle:  The section stream from which to extract the requested\r
-                          section.\r
-  SectionType:         A pointer to the type of section to search for.\r
-  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
-  SectionInstance:      Indicates which instance of the requested section to\r
-                          return.\r
-  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
-  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
-  AuthenticationStatus: Indicates the authentication status of the retrieved\r
-                          section.\r
-\r
-Returns:  \r
-  EFI_SUCCESS:        Section was retrieved successfully\r
-  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
-  EFI_NOT_FOUND:      An error was encountered when parsing the SectionStream.\r
-                        This indicates the SectionStream  is not correctly \r
-                        formatted.\r
-  EFI_NOT_FOUND:      The requested section does not exist.\r
-  EFI_OUT_OF_RESOURCES: The system has insufficient resources to process the \r
-                        request.\r
-  EFI_INVALID_PARAMETER: The SectionStreamHandle does not exist.\r
-  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
-{\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
+  @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
-  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-  Instance = SectionInstance + 1;\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
+  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
-  } 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
+  if (Child->Type != SearchType) {\r
+    return FALSE;\r
   }\r
-  CopyMem (*Buffer, CopyBuffer, CopySize);\r
-  *BufferSize = SectionSize;\r
-  \r
-GetSection_Done:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
+  if ((SearchType != EFI_SECTION_GUID_DEFINED) || (SectionDefinitionGuid == NULL)) {\r
+    return TRUE;\r
+  }\r
+  GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);\r
+  return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid);\r
 }\r
 \r
+/**\r
+  Create a protocol notification event and return it.\r
 \r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-CloseSectionStream (\r
-  IN  EFI_SECTION_EXTRACTION_PROTOCOL           *This,\r
-  IN  UINTN                                     StreamHandleToClose\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-  SEP member function.  Deletes an existing section stream\r
-\r
-Arguments:\r
-  This                - Indicates the calling context.\r
-  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
-Returns:\r
-  EFI_SUCCESS\r
-  EFI_OUT_OF_RESOURCES - memory allocation failed.\r
-  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
+**/\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
-  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
-    // 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
-    gBS->FreePool (StreamNode->StreamBuffer);\r
-    gBS->FreePool (StreamNode);\r
-    Status = EFI_SUCCESS;\r
-  } else {\r
-    Status = EFI_INVALID_PARAMETER;\r
-  }\r
-  \r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\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
 \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
+  //\r
+  // Register for protocol notifactions on this event\r
+  //\r
 \r
-Routine Description:\r
-  Worker function.  Determine if the input stream:child matches the input type.\r
+  Status = gBS->RegisterProtocolNotify (\r
+            ProtocolGuid,\r
+            Event,\r
+            Registration\r
+            );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-Arguments:\r
-  Stream              - Indicates the section stream associated with the child\r
-  Child               - Indicates the child to check\r
-  SearchType          - Indicates the type of section to check against for\r
-  SectionDefinitionGuid - Indicates the GUID to check against if the type is\r
-                        EFI_SECTION_GUID_DEFINED\r
-Returns:\r
-  TRUE                - The child matches\r
-  FALSE               - The child doesn't match\r
-\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
+  if (SignalFlag) {\r
+    //\r
+    // Kick the event so we will perform an initial pass of\r
+    // current installed drivers\r
+    //\r
+    gBS->SignalEvent (Event);\r
   }\r
-  GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);\r
-  return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid);\r
-}\r
 \r
+  return Event;\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
-  )\r
-/*++\r
+/**\r
+  RPN callback function.  Removes a stale section stream and re-initializes it\r
+  with an updated AuthenticationStatus.\r
 \r
-Routine Description:\r
-  Worker function  Recursively searches / builds section stream database\r
-  looking for requested section.\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
-Arguments:\r
-  SourceStream        - Indicates the section stream in which to do the search.\r
-  SearchType          - Indicates the type of section to search for.\r
-  SectionInstance     - Indicates which instance of section to find.  This is\r
-                        an in/out parameter to deal with recursions.\r
-  SectionDefinitionGuid  - Guid of section definition\r
-  FoundChild          - Output indicating the child node that is found.\r
-  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
-  AuthenticationStatus- Indicates the authentication status of the found section.\r
-\r
-Returns:\r
-  EFI_SUCCESS         - Child node was found and returned.\r
-  EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
-  EFI_NOT_FOUND       - Requested child node does not exist.\r
-  EFI_PROTOCOL_ERROR  - a required GUIDED section extraction protocol does not\r
-                        exist\r
-\r
---*/\r
+**/\r
+VOID\r
+EFIAPI\r
+NotifyGuidedExtraction (\r
+  IN   EFI_EVENT   Event,\r
+  IN   VOID        *RpnContext\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
+  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
-  CurrentChildNode = NULL;\r
-  ErrorStatus = EFI_NOT_FOUND;\r
+  Context = RpnContext;\r
   \r
-  if (SourceStream->StreamLength == 0) {\r
-    return EFI_NOT_FOUND;\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
   \r
-  if (IsListEmpty (&SourceStream->Children) && \r
-                   SourceStream->StreamLength > sizeof (EFI_COMMON_SECTION_HEADER)) {\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
-    // 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
+    // OR in the parent stream's aggregagate status.\r
     //\r
-    Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);\r
-    if (EFI_ERROR (Status)) {\r
-      return 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
+  //  alread 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
+  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->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
 \r
-STATIC\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
 EFI_STATUS\r
 CreateChildNode (\r
-  IN     CORE_SECTION_STREAM_NODE              *Stream,\r
+  IN     FRAMEWORK_SECTION_STREAM_NODE              *Stream,\r
   IN     UINT32                                ChildOffset,\r
-     OUT CORE_SECTION_CHILD_NODE               **ChildNode\r
+     OUT FRAMEWORK_SECTION_CHILD_NODE               **ChildNode\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-  Worker function.  Constructor for new child nodes.\r
-\r
-Arguments:\r
-  Stream              - Indicates the section stream in which to add the child.\r
-  ChildOffset         - Indicates the offset in Stream that is the beginning\r
-                        of the child section.\r
-  ChildNode           - Indicates the Callee allocated and initialized child.\r
-\r
-Returns:\r
-  EFI_SUCCESS         - Child node was found and returned.\r
-  EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
-  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
 {\r
   EFI_STATUS                                   Status;\r
   EFI_COMMON_SECTION_HEADER                    *SectionHeader;\r
@@ -759,14 +672,14 @@ Returns:
   UINT32                                       AuthenticationStatus;\r
   UINT32                                       SectionLength;\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 = AllocatePool (sizeof (FRAMEWORK_SECTION_CHILD_NODE));\r
   Node = *ChildNode;\r
   if (Node == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -775,7 +688,7 @@ Returns:
   //\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
   Node->OffsetInStream = ChildOffset;\r
@@ -801,7 +714,7 @@ Returns:
         NewStreamBufferSize = CompressionHeader->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
@@ -834,8 +747,8 @@ Returns:
 \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
@@ -849,7 +762,7 @@ Returns:
                                  ScratchSize\r
                                  );\r
           ASSERT_EFI_ERROR (Status);\r
-          gBS->FreePool (ScratchBuffer);                                           \r
+          FreePool (ScratchBuffer);                                           \r
         }\r
       } else {\r
         NewStreamBuffer = NULL;\r
@@ -864,8 +777,8 @@ Returns:
                  &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
@@ -887,7 +800,7 @@ Returns:
                                      &AuthenticationStatus\r
                                      );\r
         if (EFI_ERROR (Status)) {\r
-          gBS->FreePool (*ChildNode);\r
+          FreePool (*ChildNode);\r
           return EFI_PROTOCOL_ERROR;\r
         }\r
         \r
@@ -895,7 +808,7 @@ Returns:
         // 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 ((GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {\r
           //\r
           // OR in the parent stream's aggregate status.\r
           //\r
@@ -916,19 +829,19 @@ Returns:
                    &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 ((GuidedHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {\r
           //\r
           // If the section REQUIRES an extraction protocol, then we're toast\r
           //\r
-          gBS->FreePool (*ChildNode);\r
+          FreePool (*ChildNode);\r
           return EFI_PROTOCOL_ERROR;\r
         }\r
         \r
@@ -936,7 +849,7 @@ Returns:
         // Figure out the proper authentication status\r
         //\r
         AuthenticationStatus = Stream->AuthenticationStatus;\r
-        if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {\r
+        if ((GuidedHeader->Attributes & 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
@@ -963,7 +876,7 @@ Returns:
                    &Node->EncapsulatedStreamHandle\r
                    );\r
         if (EFI_ERROR (Status)) {\r
-          gBS->FreePool (Node);\r
+          FreePool (Node);\r
           return Status;\r
         }\r
       }\r
@@ -997,283 +910,177 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Worker function  Recursively searches / builds section stream database\r
+  looking for requested section.\r
 \r
-STATIC\r
-VOID\r
-CreateGuidedExtractionRpnEvent (\r
-  IN CORE_SECTION_STREAM_NODE       *ParentStream,\r
-  IN CORE_SECTION_CHILD_NODE        *ChildNode\r
-  )\r
-/*++\r
-\r
-Routine Description:\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
-Arguments:\r
-  ParentStream        - Indicates the parent of the ecnapsulation section (child)\r
-  ChildNode           - Indicates the child node that is the encapsulation section.\r
 \r
-Returns:\r
-  None\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
-{\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
-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
-\r
-Routine Description:\r
-  RPN callback function.  Removes a stale section stream and re-initializes it\r
-  with an updated AuthenticationStatus.\r
-\r
-Arguments:\r
-  Event               - The event that fired\r
-  RpnContext          - A pointer to the context that allows us to identify\r
-                        the relevent encapsulation...\r
-\r
-Returns:\r
-  None\r
-\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
-STATIC\r
-VOID\r
-FreeChildNode (\r
-  IN  CORE_SECTION_CHILD_NODE                   *ChildNode\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-  Worker function.  Destructor for child nodes.\r
-\r
-Arguments:\r
-  ChildNode           - Indicates the node to destroy\r
-\r
-Returns:\r
-  none\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
-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
-  Routine Description:\r
-    Worker function.  Constructor for section streams.\r
-\r
-  Arguments:\r
-    SectionStreamLength - Size in bytes of the section stream.\r
-    SectionStream       - Buffer containing the new section stream.\r
-    AllocateBuffer      - Indicates whether the stream buffer is to be copied\r
-                          or the input buffer is to be used in place.\r
-    AuthenticationStatus- Indicates the default authentication status for the\r
-                          new stream.\r
-    SectionStreamHandle - A pointer to a caller allocated section stream handle.\r
-\r
-  Returns:\r
-    EFI_SUCCESS         - Stream was added to stream database.\r
-    EFI_OUT_OF_RESOURCES - memory allocation failed.\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
+    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
+    ASSERT (CurrentChildNode != NULL);\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
+    }\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
-      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 = 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
 \r
-STATIC\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
 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
-  Routine Description:\r
-    Worker function.  Search stream database for requested stream handle.\r
-\r
-  Arguments:\r
-    SearchHandle        - Indicates which stream to look for.\r
-    FoundStream         - Output pointer to the found stream.\r
-\r
-  Returns:\r
-    EFI_SUCCESS         - StreamHandle was found and *FoundStream contains\r
-                          the stream node.\r
-    EFI_NOT_FOUND       - SearchHandle was not found in the stream database.\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
@@ -1291,135 +1098,225 @@ FindStreamNode (
   \r
   return EFI_NOT_FOUND;\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 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
 \r
-STATIC\r
-BOOLEAN\r
-IsValidSectionStream (\r
-  IN  VOID              *SectionStream,\r
-  IN  UINTN             SectionStreamLength\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-  Check if a stream is valid.\r
-\r
-Arguments:\r
-  SectionStream         - The section stream to be checked\r
-  SectionStreamLength   - The length of section stream\r
-\r
-Returns:\r
-  TRUE\r
-  FALSE\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
+**/\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
-  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
   \r
-  while (TotalLength < SectionStreamLength) {\r
-    SectionLength = SECTION_SIZE (SectionHeader);\r
-    TotalLength += SectionLength;\r
-\r
-    if (TotalLength == SectionStreamLength) {\r
-      return TRUE;    \r
-    }\r
 \r
+  OldTpl = gBS->RaiseTPL (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
+  \r
+  //\r
+  // Found the stream, now locate and return the appropriate section\r
+  //\r
+  if (SectionType == NULL) {\r
     //\r
-    // Move to the next byte following the section...\r
+    // SectionType == NULL means return the WHOLE section stream...\r
     //\r
-    SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);\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
+    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
-    // Figure out where the next section begins\r
+    // Caller allocated buffer.  Fill to size and return required 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
+    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
-\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
-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
-Routine Description:\r
-\r
-  Create a protocol notification event and return it.\r
-\r
-Arguments:\r
-\r
-  ProtocolGuid    - Protocol to register notification event on.\r
-\r
-  NotifyTpl        - Maximum TPL to signal the NotifyFunction.\r
-\r
-  NotifyFuncition  - EFI notification routine.\r
-\r
-  NotifyContext   - Context passed into Event when it is created.\r
-\r
-  Registration    - Registration key returned from RegisterProtocolNotify().\r
-\r
-  SignalFlag      -  Boolean value to decide whether kick the event after register or not.\r
-\r
-Returns:\r
+/**\r
+  Worker function.  Destructor for child nodes.\r
 \r
-  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
+**/\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
-\r
-  Status = gBS->CreateEvent (\r
-            EVT_NOTIFY_SIGNAL,\r
-            NotifyTpl,\r
-            NotifyFunction,\r
-            NotifyContext,\r
-           &Event\r
-            );\r
-  ASSERT_EFI_ERROR (Status);\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
-  // 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