+/**\r
+\r
+ Check if a stream is valid.\r
+\r
+ @param SectionStream The section stream to be checked\r
+ @param SectionStreamLength The length of section stream\r
+\r
+ @return A boolean value indicating the validness of the section stream.\r
+\r
+**/\r
+BOOLEAN\r
+IsValidSectionStream (\r
+ IN VOID *SectionStream,\r
+ IN UINTN SectionStreamLength\r
+ )\r
+{\r
+ UINTN TotalLength;\r
+ UINTN SectionLength;\r
+ EFI_COMMON_SECTION_HEADER *SectionHeader;\r
+ EFI_COMMON_SECTION_HEADER *NextSectionHeader;\r
+\r
+ TotalLength = 0;\r
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream;\r
+ \r
+ while (TotalLength < SectionStreamLength) {\r
+ if (IS_SECTION2 (SectionHeader)) {\r
+ SectionLength = SECTION2_SIZE (SectionHeader);\r
+ } else {\r
+ SectionLength = SECTION_SIZE (SectionHeader);\r
+ }\r
+ TotalLength += SectionLength;\r
+\r
+ if (TotalLength == SectionStreamLength) {\r
+ return TRUE; \r
+ }\r
+\r
+ //\r
+ // Move to the next byte following the section...\r
+ //\r
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);\r
+ \r
+ //\r
+ // Figure out where the next section begins\r
+ //\r
+ NextSectionHeader = ALIGN_POINTER(SectionHeader, 4);\r
+ TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;\r
+ SectionHeader = NextSectionHeader;\r
+ }\r
+\r
+ ASSERT (FALSE);\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Worker function. Constructor for section streams.\r
+\r
+ @param SectionStreamLength Size in bytes of the section stream.\r
+ @param SectionStream Buffer containing the new section stream.\r
+ @param AllocateBuffer Indicates whether the stream buffer is to be copied\r
+ or the input buffer is to be used in place.\r
+ @param AuthenticationStatus Indicates the default authentication status for the\r
+ new stream.\r
+ @param SectionStreamHandle A pointer to a caller allocated section stream handle.\r
+\r
+ @retval EFI_SUCCESS Stream was added to stream database.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+OpenSectionStreamEx (\r
+ IN UINTN SectionStreamLength,\r
+ IN VOID *SectionStream,\r
+ IN BOOLEAN AllocateBuffer,\r
+ IN UINT32 AuthenticationStatus, \r
+ OUT UINTN *SectionStreamHandle\r
+ )\r
+{\r
+ FRAMEWORK_SECTION_STREAM_NODE *NewStream;\r
+ EFI_TPL OldTpl;\r
+ \r
+ //\r
+ // Allocate a new stream\r
+ //\r
+ NewStream = AllocatePool (sizeof (FRAMEWORK_SECTION_STREAM_NODE));\r
+ if (NewStream == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ if (AllocateBuffer) { \r
+ //\r
+ // if we're here, we're double buffering, allocate the buffer and copy the\r
+ // data in\r
+ //\r
+ if (SectionStreamLength > 0) {\r
+ NewStream->StreamBuffer = AllocatePool (SectionStreamLength); \r
+ if (NewStream->StreamBuffer == NULL) {\r
+ FreePool (NewStream);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Copy in stream data\r
+ //\r
+ CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength);\r
+ } else {\r
+ //\r
+ // It's possible to have a zero length section stream.\r
+ //\r
+ NewStream->StreamBuffer = NULL;\r
+ }\r
+ } else {\r
+ //\r
+ // If were here, the caller has supplied the buffer (it's an internal call)\r
+ // so just assign the buffer. This happens when we open section streams\r
+ // as a result of expanding an encapsulating section.\r
+ //\r
+ NewStream->StreamBuffer = SectionStream;\r
+ }\r
+ \r
+ //\r
+ // Initialize the rest of the section stream\r
+ //\r
+ NewStream->Signature = FRAMEWORK_SECTION_STREAM_SIGNATURE;\r
+ NewStream->StreamHandle = (UINTN) NewStream;\r
+ NewStream->StreamLength = SectionStreamLength;\r
+ InitializeListHead (&NewStream->Children);\r
+ NewStream->AuthenticationStatus = AuthenticationStatus;\r
+ \r
+ //\r
+ // Add new stream to stream list\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ InsertTailList (&mStreamRoot, &NewStream->Link);\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ *SectionStreamHandle = NewStream->StreamHandle;\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r