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 - 2016, Intel Corporation. All rights reserved.<BR>
31 This program and the accompanying materials
32 are licensed and made available under the terms and conditions of the BSD License
33 which accompanies this distribution. The full text of the license may be found at
34 http://opensource.org/licenses/bsd-license.php
36 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
37 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
44 // Local defines and typedefs
46 #define CORE_SECTION_CHILD_SIGNATURE SIGNATURE_32('S','X','C','S')
47 #define CHILD_SECTION_NODE_FROM_LINK(Node) \
48 CR (Node, CORE_SECTION_CHILD_NODE, Link, CORE_SECTION_CHILD_SIGNATURE)
56 // StreamBase + OffsetInStream == pointer to section header in stream. The
57 // stream base is always known when walking the sections within.
59 UINT32 OffsetInStream
;
61 // Then EncapsulatedStreamHandle below is always 0 if the section is NOT an
62 // encapsulating section. Otherwise, it contains the stream handle
63 // of the encapsulated stream. This handle is ALWAYS produced any time an
64 // encapsulating child is encountered, irrespective of whether the
65 // encapsulated stream is processed further.
67 UINTN EncapsulatedStreamHandle
;
68 EFI_GUID
*EncapsulationGuid
;
70 // If the section REQUIRES an extraction protocol, register for RPN
71 // when the required GUIDed extraction protocol becomes available.
74 } CORE_SECTION_CHILD_NODE
;
76 #define CORE_SECTION_STREAM_SIGNATURE SIGNATURE_32('S','X','S','S')
77 #define STREAM_NODE_FROM_LINK(Node) \
78 CR (Node, CORE_SECTION_STREAM_NODE, Link, CORE_SECTION_STREAM_SIGNATURE)
88 // Authentication status is from GUIDed encapsulations.
90 UINT32 AuthenticationStatus
;
91 } CORE_SECTION_STREAM_NODE
;
93 #define NULL_STREAM_HANDLE 0
96 CORE_SECTION_CHILD_NODE
*ChildNode
;
97 CORE_SECTION_STREAM_NODE
*ParentStream
;
103 The ExtractSection() function processes the input section and
104 allocates a buffer from the pool in which it returns the section
105 contents. If the section being extracted contains
106 authentication information (the section's
107 GuidedSectionHeader.Attributes field has the
108 EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
109 returned in AuthenticationStatus must reflect the results of
110 the authentication operation. Depending on the algorithm and
111 size of the encapsulated data, the time that is required to do
112 a full authentication may be prohibitively long for some
113 classes of systems. To indicate this, use
114 EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
115 the security policy driver (see the Platform Initialization
116 Driver Execution Environment Core Interface Specification for
117 more details and the GUID definition). If the
118 EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
119 database, then, if possible, full authentication should be
120 skipped and the section contents simply returned in the
121 OutputBuffer. In this case, the
122 EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
123 must be set on return. ExtractSection() is callable only from
124 TPL_NOTIFY and below. Behavior of ExtractSection() at any
125 EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
126 defined in RaiseTPL() in the UEFI 2.0 specification.
129 @param This Indicates the
130 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
131 @param InputSection Buffer containing the input GUIDed section
132 to be processed. OutputBuffer OutputBuffer
133 is allocated from boot services pool
134 memory and contains the new section
135 stream. The caller is responsible for
137 @param OutputBuffer *OutputBuffer is allocated from boot services
138 pool memory and contains the new section stream.
139 The caller is responsible for freeing this buffer.
140 @param OutputSize A pointer to a caller-allocated UINTN in
141 which the size of OutputBuffer allocation
142 is stored. If the function returns
143 anything other than EFI_SUCCESS, the value
144 of OutputSize is undefined.
146 @param AuthenticationStatus A pointer to a caller-allocated
147 UINT32 that indicates the
148 authentication status of the
149 output buffer. If the input
151 GuidedSectionHeader.Attributes
153 EFI_GUIDED_SECTION_AUTH_STATUS_VAL
154 bit as clear, AuthenticationStatus
155 must return zero. Both local bits
156 (19:16) and aggregate bits (3:0)
157 in AuthenticationStatus are
158 returned by ExtractSection().
159 These bits reflect the status of
160 the extraction operation. The bit
161 pattern in both regions must be
162 the same, as the local and
163 aggregate authentication statuses
164 have equivalent meaning at this
165 level. If the function returns
166 anything other than EFI_SUCCESS,
167 the value of AuthenticationStatus
171 @retval EFI_SUCCESS The InputSection was successfully
172 processed and the section contents were
175 @retval EFI_OUT_OF_RESOURCES The system has insufficient
176 resources to process the
179 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
180 not match this instance of the
181 GUIDed Section Extraction
187 CustomGuidedSectionExtract (
188 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*This
,
189 IN CONST VOID
*InputSection
,
190 OUT VOID
**OutputBuffer
,
191 OUT UINTN
*OutputSize
,
192 OUT UINT32
*AuthenticationStatus
198 LIST_ENTRY mStreamRoot
= INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot
);
200 EFI_HANDLE mSectionExtractionHandle
= NULL
;
202 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL mCustomGuidedSectionExtractionProtocol
= {
203 CustomGuidedSectionExtract
208 Entry point of the section extraction code. Initializes an instance of the
209 section extraction interface and installs it on a new handle.
211 @param ImageHandle A handle for the image that is initializing this driver
212 @param SystemTable A pointer to the EFI system table
214 @retval EFI_SUCCESS Driver initialized successfully
215 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
220 InitializeSectionExtraction (
221 IN EFI_HANDLE ImageHandle
,
222 IN EFI_SYSTEM_TABLE
*SystemTable
226 EFI_GUID
*ExtractHandlerGuidTable
;
227 UINTN ExtractHandlerNumber
;
230 // Get custom extract guided section method guid list
232 ExtractHandlerNumber
= ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable
);
234 Status
= EFI_SUCCESS
;
236 // Install custom guided extraction protocol
238 while (ExtractHandlerNumber
-- > 0) {
239 Status
= CoreInstallProtocolInterface (
240 &mSectionExtractionHandle
,
241 &ExtractHandlerGuidTable
[ExtractHandlerNumber
],
242 EFI_NATIVE_INTERFACE
,
243 &mCustomGuidedSectionExtractionProtocol
245 ASSERT_EFI_ERROR (Status
);
253 Check if a stream is valid.
255 @param SectionStream The section stream to be checked
256 @param SectionStreamLength The length of section stream
258 @return A boolean value indicating the validness of the section stream.
262 IsValidSectionStream (
263 IN VOID
*SectionStream
,
264 IN UINTN SectionStreamLength
269 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
270 EFI_COMMON_SECTION_HEADER
*NextSectionHeader
;
273 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*)SectionStream
;
275 while (TotalLength
< SectionStreamLength
) {
276 if (IS_SECTION2 (SectionHeader
)) {
277 SectionLength
= SECTION2_SIZE (SectionHeader
);
279 SectionLength
= SECTION_SIZE (SectionHeader
);
281 TotalLength
+= SectionLength
;
283 if (TotalLength
== SectionStreamLength
) {
288 // Move to the next byte following the section...
290 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ SectionLength
);
293 // Figure out where the next section begins
295 NextSectionHeader
= ALIGN_POINTER(SectionHeader
, 4);
296 TotalLength
+= (UINTN
) NextSectionHeader
- (UINTN
) SectionHeader
;
297 SectionHeader
= NextSectionHeader
;
306 Worker function. Constructor for section streams.
308 @param SectionStreamLength Size in bytes of the section stream.
309 @param SectionStream Buffer containing the new section stream.
310 @param AllocateBuffer Indicates whether the stream buffer is to be
311 copied or the input buffer is to be used in
312 place. AuthenticationStatus- Indicates the
313 default authentication status for the new
315 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
316 indicates the authentication status of the
317 output buffer. If the input section's
318 GuidedSectionHeader.Attributes field
319 has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID
320 bit as clear, AuthenticationStatus must return
321 zero. Both local bits (19:16) and aggregate
322 bits (3:0) in AuthenticationStatus are returned
323 by ExtractSection(). These bits reflect the
324 status of the extraction operation. The bit
325 pattern in both regions must be the same, as
326 the local and aggregate authentication statuses
327 have equivalent meaning at this level. If the
328 function returns anything other than
329 EFI_SUCCESS, the value of *AuthenticationStatus
331 @param SectionStreamHandle A pointer to a caller allocated section stream
334 @retval EFI_SUCCESS Stream was added to stream database.
335 @retval EFI_OUT_OF_RESOURCES memory allocation failed.
339 OpenSectionStreamEx (
340 IN UINTN SectionStreamLength
,
341 IN VOID
*SectionStream
,
342 IN BOOLEAN AllocateBuffer
,
343 IN UINT32 AuthenticationStatus
,
344 OUT UINTN
*SectionStreamHandle
347 CORE_SECTION_STREAM_NODE
*NewStream
;
351 // Allocate a new stream
353 NewStream
= AllocatePool (sizeof (CORE_SECTION_STREAM_NODE
));
354 if (NewStream
== NULL
) {
355 return EFI_OUT_OF_RESOURCES
;
358 if (AllocateBuffer
) {
360 // if we're here, we're double buffering, allocate the buffer and copy the
363 if (SectionStreamLength
> 0) {
364 NewStream
->StreamBuffer
= AllocatePool (SectionStreamLength
);
365 if (NewStream
->StreamBuffer
== NULL
) {
366 CoreFreePool (NewStream
);
367 return EFI_OUT_OF_RESOURCES
;
370 // Copy in stream data
372 CopyMem (NewStream
->StreamBuffer
, SectionStream
, SectionStreamLength
);
375 // It's possible to have a zero length section stream.
377 NewStream
->StreamBuffer
= NULL
;
381 // If were here, the caller has supplied the buffer (it's an internal call)
382 // so just assign the buffer. This happens when we open section streams
383 // as a result of expanding an encapsulating section.
385 NewStream
->StreamBuffer
= SectionStream
;
389 // Initialize the rest of the section stream
391 NewStream
->Signature
= CORE_SECTION_STREAM_SIGNATURE
;
392 NewStream
->StreamHandle
= (UINTN
) NewStream
;
393 NewStream
->StreamLength
= SectionStreamLength
;
394 InitializeListHead (&NewStream
->Children
);
395 NewStream
->AuthenticationStatus
= AuthenticationStatus
;
398 // Add new stream to stream list
400 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
401 InsertTailList (&mStreamRoot
, &NewStream
->Link
);
402 CoreRestoreTpl (OldTpl
);
404 *SectionStreamHandle
= NewStream
->StreamHandle
;
411 SEP member function. This function creates and returns a new section stream
412 handle to represent the new section stream.
414 @param SectionStreamLength Size in bytes of the section stream.
415 @param SectionStream Buffer containing the new section stream.
416 @param SectionStreamHandle A pointer to a caller allocated UINTN that on
417 output contains the new section stream handle.
419 @retval EFI_SUCCESS The section stream is created successfully.
420 @retval EFI_OUT_OF_RESOURCES memory allocation failed.
421 @retval EFI_INVALID_PARAMETER Section stream does not end concident with end
428 IN UINTN SectionStreamLength
,
429 IN VOID
*SectionStream
,
430 OUT UINTN
*SectionStreamHandle
434 // Check to see section stream looks good...
436 if (!IsValidSectionStream (SectionStream
, SectionStreamLength
)) {
437 return EFI_INVALID_PARAMETER
;
440 return OpenSectionStreamEx (
452 Worker function. Determine if the input stream:child matches the input type.
454 @param Stream Indicates the section stream associated with the
456 @param Child Indicates the child to check
457 @param SearchType Indicates the type of section to check against
459 @param SectionDefinitionGuid Indicates the GUID to check against if the type
460 is EFI_SECTION_GUID_DEFINED
462 @retval TRUE The child matches
463 @retval FALSE The child doesn't match
468 IN CORE_SECTION_STREAM_NODE
*Stream
,
469 IN CORE_SECTION_CHILD_NODE
*Child
,
470 IN EFI_SECTION_TYPE SearchType
,
471 IN EFI_GUID
*SectionDefinitionGuid
474 EFI_GUID_DEFINED_SECTION
*GuidedSection
;
476 if (SearchType
== EFI_SECTION_ALL
) {
479 if (Child
->Type
!= SearchType
) {
482 if ((SearchType
!= EFI_SECTION_GUID_DEFINED
) || (SectionDefinitionGuid
== NULL
)) {
485 GuidedSection
= (EFI_GUID_DEFINED_SECTION
* )(Stream
->StreamBuffer
+ Child
->OffsetInStream
);
486 if (IS_SECTION2 (GuidedSection
)) {
487 return CompareGuid (&(((EFI_GUID_DEFINED_SECTION2
*) GuidedSection
)->SectionDefinitionGuid
), SectionDefinitionGuid
);
489 return CompareGuid (&GuidedSection
->SectionDefinitionGuid
, SectionDefinitionGuid
);
494 Verify the Guided Section GUID by checking if there is the Guided Section GUID configuration table recorded the GUID itself.
496 @param GuidedSectionGuid The Guided Section GUID.
497 @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Protocol
498 for the Guided Section.
500 @return TRUE The GuidedSectionGuid could be identified, and the pointer to
501 the Guided Section Extraction Protocol will be returned to *GuidedSectionExtraction.
502 @return FALSE The GuidedSectionGuid could not be identified, or
503 the Guided Section Extraction Protocol has not been installed yet.
507 VerifyGuidedSectionGuid (
508 IN EFI_GUID
*GuidedSectionGuid
,
509 OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
**GuidedSectionExtraction
512 EFI_GUID
*GuidRecorded
;
519 // Check if there is the Guided Section GUID configuration table recorded the GUID itself.
521 Status
= EfiGetSystemConfigurationTable (GuidedSectionGuid
, (VOID
**) &GuidRecorded
);
522 if (Status
== EFI_SUCCESS
) {
523 if (CompareGuid (GuidRecorded
, GuidedSectionGuid
)) {
525 // Found the recorded GuidedSectionGuid.
527 Status
= CoreLocateProtocol (GuidedSectionGuid
, NULL
, (VOID
**) &Interface
);
528 if (!EFI_ERROR (Status
) && Interface
!= NULL
) {
530 // Found the supported Guided Section Extraction Porotocol for the Guided Section.
532 *GuidedSectionExtraction
= (EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*) Interface
;
543 RPN callback function. Initializes the section stream
544 when GUIDED_SECTION_EXTRACTION_PROTOCOL is installed.
546 @param Event The event that fired
547 @param RpnContext A pointer to the context that allows us to identify
548 the relevent encapsulation.
552 NotifyGuidedExtraction (
558 EFI_GUID_DEFINED_SECTION
*GuidedHeader
;
559 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*GuidedExtraction
;
560 VOID
*NewStreamBuffer
;
561 UINTN NewStreamBufferSize
;
562 UINT32 AuthenticationStatus
;
563 RPN_EVENT_CONTEXT
*Context
;
565 Context
= RpnContext
;
567 GuidedHeader
= (EFI_GUID_DEFINED_SECTION
*) (Context
->ParentStream
->StreamBuffer
+ Context
->ChildNode
->OffsetInStream
);
568 ASSERT (GuidedHeader
->CommonHeader
.Type
== EFI_SECTION_GUID_DEFINED
);
570 if (!VerifyGuidedSectionGuid (Context
->ChildNode
->EncapsulationGuid
, &GuidedExtraction
)) {
574 Status
= GuidedExtraction
->ExtractSection (
578 &NewStreamBufferSize
,
579 &AuthenticationStatus
581 ASSERT_EFI_ERROR (Status
);
584 // Make sure we initialize the new stream with the correct
585 // authentication status for both aggregate and local status fields.
587 if ((GuidedHeader
->Attributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
589 // OR in the parent stream's aggregate status.
591 AuthenticationStatus
|= Context
->ParentStream
->AuthenticationStatus
& EFI_AUTH_STATUS_ALL
;
594 // since there's no authentication data contributed by the section,
595 // just inherit the full value from our immediate parent.
597 AuthenticationStatus
= Context
->ParentStream
->AuthenticationStatus
;
600 Status
= OpenSectionStreamEx (
604 AuthenticationStatus
,
605 &Context
->ChildNode
->EncapsulatedStreamHandle
607 ASSERT_EFI_ERROR (Status
);
610 // Close the event when done.
612 gBS
->CloseEvent (Event
);
613 Context
->ChildNode
->Event
= NULL
;
618 Constructor for RPN event when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...
620 @param ParentStream Indicates the parent of the ecnapsulation section (child)
621 @param ChildNode Indicates the child node that is the encapsulation section.
625 CreateGuidedExtractionRpnEvent (
626 IN CORE_SECTION_STREAM_NODE
*ParentStream
,
627 IN CORE_SECTION_CHILD_NODE
*ChildNode
630 RPN_EVENT_CONTEXT
*Context
;
633 // Allocate new event structure and context
635 Context
= AllocatePool (sizeof (RPN_EVENT_CONTEXT
));
636 ASSERT (Context
!= NULL
);
638 Context
->ChildNode
= ChildNode
;
639 Context
->ParentStream
= ParentStream
;
641 Context
->ChildNode
->Event
= EfiCreateProtocolNotifyEvent (
642 Context
->ChildNode
->EncapsulationGuid
,
644 NotifyGuidedExtraction
,
646 &Context
->Registration
651 Worker function. Constructor for new child nodes.
653 @param Stream Indicates the section stream in which to add the
655 @param ChildOffset Indicates the offset in Stream that is the
656 beginning of the child section.
657 @param ChildNode Indicates the Callee allocated and initialized
660 @retval EFI_SUCCESS Child node was found and returned.
661 EFI_OUT_OF_RESOURCES- Memory allocation failed.
662 @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream
663 handles when the child node is created. If the
664 section type is GUID defined, and the extraction
665 GUID does not exist, and producing the stream
666 requires the GUID, then a protocol error is
667 generated and no child is produced. Values
668 returned by OpenSectionStreamEx.
673 IN CORE_SECTION_STREAM_NODE
*Stream
,
674 IN UINT32 ChildOffset
,
675 OUT CORE_SECTION_CHILD_NODE
**ChildNode
679 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
680 EFI_COMPRESSION_SECTION
*CompressionHeader
;
681 EFI_GUID_DEFINED_SECTION
*GuidedHeader
;
682 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
683 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*GuidedExtraction
;
684 VOID
*NewStreamBuffer
;
687 UINTN NewStreamBufferSize
;
688 UINT32 AuthenticationStatus
;
689 VOID
*CompressionSource
;
690 UINT32 CompressionSourceSize
;
691 UINT32 UncompressedLength
;
692 UINT8 CompressionType
;
693 UINT16 GuidedSectionAttributes
;
695 CORE_SECTION_CHILD_NODE
*Node
;
697 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) (Stream
->StreamBuffer
+ ChildOffset
);
700 // Allocate a new node
702 *ChildNode
= AllocateZeroPool (sizeof (CORE_SECTION_CHILD_NODE
));
705 return EFI_OUT_OF_RESOURCES
;
711 Node
->Signature
= CORE_SECTION_CHILD_SIGNATURE
;
712 Node
->Type
= SectionHeader
->Type
;
713 if (IS_SECTION2 (SectionHeader
)) {
714 Node
->Size
= SECTION2_SIZE (SectionHeader
);
716 Node
->Size
= SECTION_SIZE (SectionHeader
);
718 Node
->OffsetInStream
= ChildOffset
;
719 Node
->EncapsulatedStreamHandle
= NULL_STREAM_HANDLE
;
720 Node
->EncapsulationGuid
= NULL
;
723 // If it's an encapsulating section, then create the new section stream also
725 switch (Node
->Type
) {
726 case EFI_SECTION_COMPRESSION
:
728 // Get the CompressionSectionHeader
730 if (Node
->Size
< sizeof (EFI_COMPRESSION_SECTION
)) {
732 return EFI_NOT_FOUND
;
735 CompressionHeader
= (EFI_COMPRESSION_SECTION
*) SectionHeader
;
737 if (IS_SECTION2 (CompressionHeader
)) {
738 CompressionSource
= (VOID
*) ((UINT8
*) CompressionHeader
+ sizeof (EFI_COMPRESSION_SECTION2
));
739 CompressionSourceSize
= (UINT32
) (SECTION2_SIZE (CompressionHeader
) - sizeof (EFI_COMPRESSION_SECTION2
));
740 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*) CompressionHeader
)->UncompressedLength
;
741 CompressionType
= ((EFI_COMPRESSION_SECTION2
*) CompressionHeader
)->CompressionType
;
743 CompressionSource
= (VOID
*) ((UINT8
*) CompressionHeader
+ sizeof (EFI_COMPRESSION_SECTION
));
744 CompressionSourceSize
= (UINT32
) (SECTION_SIZE (CompressionHeader
) - sizeof (EFI_COMPRESSION_SECTION
));
745 UncompressedLength
= CompressionHeader
->UncompressedLength
;
746 CompressionType
= CompressionHeader
->CompressionType
;
750 // Allocate space for the new stream
752 if (UncompressedLength
> 0) {
753 NewStreamBufferSize
= UncompressedLength
;
754 NewStreamBuffer
= AllocatePool (NewStreamBufferSize
);
755 if (NewStreamBuffer
== NULL
) {
757 return EFI_OUT_OF_RESOURCES
;
760 if (CompressionType
== EFI_NOT_COMPRESSED
) {
762 // stream is not actually compressed, just encapsulated. So just copy it.
764 CopyMem (NewStreamBuffer
, CompressionSource
, NewStreamBufferSize
);
765 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
767 // Only support the EFI_SATNDARD_COMPRESSION algorithm.
771 // Decompress the stream
773 Status
= CoreLocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**)&Decompress
);
774 ASSERT_EFI_ERROR (Status
);
775 ASSERT (Decompress
!= NULL
);
777 Status
= Decompress
->GetInfo (
780 CompressionSourceSize
,
781 (UINT32
*)&NewStreamBufferSize
,
784 if (EFI_ERROR (Status
) || (NewStreamBufferSize
!= UncompressedLength
)) {
786 CoreFreePool (NewStreamBuffer
);
787 if (!EFI_ERROR (Status
)) {
788 Status
= EFI_BAD_BUFFER_SIZE
;
793 ScratchBuffer
= AllocatePool (ScratchSize
);
794 if (ScratchBuffer
== NULL
) {
796 CoreFreePool (NewStreamBuffer
);
797 return EFI_OUT_OF_RESOURCES
;
800 Status
= Decompress
->Decompress (
803 CompressionSourceSize
,
805 (UINT32
)NewStreamBufferSize
,
809 CoreFreePool (ScratchBuffer
);
810 if (EFI_ERROR (Status
)) {
812 CoreFreePool (NewStreamBuffer
);
817 NewStreamBuffer
= NULL
;
818 NewStreamBufferSize
= 0;
821 Status
= OpenSectionStreamEx (
825 Stream
->AuthenticationStatus
,
826 &Node
->EncapsulatedStreamHandle
828 if (EFI_ERROR (Status
)) {
830 CoreFreePool (NewStreamBuffer
);
835 case EFI_SECTION_GUID_DEFINED
:
836 GuidedHeader
= (EFI_GUID_DEFINED_SECTION
*) SectionHeader
;
837 if (IS_SECTION2 (GuidedHeader
)) {
838 Node
->EncapsulationGuid
= &(((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->SectionDefinitionGuid
);
839 GuidedSectionAttributes
= ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->Attributes
;
841 Node
->EncapsulationGuid
= &GuidedHeader
->SectionDefinitionGuid
;
842 GuidedSectionAttributes
= GuidedHeader
->Attributes
;
844 if (VerifyGuidedSectionGuid (Node
->EncapsulationGuid
, &GuidedExtraction
)) {
846 // NewStreamBuffer is always allocated by ExtractSection... No caller
849 Status
= GuidedExtraction
->ExtractSection (
853 &NewStreamBufferSize
,
854 &AuthenticationStatus
856 if (EFI_ERROR (Status
)) {
857 CoreFreePool (*ChildNode
);
858 return EFI_PROTOCOL_ERROR
;
862 // Make sure we initialize the new stream with the correct
863 // authentication status for both aggregate and local status fields.
865 if ((GuidedSectionAttributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
867 // OR in the parent stream's aggregate status.
869 AuthenticationStatus
|= Stream
->AuthenticationStatus
& EFI_AUTH_STATUS_ALL
;
872 // since there's no authentication data contributed by the section,
873 // just inherit the full value from our immediate parent.
875 AuthenticationStatus
= Stream
->AuthenticationStatus
;
878 Status
= OpenSectionStreamEx (
882 AuthenticationStatus
,
883 &Node
->EncapsulatedStreamHandle
885 if (EFI_ERROR (Status
)) {
886 CoreFreePool (*ChildNode
);
887 CoreFreePool (NewStreamBuffer
);
892 // There's no GUIDed section extraction protocol available.
894 if ((GuidedSectionAttributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
896 // If the section REQUIRES an extraction protocol, register for RPN
897 // when the required GUIDed extraction protocol becomes available.
899 CreateGuidedExtractionRpnEvent (Stream
, Node
);
902 // Figure out the proper authentication status
904 AuthenticationStatus
= Stream
->AuthenticationStatus
;
906 if ((GuidedSectionAttributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) {
907 AuthenticationStatus
|= EFI_AUTH_STATUS_IMAGE_SIGNED
| EFI_AUTH_STATUS_NOT_TESTED
;
910 if (IS_SECTION2 (GuidedHeader
)) {
911 Status
= OpenSectionStreamEx (
912 SECTION2_SIZE (GuidedHeader
) - ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->DataOffset
,
913 (UINT8
*) GuidedHeader
+ ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->DataOffset
,
915 AuthenticationStatus
,
916 &Node
->EncapsulatedStreamHandle
919 Status
= OpenSectionStreamEx (
920 SECTION_SIZE (GuidedHeader
) - ((EFI_GUID_DEFINED_SECTION
*) GuidedHeader
)->DataOffset
,
921 (UINT8
*) GuidedHeader
+ ((EFI_GUID_DEFINED_SECTION
*) GuidedHeader
)->DataOffset
,
923 AuthenticationStatus
,
924 &Node
->EncapsulatedStreamHandle
927 if (EFI_ERROR (Status
)) {
939 // Nothing to do if it's a leaf
945 // Last, add the new child node to the stream
947 InsertTailList (&Stream
->Children
, &Node
->Link
);
954 Worker function Recursively searches / builds section stream database
955 looking for requested section.
957 @param SourceStream Indicates the section stream in which to do the
959 @param SearchType Indicates the type of section to search for.
960 @param SectionInstance Indicates which instance of section to find.
961 This is an in/out parameter to deal with
963 @param SectionDefinitionGuid Guid of section definition
964 @param FoundChild Output indicating the child node that is found.
965 @param FoundStream Output indicating which section stream the child
966 was found in. If this stream was generated as a
967 result of an encapsulation section, the
968 streamhandle is visible within the SEP driver
970 @param AuthenticationStatus Indicates the authentication status of the found section.
972 @retval EFI_SUCCESS Child node was found and returned.
973 EFI_OUT_OF_RESOURCES- Memory allocation failed.
974 @retval EFI_NOT_FOUND Requested child node does not exist.
975 @retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol
981 IN CORE_SECTION_STREAM_NODE
*SourceStream
,
982 IN EFI_SECTION_TYPE SearchType
,
983 IN OUT UINTN
*SectionInstance
,
984 IN EFI_GUID
*SectionDefinitionGuid
,
985 OUT CORE_SECTION_CHILD_NODE
**FoundChild
,
986 OUT CORE_SECTION_STREAM_NODE
**FoundStream
,
987 OUT UINT32
*AuthenticationStatus
990 CORE_SECTION_CHILD_NODE
*CurrentChildNode
;
991 CORE_SECTION_CHILD_NODE
*RecursedChildNode
;
992 CORE_SECTION_STREAM_NODE
*RecursedFoundStream
;
993 UINT32 NextChildOffset
;
994 EFI_STATUS ErrorStatus
;
997 CurrentChildNode
= NULL
;
998 ErrorStatus
= EFI_NOT_FOUND
;
1000 if (SourceStream
->StreamLength
== 0) {
1001 return EFI_NOT_FOUND
;
1004 if (IsListEmpty (&SourceStream
->Children
) &&
1005 SourceStream
->StreamLength
>= sizeof (EFI_COMMON_SECTION_HEADER
)) {
1007 // This occurs when a section stream exists, but no child sections
1008 // have been parsed out yet. Therefore, extract the first child and add it
1009 // to the list of children so we can get started.
1010 // Section stream may contain an array of zero or more bytes.
1011 // So, its size should be >= the size of commen section header.
1013 Status
= CreateChildNode (SourceStream
, 0, &CurrentChildNode
);
1014 if (EFI_ERROR (Status
)) {
1020 // At least one child has been parsed out of the section stream. So, walk
1021 // through the sections that have already been parsed out looking for the
1022 // requested section, if necessary, continue parsing section stream and
1023 // adding children until either the requested section is found, or we run
1026 CurrentChildNode
= CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream
->Children
));
1029 ASSERT (CurrentChildNode
!= NULL
);
1030 if (ChildIsType (SourceStream
, CurrentChildNode
, SearchType
, SectionDefinitionGuid
)) {
1032 // The type matches, so check the instance count to see if it's the one we want
1034 (*SectionInstance
)--;
1035 if (*SectionInstance
== 0) {
1039 *FoundChild
= CurrentChildNode
;
1040 *FoundStream
= SourceStream
;
1041 *AuthenticationStatus
= SourceStream
->AuthenticationStatus
;
1046 if (CurrentChildNode
->EncapsulatedStreamHandle
!= NULL_STREAM_HANDLE
) {
1048 // If the current node is an encapsulating node, recurse into it...
1050 Status
= FindChildNode (
1051 (CORE_SECTION_STREAM_NODE
*)CurrentChildNode
->EncapsulatedStreamHandle
,
1054 SectionDefinitionGuid
,
1056 &RecursedFoundStream
,
1057 AuthenticationStatus
1060 // If the status is not EFI_SUCCESS, just save the error code and continue
1061 // to find the request child node in the rest stream.
1063 if (*SectionInstance
== 0) {
1064 ASSERT_EFI_ERROR (Status
);
1065 *FoundChild
= RecursedChildNode
;
1066 *FoundStream
= RecursedFoundStream
;
1069 ErrorStatus
= Status
;
1071 } else if ((CurrentChildNode
->Type
== EFI_SECTION_GUID_DEFINED
) && (SearchType
!= EFI_SECTION_GUID_DEFINED
)) {
1073 // When Node Type is GUIDED section, but Node has no encapsulated data, Node data should not be parsed
1074 // because a required GUIDED section extraction protocol does not exist.
1075 // If SearchType is not GUIDED section, EFI_PROTOCOL_ERROR should return.
1077 ErrorStatus
= EFI_PROTOCOL_ERROR
;
1080 if (!IsNodeAtEnd (&SourceStream
->Children
, &CurrentChildNode
->Link
)) {
1082 // We haven't found the child node we're interested in yet, but there's
1083 // still more nodes that have already been parsed so get the next one
1084 // and continue searching..
1086 CurrentChildNode
= CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream
->Children
, &CurrentChildNode
->Link
));
1089 // We've exhausted children that have already been parsed, so see if
1090 // there's any more data and continue parsing out more children if there
1093 NextChildOffset
= CurrentChildNode
->OffsetInStream
+ CurrentChildNode
->Size
;
1095 // Round up to 4 byte boundary
1097 NextChildOffset
+= 3;
1098 NextChildOffset
&= ~(UINTN
) 3;
1099 if (NextChildOffset
<= SourceStream
->StreamLength
- sizeof (EFI_COMMON_SECTION_HEADER
)) {
1101 // There's an unparsed child remaining in the stream, so create a new child node
1103 Status
= CreateChildNode (SourceStream
, NextChildOffset
, &CurrentChildNode
);
1104 if (EFI_ERROR (Status
)) {
1108 ASSERT (EFI_ERROR (ErrorStatus
));
1117 Worker function. Search stream database for requested stream handle.
1119 @param SearchHandle Indicates which stream to look for.
1120 @param FoundStream Output pointer to the found stream.
1122 @retval EFI_SUCCESS StreamHandle was found and *FoundStream contains
1124 @retval EFI_NOT_FOUND SearchHandle was not found in the stream
1130 IN UINTN SearchHandle
,
1131 OUT CORE_SECTION_STREAM_NODE
**FoundStream
1134 CORE_SECTION_STREAM_NODE
*StreamNode
;
1136 if (!IsListEmpty (&mStreamRoot
)) {
1137 StreamNode
= STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot
));
1139 if (StreamNode
->StreamHandle
== SearchHandle
) {
1140 *FoundStream
= StreamNode
;
1142 } else if (IsNodeAtEnd (&mStreamRoot
, &StreamNode
->Link
)) {
1145 StreamNode
= STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot
, &StreamNode
->Link
));
1150 return EFI_NOT_FOUND
;
1155 SEP member function. Retrieves requested section from section stream.
1157 @param SectionStreamHandle The section stream from which to extract the
1159 @param SectionType A pointer to the type of section to search for.
1160 @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED,
1161 then SectionDefinitionGuid indicates which of
1162 these types of sections to search for.
1163 @param SectionInstance Indicates which instance of the requested
1165 @param Buffer Double indirection to buffer. If *Buffer is
1166 non-null on input, then the buffer is caller
1167 allocated. If Buffer is NULL, then the buffer
1168 is callee allocated. In either case, the
1169 required buffer size is returned in *BufferSize.
1170 @param BufferSize On input, indicates the size of *Buffer if
1171 *Buffer is non-null on input. On output,
1172 indicates the required size (allocated size if
1173 callee allocated) of *Buffer.
1174 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
1175 indicates the authentication status of the
1176 output buffer. If the input section's
1177 GuidedSectionHeader.Attributes field
1178 has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID
1179 bit as clear, AuthenticationStatus must return
1180 zero. Both local bits (19:16) and aggregate
1181 bits (3:0) in AuthenticationStatus are returned
1182 by ExtractSection(). These bits reflect the
1183 status of the extraction operation. The bit
1184 pattern in both regions must be the same, as
1185 the local and aggregate authentication statuses
1186 have equivalent meaning at this level. If the
1187 function returns anything other than
1188 EFI_SUCCESS, the value of *AuthenticationStatus
1190 @param IsFfs3Fv Indicates the FV format.
1192 @retval EFI_SUCCESS Section was retrieved successfully
1193 @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the
1194 section stream with its
1195 EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set,
1196 but there was no corresponding GUIDed Section
1197 Extraction Protocol in the handle database.
1198 *Buffer is unmodified.
1199 @retval EFI_NOT_FOUND An error was encountered when parsing the
1200 SectionStream. This indicates the SectionStream
1201 is not correctly formatted.
1202 @retval EFI_NOT_FOUND The requested section does not exist.
1203 @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process
1205 @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist.
1206 @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is
1207 insufficient to contain the requested section.
1208 The input buffer is filled and section contents
1215 IN UINTN SectionStreamHandle
,
1216 IN EFI_SECTION_TYPE
*SectionType
,
1217 IN EFI_GUID
*SectionDefinitionGuid
,
1218 IN UINTN SectionInstance
,
1220 IN OUT UINTN
*BufferSize
,
1221 OUT UINT32
*AuthenticationStatus
,
1225 CORE_SECTION_STREAM_NODE
*StreamNode
;
1228 CORE_SECTION_CHILD_NODE
*ChildNode
;
1229 CORE_SECTION_STREAM_NODE
*ChildStreamNode
;
1231 UINT32 ExtractedAuthenticationStatus
;
1235 EFI_COMMON_SECTION_HEADER
*Section
;
1238 ChildStreamNode
= NULL
;
1239 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1240 Instance
= SectionInstance
+ 1;
1243 // Locate target stream
1245 Status
= FindStreamNode (SectionStreamHandle
, &StreamNode
);
1246 if (EFI_ERROR (Status
)) {
1247 Status
= EFI_INVALID_PARAMETER
;
1248 goto GetSection_Done
;
1252 // Found the stream, now locate and return the appropriate section
1254 if (SectionType
== NULL
) {
1256 // SectionType == NULL means return the WHOLE section stream...
1258 CopySize
= StreamNode
->StreamLength
;
1259 CopyBuffer
= StreamNode
->StreamBuffer
;
1260 *AuthenticationStatus
= StreamNode
->AuthenticationStatus
;
1263 // There's a requested section type, so go find it and return it...
1265 Status
= FindChildNode (
1269 SectionDefinitionGuid
,
1272 &ExtractedAuthenticationStatus
1274 if (EFI_ERROR (Status
)) {
1275 goto GetSection_Done
;
1278 Section
= (EFI_COMMON_SECTION_HEADER
*) (ChildStreamNode
->StreamBuffer
+ ChildNode
->OffsetInStream
);
1280 if (IS_SECTION2 (Section
)) {
1281 ASSERT (SECTION2_SIZE (Section
) > 0x00FFFFFF);
1283 DEBUG ((DEBUG_ERROR
, "It is a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
1284 Status
= EFI_NOT_FOUND
;
1285 goto GetSection_Done
;
1287 CopySize
= SECTION2_SIZE (Section
) - sizeof (EFI_COMMON_SECTION_HEADER2
);
1288 CopyBuffer
= (UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER2
);
1290 CopySize
= SECTION_SIZE (Section
) - sizeof (EFI_COMMON_SECTION_HEADER
);
1291 CopyBuffer
= (UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER
);
1293 *AuthenticationStatus
= ExtractedAuthenticationStatus
;
1296 SectionSize
= CopySize
;
1297 if (*Buffer
!= NULL
) {
1299 // Caller allocated buffer. Fill to size and return required size...
1301 if (*BufferSize
< CopySize
) {
1302 Status
= EFI_WARN_BUFFER_TOO_SMALL
;
1303 CopySize
= *BufferSize
;
1307 // Callee allocated buffer. Allocate buffer and return size.
1309 *Buffer
= AllocatePool (CopySize
);
1310 if (*Buffer
== NULL
) {
1311 Status
= EFI_OUT_OF_RESOURCES
;
1312 goto GetSection_Done
;
1315 CopyMem (*Buffer
, CopyBuffer
, CopySize
);
1316 *BufferSize
= SectionSize
;
1319 CoreRestoreTpl (OldTpl
);
1326 Worker function. Destructor for child nodes.
1328 @param ChildNode Indicates the node to destroy
1333 IN CORE_SECTION_CHILD_NODE
*ChildNode
1336 ASSERT (ChildNode
->Signature
== CORE_SECTION_CHILD_SIGNATURE
);
1338 // Remove the child from it's list
1340 RemoveEntryList (&ChildNode
->Link
);
1342 if (ChildNode
->EncapsulatedStreamHandle
!= NULL_STREAM_HANDLE
) {
1344 // If it's an encapsulating section, we close the resulting section stream.
1345 // CloseSectionStream will free all memory associated with the stream.
1347 CloseSectionStream (ChildNode
->EncapsulatedStreamHandle
, TRUE
);
1350 if (ChildNode
->Event
!= NULL
) {
1351 gBS
->CloseEvent (ChildNode
->Event
);
1355 // Last, free the child node itself
1357 CoreFreePool (ChildNode
);
1362 SEP member function. Deletes an existing section stream
1364 @param StreamHandleToClose Indicates the stream to close
1365 @param FreeStreamBuffer TRUE - Need to free stream buffer;
1366 FALSE - No need to free stream buffer.
1368 @retval EFI_SUCCESS The section stream is closed sucessfully.
1369 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1370 @retval EFI_INVALID_PARAMETER Section stream does not end concident with end
1376 CloseSectionStream (
1377 IN UINTN StreamHandleToClose
,
1378 IN BOOLEAN FreeStreamBuffer
1381 CORE_SECTION_STREAM_NODE
*StreamNode
;
1385 CORE_SECTION_CHILD_NODE
*ChildNode
;
1387 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1390 // Locate target stream
1392 Status
= FindStreamNode (StreamHandleToClose
, &StreamNode
);
1393 if (!EFI_ERROR (Status
)) {
1395 // Found the stream, so close it
1397 RemoveEntryList (&StreamNode
->Link
);
1398 while (!IsListEmpty (&StreamNode
->Children
)) {
1399 Link
= GetFirstNode (&StreamNode
->Children
);
1400 ChildNode
= CHILD_SECTION_NODE_FROM_LINK (Link
);
1401 FreeChildNode (ChildNode
);
1403 if (FreeStreamBuffer
) {
1404 CoreFreePool (StreamNode
->StreamBuffer
);
1406 CoreFreePool (StreamNode
);
1407 Status
= EFI_SUCCESS
;
1409 Status
= EFI_INVALID_PARAMETER
;
1412 CoreRestoreTpl (OldTpl
);
1418 The ExtractSection() function processes the input section and
1419 allocates a buffer from the pool in which it returns the section
1420 contents. If the section being extracted contains
1421 authentication information (the section's
1422 GuidedSectionHeader.Attributes field has the
1423 EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
1424 returned in AuthenticationStatus must reflect the results of
1425 the authentication operation. Depending on the algorithm and
1426 size of the encapsulated data, the time that is required to do
1427 a full authentication may be prohibitively long for some
1428 classes of systems. To indicate this, use
1429 EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
1430 the security policy driver (see the Platform Initialization
1431 Driver Execution Environment Core Interface Specification for
1432 more details and the GUID definition). If the
1433 EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
1434 database, then, if possible, full authentication should be
1435 skipped and the section contents simply returned in the
1436 OutputBuffer. In this case, the
1437 EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
1438 must be set on return. ExtractSection() is callable only from
1439 TPL_NOTIFY and below. Behavior of ExtractSection() at any
1440 EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
1441 defined in RaiseTPL() in the UEFI 2.0 specification.
1444 @param This Indicates the
1445 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
1446 @param InputSection Buffer containing the input GUIDed section
1447 to be processed. OutputBuffer OutputBuffer
1448 is allocated from boot services pool
1449 memory and contains the new section
1450 stream. The caller is responsible for
1451 freeing this buffer.
1452 @param OutputBuffer *OutputBuffer is allocated from boot services
1453 pool memory and contains the new section stream.
1454 The caller is responsible for freeing this buffer.
1455 @param OutputSize A pointer to a caller-allocated UINTN in
1456 which the size of OutputBuffer allocation
1457 is stored. If the function returns
1458 anything other than EFI_SUCCESS, the value
1459 of OutputSize is undefined.
1461 @param AuthenticationStatus A pointer to a caller-allocated
1462 UINT32 that indicates the
1463 authentication status of the
1464 output buffer. If the input
1466 GuidedSectionHeader.Attributes
1468 EFI_GUIDED_SECTION_AUTH_STATUS_VAL
1469 bit as clear, AuthenticationStatus
1470 must return zero. Both local bits
1471 (19:16) and aggregate bits (3:0)
1472 in AuthenticationStatus are
1473 returned by ExtractSection().
1474 These bits reflect the status of
1475 the extraction operation. The bit
1476 pattern in both regions must be
1477 the same, as the local and
1478 aggregate authentication statuses
1479 have equivalent meaning at this
1480 level. If the function returns
1481 anything other than EFI_SUCCESS,
1482 the value of AuthenticationStatus
1486 @retval EFI_SUCCESS The InputSection was successfully
1487 processed and the section contents were
1490 @retval EFI_OUT_OF_RESOURCES The system has insufficient
1491 resources to process the
1494 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
1495 not match this instance of the
1496 GUIDed Section Extraction
1502 CustomGuidedSectionExtract (
1503 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*This
,
1504 IN CONST VOID
*InputSection
,
1505 OUT VOID
**OutputBuffer
,
1506 OUT UINTN
*OutputSize
,
1507 OUT UINT32
*AuthenticationStatus
1511 VOID
*ScratchBuffer
;
1512 VOID
*AllocatedOutputBuffer
;
1513 UINT32 OutputBufferSize
;
1514 UINT32 ScratchBufferSize
;
1515 UINT16 SectionAttribute
;
1518 // Init local variable
1520 ScratchBuffer
= NULL
;
1521 AllocatedOutputBuffer
= NULL
;
1524 // Call GetInfo to get the size and attribute of input guided section data.
1526 Status
= ExtractGuidedSectionGetInfo (
1533 if (EFI_ERROR (Status
)) {
1534 DEBUG ((DEBUG_ERROR
, "GetInfo from guided section Failed - %r\n", Status
));
1538 if (ScratchBufferSize
> 0) {
1540 // Allocate scratch buffer
1542 ScratchBuffer
= AllocatePool (ScratchBufferSize
);
1543 if (ScratchBuffer
== NULL
) {
1544 return EFI_OUT_OF_RESOURCES
;
1548 if (OutputBufferSize
> 0) {
1550 // Allocate output buffer
1552 AllocatedOutputBuffer
= AllocatePool (OutputBufferSize
);
1553 if (AllocatedOutputBuffer
== NULL
) {
1554 FreePool (ScratchBuffer
);
1555 return EFI_OUT_OF_RESOURCES
;
1557 *OutputBuffer
= AllocatedOutputBuffer
;
1561 // Call decode function to extract raw data from the guided section.
1563 Status
= ExtractGuidedSectionDecode (
1567 AuthenticationStatus
1569 if (EFI_ERROR (Status
)) {
1573 if (AllocatedOutputBuffer
!= NULL
) {
1574 CoreFreePool (AllocatedOutputBuffer
);
1576 if (ScratchBuffer
!= NULL
) {
1577 CoreFreePool (ScratchBuffer
);
1579 DEBUG ((DEBUG_ERROR
, "Extract guided section Failed - %r\n", Status
));
1583 if (*OutputBuffer
!= AllocatedOutputBuffer
) {
1585 // OutputBuffer was returned as a different value,
1586 // so copy section contents to the allocated memory buffer.
1588 CopyMem (AllocatedOutputBuffer
, *OutputBuffer
, OutputBufferSize
);
1589 *OutputBuffer
= AllocatedOutputBuffer
;
1593 // Set real size of output buffer.
1595 *OutputSize
= (UINTN
) OutputBufferSize
;
1598 // Free unused scratch buffer.
1600 if (ScratchBuffer
!= NULL
) {
1601 CoreFreePool (ScratchBuffer
);