2 Section Extraction Protocol implementation.
4 Stream database is implemented as a linked list of section streams,
5 where each stream contains a linked list of children, which may be leaves or
8 Children that are encapsulations generate new stream entries
9 when they are created. Streams can also be created by calls to
10 SEP->OpenSectionStream().
12 The database is only created far enough to return the requested data from
13 any given stream, or to determine that the requested data is not found.
15 If a GUIDed encapsulation is encountered, there are three possiblilites.
17 1) A support protocol is found, in which the stream is simply processed with
20 2) A support protocol is not found, but the data is available to be read
21 without processing. In this case, the database is built up through the
22 recursions to return the data, and a RPN event is set that will enable
23 the stream in question to be refreshed if and when the required section
24 extraction protocol is published.This insures the AuthenticationStatus
25 does not become stale in the cache.
27 3) A support protocol is not found, and the data is not available to be read
28 without it. This results in EFI_PROTOCOL_ERROR.
30 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
31 SPDX-License-Identifier: BSD-2-Clause-Patent
38 // Local defines and typedefs
40 #define CORE_SECTION_CHILD_SIGNATURE SIGNATURE_32('S','X','C','S')
41 #define CHILD_SECTION_NODE_FROM_LINK(Node) \
42 CR (Node, CORE_SECTION_CHILD_NODE, Link, CORE_SECTION_CHILD_SIGNATURE)
50 // StreamBase + OffsetInStream == pointer to section header in stream. The
51 // stream base is always known when walking the sections within.
53 UINT32 OffsetInStream
;
55 // Then EncapsulatedStreamHandle below is always 0 if the section is NOT an
56 // encapsulating section. Otherwise, it contains the stream handle
57 // of the encapsulated stream. This handle is ALWAYS produced any time an
58 // encapsulating child is encountered, irrespective of whether the
59 // encapsulated stream is processed further.
61 UINTN EncapsulatedStreamHandle
;
62 EFI_GUID
*EncapsulationGuid
;
64 // If the section REQUIRES an extraction protocol, register for RPN
65 // when the required GUIDed extraction protocol becomes available.
68 } CORE_SECTION_CHILD_NODE
;
70 #define CORE_SECTION_STREAM_SIGNATURE SIGNATURE_32('S','X','S','S')
71 #define STREAM_NODE_FROM_LINK(Node) \
72 CR (Node, CORE_SECTION_STREAM_NODE, Link, CORE_SECTION_STREAM_SIGNATURE)
82 // Authentication status is from GUIDed encapsulations.
84 UINT32 AuthenticationStatus
;
85 } CORE_SECTION_STREAM_NODE
;
87 #define NULL_STREAM_HANDLE 0
90 CORE_SECTION_CHILD_NODE
*ChildNode
;
91 CORE_SECTION_STREAM_NODE
*ParentStream
;
97 The ExtractSection() function processes the input section and
98 allocates a buffer from the pool in which it returns the section
99 contents. If the section being extracted contains
100 authentication information (the section's
101 GuidedSectionHeader.Attributes field has the
102 EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
103 returned in AuthenticationStatus must reflect the results of
104 the authentication operation. Depending on the algorithm and
105 size of the encapsulated data, the time that is required to do
106 a full authentication may be prohibitively long for some
107 classes of systems. To indicate this, use
108 EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
109 the security policy driver (see the Platform Initialization
110 Driver Execution Environment Core Interface Specification for
111 more details and the GUID definition). If the
112 EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
113 database, then, if possible, full authentication should be
114 skipped and the section contents simply returned in the
115 OutputBuffer. In this case, the
116 EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
117 must be set on return. ExtractSection() is callable only from
118 TPL_NOTIFY and below. Behavior of ExtractSection() at any
119 EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
120 defined in RaiseTPL() in the UEFI 2.0 specification.
123 @param This Indicates the
124 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
125 @param InputSection Buffer containing the input GUIDed section
126 to be processed. OutputBuffer OutputBuffer
127 is allocated from boot services pool
128 memory and contains the new section
129 stream. The caller is responsible for
131 @param OutputBuffer *OutputBuffer is allocated from boot services
132 pool memory and contains the new section stream.
133 The caller is responsible for freeing this buffer.
134 @param OutputSize A pointer to a caller-allocated UINTN in
135 which the size of OutputBuffer allocation
136 is stored. If the function returns
137 anything other than EFI_SUCCESS, the value
138 of OutputSize is undefined.
140 @param AuthenticationStatus A pointer to a caller-allocated
141 UINT32 that indicates the
142 authentication status of the
143 output buffer. If the input
145 GuidedSectionHeader.Attributes
147 EFI_GUIDED_SECTION_AUTH_STATUS_VAL
148 bit as clear, AuthenticationStatus
149 must return zero. Both local bits
150 (19:16) and aggregate bits (3:0)
151 in AuthenticationStatus are
152 returned by ExtractSection().
153 These bits reflect the status of
154 the extraction operation. The bit
155 pattern in both regions must be
156 the same, as the local and
157 aggregate authentication statuses
158 have equivalent meaning at this
159 level. If the function returns
160 anything other than EFI_SUCCESS,
161 the value of AuthenticationStatus
165 @retval EFI_SUCCESS The InputSection was successfully
166 processed and the section contents were
169 @retval EFI_OUT_OF_RESOURCES The system has insufficient
170 resources to process the
173 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
174 not match this instance of the
175 GUIDed Section Extraction
181 CustomGuidedSectionExtract (
182 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*This
,
183 IN CONST VOID
*InputSection
,
184 OUT VOID
**OutputBuffer
,
185 OUT UINTN
*OutputSize
,
186 OUT UINT32
*AuthenticationStatus
192 LIST_ENTRY mStreamRoot
= INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot
);
194 EFI_HANDLE mSectionExtractionHandle
= NULL
;
196 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL mCustomGuidedSectionExtractionProtocol
= {
197 CustomGuidedSectionExtract
202 Entry point of the section extraction code. Initializes an instance of the
203 section extraction interface and installs it on a new handle.
205 @param ImageHandle A handle for the image that is initializing this driver
206 @param SystemTable A pointer to the EFI system table
208 @retval EFI_SUCCESS Driver initialized successfully
209 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
214 InitializeSectionExtraction (
215 IN EFI_HANDLE ImageHandle
,
216 IN EFI_SYSTEM_TABLE
*SystemTable
220 EFI_GUID
*ExtractHandlerGuidTable
;
221 UINTN ExtractHandlerNumber
;
224 // Get custom extract guided section method guid list
226 ExtractHandlerNumber
= ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable
);
228 Status
= EFI_SUCCESS
;
230 // Install custom guided extraction protocol
232 while (ExtractHandlerNumber
-- > 0) {
233 Status
= CoreInstallProtocolInterface (
234 &mSectionExtractionHandle
,
235 &ExtractHandlerGuidTable
[ExtractHandlerNumber
],
236 EFI_NATIVE_INTERFACE
,
237 &mCustomGuidedSectionExtractionProtocol
239 ASSERT_EFI_ERROR (Status
);
247 Check if a stream is valid.
249 @param SectionStream The section stream to be checked
250 @param SectionStreamLength The length of section stream
252 @return A boolean value indicating the validness of the section stream.
256 IsValidSectionStream (
257 IN VOID
*SectionStream
,
258 IN UINTN SectionStreamLength
263 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
264 EFI_COMMON_SECTION_HEADER
*NextSectionHeader
;
267 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*)SectionStream
;
269 while (TotalLength
< SectionStreamLength
) {
270 if (IS_SECTION2 (SectionHeader
)) {
271 SectionLength
= SECTION2_SIZE (SectionHeader
);
273 SectionLength
= SECTION_SIZE (SectionHeader
);
275 TotalLength
+= SectionLength
;
277 if (TotalLength
== SectionStreamLength
) {
282 // Move to the next byte following the section...
284 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ SectionLength
);
287 // Figure out where the next section begins
289 NextSectionHeader
= ALIGN_POINTER(SectionHeader
, 4);
290 TotalLength
+= (UINTN
) NextSectionHeader
- (UINTN
) SectionHeader
;
291 SectionHeader
= NextSectionHeader
;
300 Worker function. Constructor for section streams.
302 @param SectionStreamLength Size in bytes of the section stream.
303 @param SectionStream Buffer containing the new section stream.
304 @param AllocateBuffer Indicates whether the stream buffer is to be
305 copied or the input buffer is to be used in
306 place. AuthenticationStatus- Indicates the
307 default authentication status for the new
309 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
310 indicates the authentication status of the
311 output buffer. If the input section's
312 GuidedSectionHeader.Attributes field
313 has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID
314 bit as clear, AuthenticationStatus must return
315 zero. Both local bits (19:16) and aggregate
316 bits (3:0) in AuthenticationStatus are returned
317 by ExtractSection(). These bits reflect the
318 status of the extraction operation. The bit
319 pattern in both regions must be the same, as
320 the local and aggregate authentication statuses
321 have equivalent meaning at this level. If the
322 function returns anything other than
323 EFI_SUCCESS, the value of *AuthenticationStatus
325 @param SectionStreamHandle A pointer to a caller allocated section stream
328 @retval EFI_SUCCESS Stream was added to stream database.
329 @retval EFI_OUT_OF_RESOURCES memory allocation failed.
333 OpenSectionStreamEx (
334 IN UINTN SectionStreamLength
,
335 IN VOID
*SectionStream
,
336 IN BOOLEAN AllocateBuffer
,
337 IN UINT32 AuthenticationStatus
,
338 OUT UINTN
*SectionStreamHandle
341 CORE_SECTION_STREAM_NODE
*NewStream
;
345 // Allocate a new stream
347 NewStream
= AllocatePool (sizeof (CORE_SECTION_STREAM_NODE
));
348 if (NewStream
== NULL
) {
349 return EFI_OUT_OF_RESOURCES
;
352 if (AllocateBuffer
) {
354 // if we're here, we're double buffering, allocate the buffer and copy the
357 if (SectionStreamLength
> 0) {
358 NewStream
->StreamBuffer
= AllocatePool (SectionStreamLength
);
359 if (NewStream
->StreamBuffer
== NULL
) {
360 CoreFreePool (NewStream
);
361 return EFI_OUT_OF_RESOURCES
;
364 // Copy in stream data
366 CopyMem (NewStream
->StreamBuffer
, SectionStream
, SectionStreamLength
);
369 // It's possible to have a zero length section stream.
371 NewStream
->StreamBuffer
= NULL
;
375 // If were here, the caller has supplied the buffer (it's an internal call)
376 // so just assign the buffer. This happens when we open section streams
377 // as a result of expanding an encapsulating section.
379 NewStream
->StreamBuffer
= SectionStream
;
383 // Initialize the rest of the section stream
385 NewStream
->Signature
= CORE_SECTION_STREAM_SIGNATURE
;
386 NewStream
->StreamHandle
= (UINTN
) NewStream
;
387 NewStream
->StreamLength
= SectionStreamLength
;
388 InitializeListHead (&NewStream
->Children
);
389 NewStream
->AuthenticationStatus
= AuthenticationStatus
;
392 // Add new stream to stream list
394 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
395 InsertTailList (&mStreamRoot
, &NewStream
->Link
);
396 CoreRestoreTpl (OldTpl
);
398 *SectionStreamHandle
= NewStream
->StreamHandle
;
405 SEP member function. This function creates and returns a new section stream
406 handle to represent the new section stream.
408 @param SectionStreamLength Size in bytes of the section stream.
409 @param SectionStream Buffer containing the new section stream.
410 @param SectionStreamHandle A pointer to a caller allocated UINTN that on
411 output contains the new section stream handle.
413 @retval EFI_SUCCESS The section stream is created successfully.
414 @retval EFI_OUT_OF_RESOURCES memory allocation failed.
415 @retval EFI_INVALID_PARAMETER Section stream does not end concident with end
422 IN UINTN SectionStreamLength
,
423 IN VOID
*SectionStream
,
424 OUT UINTN
*SectionStreamHandle
428 // Check to see section stream looks good...
430 if (!IsValidSectionStream (SectionStream
, SectionStreamLength
)) {
431 return EFI_INVALID_PARAMETER
;
434 return OpenSectionStreamEx (
446 Worker function. Determine if the input stream:child matches the input type.
448 @param Stream Indicates the section stream associated with the
450 @param Child Indicates the child to check
451 @param SearchType Indicates the type of section to check against
453 @param SectionDefinitionGuid Indicates the GUID to check against if the type
454 is EFI_SECTION_GUID_DEFINED
456 @retval TRUE The child matches
457 @retval FALSE The child doesn't match
462 IN CORE_SECTION_STREAM_NODE
*Stream
,
463 IN CORE_SECTION_CHILD_NODE
*Child
,
464 IN EFI_SECTION_TYPE SearchType
,
465 IN EFI_GUID
*SectionDefinitionGuid
468 EFI_GUID_DEFINED_SECTION
*GuidedSection
;
470 if (SearchType
== EFI_SECTION_ALL
) {
473 if (Child
->Type
!= SearchType
) {
476 if ((SearchType
!= EFI_SECTION_GUID_DEFINED
) || (SectionDefinitionGuid
== NULL
)) {
479 GuidedSection
= (EFI_GUID_DEFINED_SECTION
* )(Stream
->StreamBuffer
+ Child
->OffsetInStream
);
480 if (IS_SECTION2 (GuidedSection
)) {
481 return CompareGuid (&(((EFI_GUID_DEFINED_SECTION2
*) GuidedSection
)->SectionDefinitionGuid
), SectionDefinitionGuid
);
483 return CompareGuid (&GuidedSection
->SectionDefinitionGuid
, SectionDefinitionGuid
);
488 Verify the Guided Section GUID by checking if there is the Guided Section GUID configuration table recorded the GUID itself.
490 @param GuidedSectionGuid The Guided Section GUID.
491 @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Protocol
492 for the Guided Section.
494 @return TRUE The GuidedSectionGuid could be identified, and the pointer to
495 the Guided Section Extraction Protocol will be returned to *GuidedSectionExtraction.
496 @return FALSE The GuidedSectionGuid could not be identified, or
497 the Guided Section Extraction Protocol has not been installed yet.
501 VerifyGuidedSectionGuid (
502 IN EFI_GUID
*GuidedSectionGuid
,
503 OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
**GuidedSectionExtraction
506 EFI_GUID
*GuidRecorded
;
513 // Check if there is the Guided Section GUID configuration table recorded the GUID itself.
515 Status
= EfiGetSystemConfigurationTable (GuidedSectionGuid
, (VOID
**) &GuidRecorded
);
516 if (Status
== EFI_SUCCESS
) {
517 if (CompareGuid (GuidRecorded
, GuidedSectionGuid
)) {
519 // Found the recorded GuidedSectionGuid.
521 Status
= CoreLocateProtocol (GuidedSectionGuid
, NULL
, (VOID
**) &Interface
);
522 if (!EFI_ERROR (Status
) && Interface
!= NULL
) {
524 // Found the supported Guided Section Extraction Porotocol for the Guided Section.
526 *GuidedSectionExtraction
= (EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*) Interface
;
537 RPN callback function. Initializes the section stream
538 when GUIDED_SECTION_EXTRACTION_PROTOCOL is installed.
540 @param Event The event that fired
541 @param RpnContext A pointer to the context that allows us to identify
542 the relevent encapsulation.
546 NotifyGuidedExtraction (
552 EFI_GUID_DEFINED_SECTION
*GuidedHeader
;
553 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*GuidedExtraction
;
554 VOID
*NewStreamBuffer
;
555 UINTN NewStreamBufferSize
;
556 UINT32 AuthenticationStatus
;
557 RPN_EVENT_CONTEXT
*Context
;
559 Context
= RpnContext
;
561 GuidedHeader
= (EFI_GUID_DEFINED_SECTION
*) (Context
->ParentStream
->StreamBuffer
+ Context
->ChildNode
->OffsetInStream
);
562 ASSERT (GuidedHeader
->CommonHeader
.Type
== EFI_SECTION_GUID_DEFINED
);
564 if (!VerifyGuidedSectionGuid (Context
->ChildNode
->EncapsulationGuid
, &GuidedExtraction
)) {
568 Status
= GuidedExtraction
->ExtractSection (
572 &NewStreamBufferSize
,
573 &AuthenticationStatus
575 ASSERT_EFI_ERROR (Status
);
578 // Make sure we initialize the new stream with the correct
579 // authentication status for both aggregate and local status fields.
581 if ((GuidedHeader
->Attributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
583 // OR in the parent stream's aggregate status.
585 AuthenticationStatus
|= Context
->ParentStream
->AuthenticationStatus
& EFI_AUTH_STATUS_ALL
;
588 // since there's no authentication data contributed by the section,
589 // just inherit the full value from our immediate parent.
591 AuthenticationStatus
= Context
->ParentStream
->AuthenticationStatus
;
594 Status
= OpenSectionStreamEx (
598 AuthenticationStatus
,
599 &Context
->ChildNode
->EncapsulatedStreamHandle
601 ASSERT_EFI_ERROR (Status
);
604 // Close the event when done.
606 gBS
->CloseEvent (Event
);
607 Context
->ChildNode
->Event
= NULL
;
612 Constructor for RPN event when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...
614 @param ParentStream Indicates the parent of the ecnapsulation section (child)
615 @param ChildNode Indicates the child node that is the encapsulation section.
619 CreateGuidedExtractionRpnEvent (
620 IN CORE_SECTION_STREAM_NODE
*ParentStream
,
621 IN CORE_SECTION_CHILD_NODE
*ChildNode
624 RPN_EVENT_CONTEXT
*Context
;
627 // Allocate new event structure and context
629 Context
= AllocatePool (sizeof (RPN_EVENT_CONTEXT
));
630 ASSERT (Context
!= NULL
);
632 Context
->ChildNode
= ChildNode
;
633 Context
->ParentStream
= ParentStream
;
635 Context
->ChildNode
->Event
= EfiCreateProtocolNotifyEvent (
636 Context
->ChildNode
->EncapsulationGuid
,
638 NotifyGuidedExtraction
,
640 &Context
->Registration
645 Worker function. Constructor for new child nodes.
647 @param Stream Indicates the section stream in which to add the
649 @param ChildOffset Indicates the offset in Stream that is the
650 beginning of the child section.
651 @param ChildNode Indicates the Callee allocated and initialized
654 @retval EFI_SUCCESS Child node was found and returned.
655 EFI_OUT_OF_RESOURCES- Memory allocation failed.
656 @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream
657 handles when the child node is created. If the
658 section type is GUID defined, and the extraction
659 GUID does not exist, and producing the stream
660 requires the GUID, then a protocol error is
661 generated and no child is produced. Values
662 returned by OpenSectionStreamEx.
667 IN CORE_SECTION_STREAM_NODE
*Stream
,
668 IN UINT32 ChildOffset
,
669 OUT CORE_SECTION_CHILD_NODE
**ChildNode
673 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
674 EFI_COMPRESSION_SECTION
*CompressionHeader
;
675 EFI_GUID_DEFINED_SECTION
*GuidedHeader
;
676 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
677 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*GuidedExtraction
;
678 VOID
*NewStreamBuffer
;
681 UINTN NewStreamBufferSize
;
682 UINT32 AuthenticationStatus
;
683 VOID
*CompressionSource
;
684 UINT32 CompressionSourceSize
;
685 UINT32 UncompressedLength
;
686 UINT8 CompressionType
;
687 UINT16 GuidedSectionAttributes
;
689 CORE_SECTION_CHILD_NODE
*Node
;
691 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) (Stream
->StreamBuffer
+ ChildOffset
);
694 // Allocate a new node
696 *ChildNode
= AllocateZeroPool (sizeof (CORE_SECTION_CHILD_NODE
));
699 return EFI_OUT_OF_RESOURCES
;
705 Node
->Signature
= CORE_SECTION_CHILD_SIGNATURE
;
706 Node
->Type
= SectionHeader
->Type
;
707 if (IS_SECTION2 (SectionHeader
)) {
708 Node
->Size
= SECTION2_SIZE (SectionHeader
);
710 Node
->Size
= SECTION_SIZE (SectionHeader
);
712 Node
->OffsetInStream
= ChildOffset
;
713 Node
->EncapsulatedStreamHandle
= NULL_STREAM_HANDLE
;
714 Node
->EncapsulationGuid
= NULL
;
717 // If it's an encapsulating section, then create the new section stream also
719 switch (Node
->Type
) {
720 case EFI_SECTION_COMPRESSION
:
722 // Get the CompressionSectionHeader
724 if (Node
->Size
< sizeof (EFI_COMPRESSION_SECTION
)) {
726 return EFI_NOT_FOUND
;
729 CompressionHeader
= (EFI_COMPRESSION_SECTION
*) SectionHeader
;
731 if (IS_SECTION2 (CompressionHeader
)) {
732 CompressionSource
= (VOID
*) ((UINT8
*) CompressionHeader
+ sizeof (EFI_COMPRESSION_SECTION2
));
733 CompressionSourceSize
= (UINT32
) (SECTION2_SIZE (CompressionHeader
) - sizeof (EFI_COMPRESSION_SECTION2
));
734 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*) CompressionHeader
)->UncompressedLength
;
735 CompressionType
= ((EFI_COMPRESSION_SECTION2
*) CompressionHeader
)->CompressionType
;
737 CompressionSource
= (VOID
*) ((UINT8
*) CompressionHeader
+ sizeof (EFI_COMPRESSION_SECTION
));
738 CompressionSourceSize
= (UINT32
) (SECTION_SIZE (CompressionHeader
) - sizeof (EFI_COMPRESSION_SECTION
));
739 UncompressedLength
= CompressionHeader
->UncompressedLength
;
740 CompressionType
= CompressionHeader
->CompressionType
;
744 // Allocate space for the new stream
746 if (UncompressedLength
> 0) {
747 NewStreamBufferSize
= UncompressedLength
;
748 NewStreamBuffer
= AllocatePool (NewStreamBufferSize
);
749 if (NewStreamBuffer
== NULL
) {
751 return EFI_OUT_OF_RESOURCES
;
754 if (CompressionType
== EFI_NOT_COMPRESSED
) {
756 // stream is not actually compressed, just encapsulated. So just copy it.
758 CopyMem (NewStreamBuffer
, CompressionSource
, NewStreamBufferSize
);
759 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
761 // Only support the EFI_SATNDARD_COMPRESSION algorithm.
765 // Decompress the stream
767 Status
= CoreLocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**)&Decompress
);
768 ASSERT_EFI_ERROR (Status
);
769 ASSERT (Decompress
!= NULL
);
771 Status
= Decompress
->GetInfo (
774 CompressionSourceSize
,
775 (UINT32
*)&NewStreamBufferSize
,
778 if (EFI_ERROR (Status
) || (NewStreamBufferSize
!= UncompressedLength
)) {
780 CoreFreePool (NewStreamBuffer
);
781 if (!EFI_ERROR (Status
)) {
782 Status
= EFI_BAD_BUFFER_SIZE
;
787 ScratchBuffer
= AllocatePool (ScratchSize
);
788 if (ScratchBuffer
== NULL
) {
790 CoreFreePool (NewStreamBuffer
);
791 return EFI_OUT_OF_RESOURCES
;
794 Status
= Decompress
->Decompress (
797 CompressionSourceSize
,
799 (UINT32
)NewStreamBufferSize
,
803 CoreFreePool (ScratchBuffer
);
804 if (EFI_ERROR (Status
)) {
806 CoreFreePool (NewStreamBuffer
);
811 NewStreamBuffer
= NULL
;
812 NewStreamBufferSize
= 0;
815 Status
= OpenSectionStreamEx (
819 Stream
->AuthenticationStatus
,
820 &Node
->EncapsulatedStreamHandle
822 if (EFI_ERROR (Status
)) {
824 CoreFreePool (NewStreamBuffer
);
829 case EFI_SECTION_GUID_DEFINED
:
830 GuidedHeader
= (EFI_GUID_DEFINED_SECTION
*) SectionHeader
;
831 if (IS_SECTION2 (GuidedHeader
)) {
832 Node
->EncapsulationGuid
= &(((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->SectionDefinitionGuid
);
833 GuidedSectionAttributes
= ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->Attributes
;
835 Node
->EncapsulationGuid
= &GuidedHeader
->SectionDefinitionGuid
;
836 GuidedSectionAttributes
= GuidedHeader
->Attributes
;
838 if (VerifyGuidedSectionGuid (Node
->EncapsulationGuid
, &GuidedExtraction
)) {
840 // NewStreamBuffer is always allocated by ExtractSection... No caller
843 Status
= GuidedExtraction
->ExtractSection (
847 &NewStreamBufferSize
,
848 &AuthenticationStatus
850 if (EFI_ERROR (Status
)) {
851 CoreFreePool (*ChildNode
);
852 return EFI_PROTOCOL_ERROR
;
856 // Make sure we initialize the new stream with the correct
857 // authentication status for both aggregate and local status fields.
859 if ((GuidedSectionAttributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
861 // OR in the parent stream's aggregate status.
863 AuthenticationStatus
|= Stream
->AuthenticationStatus
& EFI_AUTH_STATUS_ALL
;
866 // since there's no authentication data contributed by the section,
867 // just inherit the full value from our immediate parent.
869 AuthenticationStatus
= Stream
->AuthenticationStatus
;
872 Status
= OpenSectionStreamEx (
876 AuthenticationStatus
,
877 &Node
->EncapsulatedStreamHandle
879 if (EFI_ERROR (Status
)) {
880 CoreFreePool (*ChildNode
);
881 CoreFreePool (NewStreamBuffer
);
886 // There's no GUIDed section extraction protocol available.
888 if ((GuidedSectionAttributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
890 // If the section REQUIRES an extraction protocol, register for RPN
891 // when the required GUIDed extraction protocol becomes available.
893 CreateGuidedExtractionRpnEvent (Stream
, Node
);
896 // Figure out the proper authentication status
898 AuthenticationStatus
= Stream
->AuthenticationStatus
;
900 if ((GuidedSectionAttributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) {
901 AuthenticationStatus
|= EFI_AUTH_STATUS_IMAGE_SIGNED
| EFI_AUTH_STATUS_NOT_TESTED
;
904 if (IS_SECTION2 (GuidedHeader
)) {
905 Status
= OpenSectionStreamEx (
906 SECTION2_SIZE (GuidedHeader
) - ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->DataOffset
,
907 (UINT8
*) GuidedHeader
+ ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->DataOffset
,
909 AuthenticationStatus
,
910 &Node
->EncapsulatedStreamHandle
913 Status
= OpenSectionStreamEx (
914 SECTION_SIZE (GuidedHeader
) - ((EFI_GUID_DEFINED_SECTION
*) GuidedHeader
)->DataOffset
,
915 (UINT8
*) GuidedHeader
+ ((EFI_GUID_DEFINED_SECTION
*) GuidedHeader
)->DataOffset
,
917 AuthenticationStatus
,
918 &Node
->EncapsulatedStreamHandle
921 if (EFI_ERROR (Status
)) {
933 // Nothing to do if it's a leaf
939 // Last, add the new child node to the stream
941 InsertTailList (&Stream
->Children
, &Node
->Link
);
948 Worker function Recursively searches / builds section stream database
949 looking for requested section.
951 @param SourceStream Indicates the section stream in which to do the
953 @param SearchType Indicates the type of section to search for.
954 @param SectionInstance Indicates which instance of section to find.
955 This is an in/out parameter and it is 1-based,
956 to deal with recursions.
957 @param SectionDefinitionGuid Guid of section definition
958 @param FoundChild Output indicating the child node that is found.
959 @param FoundStream Output indicating which section stream the child
960 was found in. If this stream was generated as a
961 result of an encapsulation section, the
962 streamhandle is visible within the SEP driver
964 @param AuthenticationStatus Indicates the authentication status of the found section.
966 @retval EFI_SUCCESS Child node was found and returned.
967 EFI_OUT_OF_RESOURCES- Memory allocation failed.
968 @retval EFI_NOT_FOUND Requested child node does not exist.
969 @retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol
975 IN CORE_SECTION_STREAM_NODE
*SourceStream
,
976 IN EFI_SECTION_TYPE SearchType
,
977 IN OUT UINTN
*SectionInstance
,
978 IN EFI_GUID
*SectionDefinitionGuid
,
979 OUT CORE_SECTION_CHILD_NODE
**FoundChild
,
980 OUT CORE_SECTION_STREAM_NODE
**FoundStream
,
981 OUT UINT32
*AuthenticationStatus
984 CORE_SECTION_CHILD_NODE
*CurrentChildNode
;
985 CORE_SECTION_CHILD_NODE
*RecursedChildNode
;
986 CORE_SECTION_STREAM_NODE
*RecursedFoundStream
;
987 UINT32 NextChildOffset
;
988 EFI_STATUS ErrorStatus
;
991 ASSERT (*SectionInstance
> 0);
993 CurrentChildNode
= NULL
;
994 ErrorStatus
= EFI_NOT_FOUND
;
996 if (SourceStream
->StreamLength
== 0) {
997 return EFI_NOT_FOUND
;
1000 if (IsListEmpty (&SourceStream
->Children
) &&
1001 SourceStream
->StreamLength
>= sizeof (EFI_COMMON_SECTION_HEADER
)) {
1003 // This occurs when a section stream exists, but no child sections
1004 // have been parsed out yet. Therefore, extract the first child and add it
1005 // to the list of children so we can get started.
1006 // Section stream may contain an array of zero or more bytes.
1007 // So, its size should be >= the size of commen section header.
1009 Status
= CreateChildNode (SourceStream
, 0, &CurrentChildNode
);
1010 if (EFI_ERROR (Status
)) {
1016 // At least one child has been parsed out of the section stream. So, walk
1017 // through the sections that have already been parsed out looking for the
1018 // requested section, if necessary, continue parsing section stream and
1019 // adding children until either the requested section is found, or we run
1022 CurrentChildNode
= CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream
->Children
));
1025 ASSERT (CurrentChildNode
!= NULL
);
1026 if (ChildIsType (SourceStream
, CurrentChildNode
, SearchType
, SectionDefinitionGuid
)) {
1028 // The type matches, so check the instance count to see if it's the one we want
1030 (*SectionInstance
)--;
1031 if (*SectionInstance
== 0) {
1035 *FoundChild
= CurrentChildNode
;
1036 *FoundStream
= SourceStream
;
1037 *AuthenticationStatus
= SourceStream
->AuthenticationStatus
;
1043 // Type mismatch, or we haven't found the desired instance yet.
1045 ASSERT (*SectionInstance
> 0);
1047 if (CurrentChildNode
->EncapsulatedStreamHandle
!= NULL_STREAM_HANDLE
) {
1049 // If the current node is an encapsulating node, recurse into it...
1051 Status
= FindChildNode (
1052 (CORE_SECTION_STREAM_NODE
*)CurrentChildNode
->EncapsulatedStreamHandle
,
1055 SectionDefinitionGuid
,
1057 &RecursedFoundStream
,
1058 AuthenticationStatus
1060 if (*SectionInstance
== 0) {
1062 // The recursive FindChildNode() call decreased (*SectionInstance) to
1065 ASSERT_EFI_ERROR (Status
);
1066 *FoundChild
= RecursedChildNode
;
1067 *FoundStream
= RecursedFoundStream
;
1071 // If the status is not EFI_SUCCESS, just save the error code and
1072 // continue to find the request child node in the rest stream.
1074 ErrorStatus
= Status
;
1076 } else if ((CurrentChildNode
->Type
== EFI_SECTION_GUID_DEFINED
) && (SearchType
!= EFI_SECTION_GUID_DEFINED
)) {
1078 // When Node Type is GUIDED section, but Node has no encapsulated data, Node data should not be parsed
1079 // because a required GUIDED section extraction protocol does not exist.
1080 // If SearchType is not GUIDED section, EFI_PROTOCOL_ERROR should return.
1082 ErrorStatus
= EFI_PROTOCOL_ERROR
;
1085 if (!IsNodeAtEnd (&SourceStream
->Children
, &CurrentChildNode
->Link
)) {
1087 // We haven't found the child node we're interested in yet, but there's
1088 // still more nodes that have already been parsed so get the next one
1089 // and continue searching..
1091 CurrentChildNode
= CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream
->Children
, &CurrentChildNode
->Link
));
1094 // We've exhausted children that have already been parsed, so see if
1095 // there's any more data and continue parsing out more children if there
1098 NextChildOffset
= CurrentChildNode
->OffsetInStream
+ CurrentChildNode
->Size
;
1100 // Round up to 4 byte boundary
1102 NextChildOffset
+= 3;
1103 NextChildOffset
&= ~(UINTN
) 3;
1104 if (NextChildOffset
<= SourceStream
->StreamLength
- sizeof (EFI_COMMON_SECTION_HEADER
)) {
1106 // There's an unparsed child remaining in the stream, so create a new child node
1108 Status
= CreateChildNode (SourceStream
, NextChildOffset
, &CurrentChildNode
);
1109 if (EFI_ERROR (Status
)) {
1113 ASSERT (EFI_ERROR (ErrorStatus
));
1122 Worker function. Search stream database for requested stream handle.
1124 @param SearchHandle Indicates which stream to look for.
1125 @param FoundStream Output pointer to the found stream.
1127 @retval EFI_SUCCESS StreamHandle was found and *FoundStream contains
1129 @retval EFI_NOT_FOUND SearchHandle was not found in the stream
1135 IN UINTN SearchHandle
,
1136 OUT CORE_SECTION_STREAM_NODE
**FoundStream
1139 CORE_SECTION_STREAM_NODE
*StreamNode
;
1141 if (!IsListEmpty (&mStreamRoot
)) {
1142 StreamNode
= STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot
));
1144 if (StreamNode
->StreamHandle
== SearchHandle
) {
1145 *FoundStream
= StreamNode
;
1147 } else if (IsNodeAtEnd (&mStreamRoot
, &StreamNode
->Link
)) {
1150 StreamNode
= STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot
, &StreamNode
->Link
));
1155 return EFI_NOT_FOUND
;
1160 SEP member function. Retrieves requested section from section stream.
1162 @param SectionStreamHandle The section stream from which to extract the
1164 @param SectionType A pointer to the type of section to search for.
1165 @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED,
1166 then SectionDefinitionGuid indicates which of
1167 these types of sections to search for.
1168 @param SectionInstance Indicates which instance of the requested
1170 @param Buffer Double indirection to buffer. If *Buffer is
1171 non-null on input, then the buffer is caller
1172 allocated. If Buffer is NULL, then the buffer
1173 is callee allocated. In either case, the
1174 required buffer size is returned in *BufferSize.
1175 @param BufferSize On input, indicates the size of *Buffer if
1176 *Buffer is non-null on input. On output,
1177 indicates the required size (allocated size if
1178 callee allocated) of *Buffer.
1179 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
1180 indicates the authentication status of the
1181 output buffer. If the input section's
1182 GuidedSectionHeader.Attributes field
1183 has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID
1184 bit as clear, AuthenticationStatus must return
1185 zero. Both local bits (19:16) and aggregate
1186 bits (3:0) in AuthenticationStatus are returned
1187 by ExtractSection(). These bits reflect the
1188 status of the extraction operation. The bit
1189 pattern in both regions must be the same, as
1190 the local and aggregate authentication statuses
1191 have equivalent meaning at this level. If the
1192 function returns anything other than
1193 EFI_SUCCESS, the value of *AuthenticationStatus
1195 @param IsFfs3Fv Indicates the FV format.
1197 @retval EFI_SUCCESS Section was retrieved successfully
1198 @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the
1199 section stream with its
1200 EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set,
1201 but there was no corresponding GUIDed Section
1202 Extraction Protocol in the handle database.
1203 *Buffer is unmodified.
1204 @retval EFI_NOT_FOUND An error was encountered when parsing the
1205 SectionStream. This indicates the SectionStream
1206 is not correctly formatted.
1207 @retval EFI_NOT_FOUND The requested section does not exist.
1208 @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process
1210 @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist.
1211 @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is
1212 insufficient to contain the requested section.
1213 The input buffer is filled and section contents
1220 IN UINTN SectionStreamHandle
,
1221 IN EFI_SECTION_TYPE
*SectionType
,
1222 IN EFI_GUID
*SectionDefinitionGuid
,
1223 IN UINTN SectionInstance
,
1225 IN OUT UINTN
*BufferSize
,
1226 OUT UINT32
*AuthenticationStatus
,
1230 CORE_SECTION_STREAM_NODE
*StreamNode
;
1233 CORE_SECTION_CHILD_NODE
*ChildNode
;
1234 CORE_SECTION_STREAM_NODE
*ChildStreamNode
;
1236 UINT32 ExtractedAuthenticationStatus
;
1240 EFI_COMMON_SECTION_HEADER
*Section
;
1243 ChildStreamNode
= NULL
;
1244 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1245 Instance
= SectionInstance
+ 1;
1248 // Locate target stream
1250 Status
= FindStreamNode (SectionStreamHandle
, &StreamNode
);
1251 if (EFI_ERROR (Status
)) {
1252 Status
= EFI_INVALID_PARAMETER
;
1253 goto GetSection_Done
;
1257 // Found the stream, now locate and return the appropriate section
1259 if (SectionType
== NULL
) {
1261 // SectionType == NULL means return the WHOLE section stream...
1263 CopySize
= StreamNode
->StreamLength
;
1264 CopyBuffer
= StreamNode
->StreamBuffer
;
1265 *AuthenticationStatus
= StreamNode
->AuthenticationStatus
;
1268 // There's a requested section type, so go find it and return it...
1270 Status
= FindChildNode (
1274 SectionDefinitionGuid
,
1277 &ExtractedAuthenticationStatus
1279 if (EFI_ERROR (Status
)) {
1280 goto GetSection_Done
;
1283 Section
= (EFI_COMMON_SECTION_HEADER
*) (ChildStreamNode
->StreamBuffer
+ ChildNode
->OffsetInStream
);
1285 if (IS_SECTION2 (Section
)) {
1286 ASSERT (SECTION2_SIZE (Section
) > 0x00FFFFFF);
1288 DEBUG ((DEBUG_ERROR
, "It is a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
1289 Status
= EFI_NOT_FOUND
;
1290 goto GetSection_Done
;
1292 CopySize
= SECTION2_SIZE (Section
) - sizeof (EFI_COMMON_SECTION_HEADER2
);
1293 CopyBuffer
= (UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER2
);
1295 CopySize
= SECTION_SIZE (Section
) - sizeof (EFI_COMMON_SECTION_HEADER
);
1296 CopyBuffer
= (UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER
);
1298 *AuthenticationStatus
= ExtractedAuthenticationStatus
;
1301 SectionSize
= CopySize
;
1302 if (*Buffer
!= NULL
) {
1304 // Caller allocated buffer. Fill to size and return required size...
1306 if (*BufferSize
< CopySize
) {
1307 Status
= EFI_WARN_BUFFER_TOO_SMALL
;
1308 CopySize
= *BufferSize
;
1312 // Callee allocated buffer. Allocate buffer and return size.
1314 *Buffer
= AllocatePool (CopySize
);
1315 if (*Buffer
== NULL
) {
1316 Status
= EFI_OUT_OF_RESOURCES
;
1317 goto GetSection_Done
;
1320 CopyMem (*Buffer
, CopyBuffer
, CopySize
);
1321 *BufferSize
= SectionSize
;
1324 CoreRestoreTpl (OldTpl
);
1331 Worker function. Destructor for child nodes.
1333 @param ChildNode Indicates the node to destroy
1338 IN CORE_SECTION_CHILD_NODE
*ChildNode
1341 ASSERT (ChildNode
->Signature
== CORE_SECTION_CHILD_SIGNATURE
);
1343 // Remove the child from it's list
1345 RemoveEntryList (&ChildNode
->Link
);
1347 if (ChildNode
->EncapsulatedStreamHandle
!= NULL_STREAM_HANDLE
) {
1349 // If it's an encapsulating section, we close the resulting section stream.
1350 // CloseSectionStream will free all memory associated with the stream.
1352 CloseSectionStream (ChildNode
->EncapsulatedStreamHandle
, TRUE
);
1355 if (ChildNode
->Event
!= NULL
) {
1356 gBS
->CloseEvent (ChildNode
->Event
);
1360 // Last, free the child node itself
1362 CoreFreePool (ChildNode
);
1367 SEP member function. Deletes an existing section stream
1369 @param StreamHandleToClose Indicates the stream to close
1370 @param FreeStreamBuffer TRUE - Need to free stream buffer;
1371 FALSE - No need to free stream buffer.
1373 @retval EFI_SUCCESS The section stream is closed sucessfully.
1374 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1375 @retval EFI_INVALID_PARAMETER Section stream does not end concident with end
1381 CloseSectionStream (
1382 IN UINTN StreamHandleToClose
,
1383 IN BOOLEAN FreeStreamBuffer
1386 CORE_SECTION_STREAM_NODE
*StreamNode
;
1390 CORE_SECTION_CHILD_NODE
*ChildNode
;
1392 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1395 // Locate target stream
1397 Status
= FindStreamNode (StreamHandleToClose
, &StreamNode
);
1398 if (!EFI_ERROR (Status
)) {
1400 // Found the stream, so close it
1402 RemoveEntryList (&StreamNode
->Link
);
1403 while (!IsListEmpty (&StreamNode
->Children
)) {
1404 Link
= GetFirstNode (&StreamNode
->Children
);
1405 ChildNode
= CHILD_SECTION_NODE_FROM_LINK (Link
);
1406 FreeChildNode (ChildNode
);
1408 if (FreeStreamBuffer
) {
1409 CoreFreePool (StreamNode
->StreamBuffer
);
1411 CoreFreePool (StreamNode
);
1412 Status
= EFI_SUCCESS
;
1414 Status
= EFI_INVALID_PARAMETER
;
1417 CoreRestoreTpl (OldTpl
);
1423 The ExtractSection() function processes the input section and
1424 allocates a buffer from the pool in which it returns the section
1425 contents. If the section being extracted contains
1426 authentication information (the section's
1427 GuidedSectionHeader.Attributes field has the
1428 EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
1429 returned in AuthenticationStatus must reflect the results of
1430 the authentication operation. Depending on the algorithm and
1431 size of the encapsulated data, the time that is required to do
1432 a full authentication may be prohibitively long for some
1433 classes of systems. To indicate this, use
1434 EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
1435 the security policy driver (see the Platform Initialization
1436 Driver Execution Environment Core Interface Specification for
1437 more details and the GUID definition). If the
1438 EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
1439 database, then, if possible, full authentication should be
1440 skipped and the section contents simply returned in the
1441 OutputBuffer. In this case, the
1442 EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
1443 must be set on return. ExtractSection() is callable only from
1444 TPL_NOTIFY and below. Behavior of ExtractSection() at any
1445 EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
1446 defined in RaiseTPL() in the UEFI 2.0 specification.
1449 @param This Indicates the
1450 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
1451 @param InputSection Buffer containing the input GUIDed section
1452 to be processed. OutputBuffer OutputBuffer
1453 is allocated from boot services pool
1454 memory and contains the new section
1455 stream. The caller is responsible for
1456 freeing this buffer.
1457 @param OutputBuffer *OutputBuffer is allocated from boot services
1458 pool memory and contains the new section stream.
1459 The caller is responsible for freeing this buffer.
1460 @param OutputSize A pointer to a caller-allocated UINTN in
1461 which the size of OutputBuffer allocation
1462 is stored. If the function returns
1463 anything other than EFI_SUCCESS, the value
1464 of OutputSize is undefined.
1466 @param AuthenticationStatus A pointer to a caller-allocated
1467 UINT32 that indicates the
1468 authentication status of the
1469 output buffer. If the input
1471 GuidedSectionHeader.Attributes
1473 EFI_GUIDED_SECTION_AUTH_STATUS_VAL
1474 bit as clear, AuthenticationStatus
1475 must return zero. Both local bits
1476 (19:16) and aggregate bits (3:0)
1477 in AuthenticationStatus are
1478 returned by ExtractSection().
1479 These bits reflect the status of
1480 the extraction operation. The bit
1481 pattern in both regions must be
1482 the same, as the local and
1483 aggregate authentication statuses
1484 have equivalent meaning at this
1485 level. If the function returns
1486 anything other than EFI_SUCCESS,
1487 the value of AuthenticationStatus
1491 @retval EFI_SUCCESS The InputSection was successfully
1492 processed and the section contents were
1495 @retval EFI_OUT_OF_RESOURCES The system has insufficient
1496 resources to process the
1499 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
1500 not match this instance of the
1501 GUIDed Section Extraction
1507 CustomGuidedSectionExtract (
1508 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*This
,
1509 IN CONST VOID
*InputSection
,
1510 OUT VOID
**OutputBuffer
,
1511 OUT UINTN
*OutputSize
,
1512 OUT UINT32
*AuthenticationStatus
1516 VOID
*ScratchBuffer
;
1517 VOID
*AllocatedOutputBuffer
;
1518 UINT32 OutputBufferSize
;
1519 UINT32 ScratchBufferSize
;
1520 UINT16 SectionAttribute
;
1523 // Init local variable
1525 ScratchBuffer
= NULL
;
1526 AllocatedOutputBuffer
= NULL
;
1529 // Call GetInfo to get the size and attribute of input guided section data.
1531 Status
= ExtractGuidedSectionGetInfo (
1538 if (EFI_ERROR (Status
)) {
1539 DEBUG ((DEBUG_ERROR
, "GetInfo from guided section Failed - %r\n", Status
));
1543 if (ScratchBufferSize
> 0) {
1545 // Allocate scratch buffer
1547 ScratchBuffer
= AllocatePool (ScratchBufferSize
);
1548 if (ScratchBuffer
== NULL
) {
1549 return EFI_OUT_OF_RESOURCES
;
1553 if (OutputBufferSize
> 0) {
1555 // Allocate output buffer
1557 AllocatedOutputBuffer
= AllocatePool (OutputBufferSize
);
1558 if (AllocatedOutputBuffer
== NULL
) {
1559 if (ScratchBuffer
!= NULL
) {
1560 FreePool (ScratchBuffer
);
1562 return EFI_OUT_OF_RESOURCES
;
1564 *OutputBuffer
= AllocatedOutputBuffer
;
1568 // Call decode function to extract raw data from the guided section.
1570 Status
= ExtractGuidedSectionDecode (
1574 AuthenticationStatus
1576 if (EFI_ERROR (Status
)) {
1580 if (AllocatedOutputBuffer
!= NULL
) {
1581 CoreFreePool (AllocatedOutputBuffer
);
1583 if (ScratchBuffer
!= NULL
) {
1584 CoreFreePool (ScratchBuffer
);
1586 DEBUG ((DEBUG_ERROR
, "Extract guided section Failed - %r\n", Status
));
1590 if (*OutputBuffer
!= AllocatedOutputBuffer
) {
1592 // OutputBuffer was returned as a different value,
1593 // so copy section contents to the allocated memory buffer.
1595 CopyMem (AllocatedOutputBuffer
, *OutputBuffer
, OutputBufferSize
);
1596 *OutputBuffer
= AllocatedOutputBuffer
;
1600 // Set real size of output buffer.
1602 *OutputSize
= (UINTN
) OutputBufferSize
;
1605 // Free unused scratch buffer.
1607 if (ScratchBuffer
!= NULL
) {
1608 CoreFreePool (ScratchBuffer
);