Fix several approved code review comments:
authorqhuang8 <qhuang8@de2fecce-e211-0410-80a6-f3fac2684e05>
Thu, 28 Aug 2008 02:53:16 +0000 (02:53 +0000)
committerqhuang8 <qhuang8@de2fecce-e211-0410-80a6-f3fac2684e05>
Thu, 28 Aug 2008 02:53:16 +0000 (02:53 +0000)
1. Remove internal function prototypes to avoid sync efforts. The layout of them have been adjusted
2. Apply macro ALIGN_POINTER to get next section stream
3. Fix a potential memory leak issue.
4. Make the comparison between type UINTN and 0 consistent between one function.

git-svn-id: https://edk2.tianocore.org/svn/edk2/trunk@5747 de2fecce-e211-0410-80a6-f3fac2684e05

edk2/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c

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