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 - 2012, 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 RPN callback function. Initializes the section stream
495 when GUIDED_SECTION_EXTRACTION_PROTOCOL is installed.
497 @param Event The event that fired
498 @param RpnContext A pointer to the context that allows us to identify
499 the relevent encapsulation.
503 NotifyGuidedExtraction (
509 EFI_GUID_DEFINED_SECTION
*GuidedHeader
;
510 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*GuidedExtraction
;
511 VOID
*NewStreamBuffer
;
512 UINTN NewStreamBufferSize
;
513 UINT32 AuthenticationStatus
;
514 RPN_EVENT_CONTEXT
*Context
;
516 Context
= RpnContext
;
518 GuidedHeader
= (EFI_GUID_DEFINED_SECTION
*) (Context
->ParentStream
->StreamBuffer
+ Context
->ChildNode
->OffsetInStream
);
519 ASSERT (GuidedHeader
->CommonHeader
.Type
== EFI_SECTION_GUID_DEFINED
);
521 Status
= gBS
->LocateProtocol (Context
->ChildNode
->EncapsulationGuid
, NULL
, (VOID
**)&GuidedExtraction
);
522 if (EFI_ERROR (Status
)) {
526 Status
= GuidedExtraction
->ExtractSection (
530 &NewStreamBufferSize
,
531 &AuthenticationStatus
533 ASSERT_EFI_ERROR (Status
);
536 // Make sure we initialize the new stream with the correct
537 // authentication status for both aggregate and local status fields.
539 if ((GuidedHeader
->Attributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
541 // OR in the parent stream's aggregate status.
543 AuthenticationStatus
|= Context
->ParentStream
->AuthenticationStatus
& EFI_AUTH_STATUS_ALL
;
546 // since there's no authentication data contributed by the section,
547 // just inherit the full value from our immediate parent.
549 AuthenticationStatus
= Context
->ParentStream
->AuthenticationStatus
;
552 Status
= OpenSectionStreamEx (
556 AuthenticationStatus
,
557 &Context
->ChildNode
->EncapsulatedStreamHandle
559 ASSERT_EFI_ERROR (Status
);
562 // Close the event when done.
564 gBS
->CloseEvent (Event
);
565 Context
->ChildNode
->Event
= NULL
;
570 Constructor for RPN event when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...
572 @param ParentStream Indicates the parent of the ecnapsulation section (child)
573 @param ChildNode Indicates the child node that is the encapsulation section.
577 CreateGuidedExtractionRpnEvent (
578 IN CORE_SECTION_STREAM_NODE
*ParentStream
,
579 IN CORE_SECTION_CHILD_NODE
*ChildNode
582 RPN_EVENT_CONTEXT
*Context
;
585 // Allocate new event structure and context
587 Context
= AllocatePool (sizeof (RPN_EVENT_CONTEXT
));
588 ASSERT (Context
!= NULL
);
590 Context
->ChildNode
= ChildNode
;
591 Context
->ParentStream
= ParentStream
;
593 Context
->ChildNode
->Event
= EfiCreateProtocolNotifyEvent (
594 Context
->ChildNode
->EncapsulationGuid
,
596 NotifyGuidedExtraction
,
598 &Context
->Registration
603 Worker function. Constructor for new child nodes.
605 @param Stream Indicates the section stream in which to add the
607 @param ChildOffset Indicates the offset in Stream that is the
608 beginning of the child section.
609 @param ChildNode Indicates the Callee allocated and initialized
612 @retval EFI_SUCCESS Child node was found and returned.
613 EFI_OUT_OF_RESOURCES- Memory allocation failed.
614 @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream
615 handles when the child node is created. If the
616 section type is GUID defined, and the extraction
617 GUID does not exist, and producing the stream
618 requires the GUID, then a protocol error is
619 generated and no child is produced. Values
620 returned by OpenSectionStreamEx.
625 IN CORE_SECTION_STREAM_NODE
*Stream
,
626 IN UINT32 ChildOffset
,
627 OUT CORE_SECTION_CHILD_NODE
**ChildNode
631 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
632 EFI_COMPRESSION_SECTION
*CompressionHeader
;
633 EFI_GUID_DEFINED_SECTION
*GuidedHeader
;
634 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
635 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*GuidedExtraction
;
636 VOID
*NewStreamBuffer
;
639 UINTN NewStreamBufferSize
;
640 UINT32 AuthenticationStatus
;
641 VOID
*CompressionSource
;
642 UINT32 CompressionSourceSize
;
643 UINT32 UncompressedLength
;
644 UINT8 CompressionType
;
645 UINT16 GuidedSectionAttributes
;
647 CORE_SECTION_CHILD_NODE
*Node
;
649 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) (Stream
->StreamBuffer
+ ChildOffset
);
652 // Allocate a new node
654 *ChildNode
= AllocateZeroPool (sizeof (CORE_SECTION_CHILD_NODE
));
657 return EFI_OUT_OF_RESOURCES
;
663 Node
->Signature
= CORE_SECTION_CHILD_SIGNATURE
;
664 Node
->Type
= SectionHeader
->Type
;
665 if (IS_SECTION2 (SectionHeader
)) {
666 Node
->Size
= SECTION2_SIZE (SectionHeader
);
668 Node
->Size
= SECTION_SIZE (SectionHeader
);
670 Node
->OffsetInStream
= ChildOffset
;
671 Node
->EncapsulatedStreamHandle
= NULL_STREAM_HANDLE
;
672 Node
->EncapsulationGuid
= NULL
;
675 // If it's an encapsulating section, then create the new section stream also
677 switch (Node
->Type
) {
678 case EFI_SECTION_COMPRESSION
:
680 // Get the CompressionSectionHeader
682 if (Node
->Size
< sizeof (EFI_COMPRESSION_SECTION
)) {
684 return EFI_NOT_FOUND
;
687 CompressionHeader
= (EFI_COMPRESSION_SECTION
*) SectionHeader
;
689 if (IS_SECTION2 (CompressionHeader
)) {
690 CompressionSource
= (VOID
*) ((UINT8
*) CompressionHeader
+ sizeof (EFI_COMPRESSION_SECTION2
));
691 CompressionSourceSize
= (UINT32
) (SECTION2_SIZE (CompressionHeader
) - sizeof (EFI_COMPRESSION_SECTION2
));
692 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*) CompressionHeader
)->UncompressedLength
;
693 CompressionType
= ((EFI_COMPRESSION_SECTION2
*) CompressionHeader
)->CompressionType
;
695 CompressionSource
= (VOID
*) ((UINT8
*) CompressionHeader
+ sizeof (EFI_COMPRESSION_SECTION
));
696 CompressionSourceSize
= (UINT32
) (SECTION_SIZE (CompressionHeader
) - sizeof (EFI_COMPRESSION_SECTION
));
697 UncompressedLength
= CompressionHeader
->UncompressedLength
;
698 CompressionType
= CompressionHeader
->CompressionType
;
702 // Allocate space for the new stream
704 if (UncompressedLength
> 0) {
705 NewStreamBufferSize
= UncompressedLength
;
706 NewStreamBuffer
= AllocatePool (NewStreamBufferSize
);
707 if (NewStreamBuffer
== NULL
) {
709 return EFI_OUT_OF_RESOURCES
;
712 if (CompressionType
== EFI_NOT_COMPRESSED
) {
714 // stream is not actually compressed, just encapsulated. So just copy it.
716 CopyMem (NewStreamBuffer
, CompressionSource
, NewStreamBufferSize
);
717 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
719 // Only support the EFI_SATNDARD_COMPRESSION algorithm.
723 // Decompress the stream
725 Status
= CoreLocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**)&Decompress
);
726 ASSERT_EFI_ERROR (Status
);
727 ASSERT (Decompress
!= NULL
);
729 Status
= Decompress
->GetInfo (
732 CompressionSourceSize
,
733 (UINT32
*)&NewStreamBufferSize
,
736 if (EFI_ERROR (Status
) || (NewStreamBufferSize
!= UncompressedLength
)) {
738 CoreFreePool (NewStreamBuffer
);
739 if (!EFI_ERROR (Status
)) {
740 Status
= EFI_BAD_BUFFER_SIZE
;
745 ScratchBuffer
= AllocatePool (ScratchSize
);
746 if (ScratchBuffer
== NULL
) {
748 CoreFreePool (NewStreamBuffer
);
749 return EFI_OUT_OF_RESOURCES
;
752 Status
= Decompress
->Decompress (
755 CompressionSourceSize
,
757 (UINT32
)NewStreamBufferSize
,
761 CoreFreePool (ScratchBuffer
);
762 if (EFI_ERROR (Status
)) {
764 CoreFreePool (NewStreamBuffer
);
769 NewStreamBuffer
= NULL
;
770 NewStreamBufferSize
= 0;
773 Status
= OpenSectionStreamEx (
777 Stream
->AuthenticationStatus
,
778 &Node
->EncapsulatedStreamHandle
780 if (EFI_ERROR (Status
)) {
782 CoreFreePool (NewStreamBuffer
);
787 case EFI_SECTION_GUID_DEFINED
:
788 GuidedHeader
= (EFI_GUID_DEFINED_SECTION
*) SectionHeader
;
789 if (IS_SECTION2 (GuidedHeader
)) {
790 Node
->EncapsulationGuid
= &(((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->SectionDefinitionGuid
);
791 GuidedSectionAttributes
= ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->Attributes
;
793 Node
->EncapsulationGuid
= &GuidedHeader
->SectionDefinitionGuid
;
794 GuidedSectionAttributes
= GuidedHeader
->Attributes
;
796 Status
= CoreLocateProtocol (Node
->EncapsulationGuid
, NULL
, (VOID
**)&GuidedExtraction
);
797 if (!EFI_ERROR (Status
) && GuidedExtraction
!= NULL
) {
799 // NewStreamBuffer is always allocated by ExtractSection... No caller
802 Status
= GuidedExtraction
->ExtractSection (
806 &NewStreamBufferSize
,
807 &AuthenticationStatus
809 if (EFI_ERROR (Status
)) {
810 CoreFreePool (*ChildNode
);
811 return EFI_PROTOCOL_ERROR
;
815 // Make sure we initialize the new stream with the correct
816 // authentication status for both aggregate and local status fields.
818 if ((GuidedSectionAttributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
820 // OR in the parent stream's aggregate status.
822 AuthenticationStatus
|= Stream
->AuthenticationStatus
& EFI_AUTH_STATUS_ALL
;
825 // since there's no authentication data contributed by the section,
826 // just inherit the full value from our immediate parent.
828 AuthenticationStatus
= Stream
->AuthenticationStatus
;
831 Status
= OpenSectionStreamEx (
835 AuthenticationStatus
,
836 &Node
->EncapsulatedStreamHandle
838 if (EFI_ERROR (Status
)) {
839 CoreFreePool (*ChildNode
);
840 CoreFreePool (NewStreamBuffer
);
845 // There's no GUIDed section extraction protocol available.
847 if ((GuidedSectionAttributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
849 // If the section REQUIRES an extraction protocol, register for RPN
850 // when the required GUIDed extraction protocol becomes available.
852 CreateGuidedExtractionRpnEvent (Stream
, Node
);
855 // Figure out the proper authentication status
857 AuthenticationStatus
= Stream
->AuthenticationStatus
;
859 if (IS_SECTION2 (GuidedHeader
)) {
860 Status
= OpenSectionStreamEx (
861 SECTION2_SIZE (GuidedHeader
) - ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->DataOffset
,
862 (UINT8
*) GuidedHeader
+ ((EFI_GUID_DEFINED_SECTION2
*) GuidedHeader
)->DataOffset
,
864 AuthenticationStatus
,
865 &Node
->EncapsulatedStreamHandle
868 Status
= OpenSectionStreamEx (
869 SECTION_SIZE (GuidedHeader
) - ((EFI_GUID_DEFINED_SECTION
*) GuidedHeader
)->DataOffset
,
870 (UINT8
*) GuidedHeader
+ ((EFI_GUID_DEFINED_SECTION
*) GuidedHeader
)->DataOffset
,
872 AuthenticationStatus
,
873 &Node
->EncapsulatedStreamHandle
876 if (EFI_ERROR (Status
)) {
888 // Nothing to do if it's a leaf
894 // Last, add the new child node to the stream
896 InsertTailList (&Stream
->Children
, &Node
->Link
);
903 Worker function Recursively searches / builds section stream database
904 looking for requested section.
906 @param SourceStream Indicates the section stream in which to do the
908 @param SearchType Indicates the type of section to search for.
909 @param SectionInstance Indicates which instance of section to find.
910 This is an in/out parameter to deal with
912 @param SectionDefinitionGuid Guid of section definition
913 @param FoundChild Output indicating the child node that is found.
914 @param FoundStream Output indicating which section stream the child
915 was found in. If this stream was generated as a
916 result of an encapsulation section, the
917 streamhandle is visible within the SEP driver
919 @param AuthenticationStatus Indicates the authentication status of the found section.
921 @retval EFI_SUCCESS Child node was found and returned.
922 EFI_OUT_OF_RESOURCES- Memory allocation failed.
923 @retval EFI_NOT_FOUND Requested child node does not exist.
924 @retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol
930 IN CORE_SECTION_STREAM_NODE
*SourceStream
,
931 IN EFI_SECTION_TYPE SearchType
,
932 IN OUT UINTN
*SectionInstance
,
933 IN EFI_GUID
*SectionDefinitionGuid
,
934 OUT CORE_SECTION_CHILD_NODE
**FoundChild
,
935 OUT CORE_SECTION_STREAM_NODE
**FoundStream
,
936 OUT UINT32
*AuthenticationStatus
939 CORE_SECTION_CHILD_NODE
*CurrentChildNode
;
940 CORE_SECTION_CHILD_NODE
*RecursedChildNode
;
941 CORE_SECTION_STREAM_NODE
*RecursedFoundStream
;
942 UINT32 NextChildOffset
;
943 EFI_STATUS ErrorStatus
;
946 CurrentChildNode
= NULL
;
947 ErrorStatus
= EFI_NOT_FOUND
;
949 if (SourceStream
->StreamLength
== 0) {
950 return EFI_NOT_FOUND
;
953 if (IsListEmpty (&SourceStream
->Children
) &&
954 SourceStream
->StreamLength
>= sizeof (EFI_COMMON_SECTION_HEADER
)) {
956 // This occurs when a section stream exists, but no child sections
957 // have been parsed out yet. Therefore, extract the first child and add it
958 // to the list of children so we can get started.
959 // Section stream may contain an array of zero or more bytes.
960 // So, its size should be >= the size of commen section header.
962 Status
= CreateChildNode (SourceStream
, 0, &CurrentChildNode
);
963 if (EFI_ERROR (Status
)) {
969 // At least one child has been parsed out of the section stream. So, walk
970 // through the sections that have already been parsed out looking for the
971 // requested section, if necessary, continue parsing section stream and
972 // adding children until either the requested section is found, or we run
975 CurrentChildNode
= CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream
->Children
));
978 ASSERT (CurrentChildNode
!= NULL
);
979 if (ChildIsType (SourceStream
, CurrentChildNode
, SearchType
, SectionDefinitionGuid
)) {
981 // The type matches, so check the instance count to see if it's the one we want
983 (*SectionInstance
)--;
984 if (*SectionInstance
== 0) {
988 *FoundChild
= CurrentChildNode
;
989 *FoundStream
= SourceStream
;
990 *AuthenticationStatus
= SourceStream
->AuthenticationStatus
;
995 if (CurrentChildNode
->EncapsulatedStreamHandle
!= NULL_STREAM_HANDLE
) {
997 // If the current node is an encapsulating node, recurse into it...
999 Status
= FindChildNode (
1000 (CORE_SECTION_STREAM_NODE
*)CurrentChildNode
->EncapsulatedStreamHandle
,
1003 SectionDefinitionGuid
,
1005 &RecursedFoundStream
,
1006 AuthenticationStatus
1009 // If the status is not EFI_SUCCESS, just save the error code and continue
1010 // to find the request child node in the rest stream.
1012 if (*SectionInstance
== 0) {
1013 ASSERT_EFI_ERROR (Status
);
1014 *FoundChild
= RecursedChildNode
;
1015 *FoundStream
= RecursedFoundStream
;
1018 ErrorStatus
= Status
;
1020 } else if ((CurrentChildNode
->Type
== EFI_SECTION_GUID_DEFINED
) && (SearchType
!= EFI_SECTION_GUID_DEFINED
)) {
1022 // When Node Type is GUIDED section, but Node has no encapsulated data, Node data should not be parsed
1023 // because a required GUIDED section extraction protocol does not exist.
1024 // If SearchType is not GUIDED section, EFI_PROTOCOL_ERROR should return.
1026 ErrorStatus
= EFI_PROTOCOL_ERROR
;
1029 if (!IsNodeAtEnd (&SourceStream
->Children
, &CurrentChildNode
->Link
)) {
1031 // We haven't found the child node we're interested in yet, but there's
1032 // still more nodes that have already been parsed so get the next one
1033 // and continue searching..
1035 CurrentChildNode
= CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream
->Children
, &CurrentChildNode
->Link
));
1038 // We've exhausted children that have already been parsed, so see if
1039 // there's any more data and continue parsing out more children if there
1042 NextChildOffset
= CurrentChildNode
->OffsetInStream
+ CurrentChildNode
->Size
;
1044 // Round up to 4 byte boundary
1046 NextChildOffset
+= 3;
1047 NextChildOffset
&= ~(UINTN
) 3;
1048 if (NextChildOffset
<= SourceStream
->StreamLength
- sizeof (EFI_COMMON_SECTION_HEADER
)) {
1050 // There's an unparsed child remaining in the stream, so create a new child node
1052 Status
= CreateChildNode (SourceStream
, NextChildOffset
, &CurrentChildNode
);
1053 if (EFI_ERROR (Status
)) {
1057 ASSERT (EFI_ERROR (ErrorStatus
));
1066 Worker function. Search stream database for requested stream handle.
1068 @param SearchHandle Indicates which stream to look for.
1069 @param FoundStream Output pointer to the found stream.
1071 @retval EFI_SUCCESS StreamHandle was found and *FoundStream contains
1073 @retval EFI_NOT_FOUND SearchHandle was not found in the stream
1079 IN UINTN SearchHandle
,
1080 OUT CORE_SECTION_STREAM_NODE
**FoundStream
1083 CORE_SECTION_STREAM_NODE
*StreamNode
;
1085 if (!IsListEmpty (&mStreamRoot
)) {
1086 StreamNode
= STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot
));
1088 if (StreamNode
->StreamHandle
== SearchHandle
) {
1089 *FoundStream
= StreamNode
;
1091 } else if (IsNodeAtEnd (&mStreamRoot
, &StreamNode
->Link
)) {
1094 StreamNode
= STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot
, &StreamNode
->Link
));
1099 return EFI_NOT_FOUND
;
1104 SEP member function. Retrieves requested section from section stream.
1106 @param SectionStreamHandle The section stream from which to extract the
1108 @param SectionType A pointer to the type of section to search for.
1109 @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED,
1110 then SectionDefinitionGuid indicates which of
1111 these types of sections to search for.
1112 @param SectionInstance Indicates which instance of the requested
1114 @param Buffer Double indirection to buffer. If *Buffer is
1115 non-null on input, then the buffer is caller
1116 allocated. If Buffer is NULL, then the buffer
1117 is callee allocated. In either case, the
1118 requried buffer size is returned in *BufferSize.
1119 @param BufferSize On input, indicates the size of *Buffer if
1120 *Buffer is non-null on input. On output,
1121 indicates the required size (allocated size if
1122 callee allocated) of *Buffer.
1123 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
1124 indicates the authentication status of the
1125 output buffer. If the input section's
1126 GuidedSectionHeader.Attributes field
1127 has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID
1128 bit as clear, AuthenticationStatus must return
1129 zero. Both local bits (19:16) and aggregate
1130 bits (3:0) in AuthenticationStatus are returned
1131 by ExtractSection(). These bits reflect the
1132 status of the extraction operation. The bit
1133 pattern in both regions must be the same, as
1134 the local and aggregate authentication statuses
1135 have equivalent meaning at this level. If the
1136 function returns anything other than
1137 EFI_SUCCESS, the value of *AuthenticationStatus
1139 @param IsFfs3Fv Indicates the FV format.
1141 @retval EFI_SUCCESS Section was retrieved successfully
1142 @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the
1143 section stream with its
1144 EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set,
1145 but there was no corresponding GUIDed Section
1146 Extraction Protocol in the handle database.
1147 *Buffer is unmodified.
1148 @retval EFI_NOT_FOUND An error was encountered when parsing the
1149 SectionStream. This indicates the SectionStream
1150 is not correctly formatted.
1151 @retval EFI_NOT_FOUND The requested section does not exist.
1152 @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process
1154 @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist.
1155 @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is
1156 insufficient to contain the requested section.
1157 The input buffer is filled and section contents
1164 IN UINTN SectionStreamHandle
,
1165 IN EFI_SECTION_TYPE
*SectionType
,
1166 IN EFI_GUID
*SectionDefinitionGuid
,
1167 IN UINTN SectionInstance
,
1169 IN OUT UINTN
*BufferSize
,
1170 OUT UINT32
*AuthenticationStatus
,
1174 CORE_SECTION_STREAM_NODE
*StreamNode
;
1177 CORE_SECTION_CHILD_NODE
*ChildNode
;
1178 CORE_SECTION_STREAM_NODE
*ChildStreamNode
;
1180 UINT32 ExtractedAuthenticationStatus
;
1184 EFI_COMMON_SECTION_HEADER
*Section
;
1187 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1188 Instance
= SectionInstance
+ 1;
1191 // Locate target stream
1193 Status
= FindStreamNode (SectionStreamHandle
, &StreamNode
);
1194 if (EFI_ERROR (Status
)) {
1195 Status
= EFI_INVALID_PARAMETER
;
1196 goto GetSection_Done
;
1200 // Found the stream, now locate and return the appropriate section
1202 if (SectionType
== NULL
) {
1204 // SectionType == NULL means return the WHOLE section stream...
1206 CopySize
= StreamNode
->StreamLength
;
1207 CopyBuffer
= StreamNode
->StreamBuffer
;
1208 *AuthenticationStatus
= StreamNode
->AuthenticationStatus
;
1211 // There's a requested section type, so go find it and return it...
1213 Status
= FindChildNode (
1217 SectionDefinitionGuid
,
1220 &ExtractedAuthenticationStatus
1222 if (EFI_ERROR (Status
)) {
1223 goto GetSection_Done
;
1226 Section
= (EFI_COMMON_SECTION_HEADER
*) (ChildStreamNode
->StreamBuffer
+ ChildNode
->OffsetInStream
);
1228 if (IS_SECTION2 (Section
)) {
1229 ASSERT (SECTION2_SIZE (Section
) > 0x00FFFFFF);
1231 DEBUG ((DEBUG_ERROR
, "It is a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
1232 Status
= EFI_NOT_FOUND
;
1233 goto GetSection_Done
;
1235 CopySize
= SECTION2_SIZE (Section
) - sizeof (EFI_COMMON_SECTION_HEADER2
);
1236 CopyBuffer
= (UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER2
);
1238 CopySize
= SECTION_SIZE (Section
) - sizeof (EFI_COMMON_SECTION_HEADER
);
1239 CopyBuffer
= (UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER
);
1241 *AuthenticationStatus
= ExtractedAuthenticationStatus
;
1244 SectionSize
= CopySize
;
1245 if (*Buffer
!= NULL
) {
1247 // Caller allocated buffer. Fill to size and return required size...
1249 if (*BufferSize
< CopySize
) {
1250 Status
= EFI_WARN_BUFFER_TOO_SMALL
;
1251 CopySize
= *BufferSize
;
1255 // Callee allocated buffer. Allocate buffer and return size.
1257 *Buffer
= AllocatePool (CopySize
);
1258 if (*Buffer
== NULL
) {
1259 Status
= EFI_OUT_OF_RESOURCES
;
1260 goto GetSection_Done
;
1263 CopyMem (*Buffer
, CopyBuffer
, CopySize
);
1264 *BufferSize
= SectionSize
;
1267 CoreRestoreTpl (OldTpl
);
1274 Worker function. Destructor for child nodes.
1276 @param ChildNode Indicates the node to destroy
1281 IN CORE_SECTION_CHILD_NODE
*ChildNode
1284 ASSERT (ChildNode
->Signature
== CORE_SECTION_CHILD_SIGNATURE
);
1286 // Remove the child from it's list
1288 RemoveEntryList (&ChildNode
->Link
);
1290 if (ChildNode
->EncapsulatedStreamHandle
!= NULL_STREAM_HANDLE
) {
1292 // If it's an encapsulating section, we close the resulting section stream.
1293 // CloseSectionStream will free all memory associated with the stream.
1295 CloseSectionStream (ChildNode
->EncapsulatedStreamHandle
);
1298 if (ChildNode
->Event
!= NULL
) {
1299 gBS
->CloseEvent (ChildNode
->Event
);
1303 // Last, free the child node itself
1305 CoreFreePool (ChildNode
);
1310 SEP member function. Deletes an existing section stream
1312 @param StreamHandleToClose Indicates the stream to close
1314 @retval EFI_SUCCESS The section stream is closed sucessfully.
1315 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1316 @retval EFI_INVALID_PARAMETER Section stream does not end concident with end
1322 CloseSectionStream (
1323 IN UINTN StreamHandleToClose
1326 CORE_SECTION_STREAM_NODE
*StreamNode
;
1330 CORE_SECTION_CHILD_NODE
*ChildNode
;
1332 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1335 // Locate target stream
1337 Status
= FindStreamNode (StreamHandleToClose
, &StreamNode
);
1338 if (!EFI_ERROR (Status
)) {
1340 // Found the stream, so close it
1342 RemoveEntryList (&StreamNode
->Link
);
1343 while (!IsListEmpty (&StreamNode
->Children
)) {
1344 Link
= GetFirstNode (&StreamNode
->Children
);
1345 ChildNode
= CHILD_SECTION_NODE_FROM_LINK (Link
);
1346 FreeChildNode (ChildNode
);
1348 CoreFreePool (StreamNode
->StreamBuffer
);
1349 CoreFreePool (StreamNode
);
1350 Status
= EFI_SUCCESS
;
1352 Status
= EFI_INVALID_PARAMETER
;
1355 CoreRestoreTpl (OldTpl
);
1361 The ExtractSection() function processes the input section and
1362 allocates a buffer from the pool in which it returns the section
1363 contents. If the section being extracted contains
1364 authentication information (the section's
1365 GuidedSectionHeader.Attributes field has the
1366 EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
1367 returned in AuthenticationStatus must reflect the results of
1368 the authentication operation. Depending on the algorithm and
1369 size of the encapsulated data, the time that is required to do
1370 a full authentication may be prohibitively long for some
1371 classes of systems. To indicate this, use
1372 EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
1373 the security policy driver (see the Platform Initialization
1374 Driver Execution Environment Core Interface Specification for
1375 more details and the GUID definition). If the
1376 EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
1377 database, then, if possible, full authentication should be
1378 skipped and the section contents simply returned in the
1379 OutputBuffer. In this case, the
1380 EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
1381 must be set on return. ExtractSection() is callable only from
1382 TPL_NOTIFY and below. Behavior of ExtractSection() at any
1383 EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
1384 defined in RaiseTPL() in the UEFI 2.0 specification.
1387 @param This Indicates the
1388 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
1389 @param InputSection Buffer containing the input GUIDed section
1390 to be processed. OutputBuffer OutputBuffer
1391 is allocated from boot services pool
1392 memory and contains the new section
1393 stream. The caller is responsible for
1394 freeing this buffer.
1395 @param OutputBuffer *OutputBuffer is allocated from boot services
1396 pool memory and contains the new section stream.
1397 The caller is responsible for freeing this buffer.
1398 @param OutputSize A pointer to a caller-allocated UINTN in
1399 which the size of OutputBuffer allocation
1400 is stored. If the function returns
1401 anything other than EFI_SUCCESS, the value
1402 of OutputSize is undefined.
1404 @param AuthenticationStatus A pointer to a caller-allocated
1405 UINT32 that indicates the
1406 authentication status of the
1407 output buffer. If the input
1409 GuidedSectionHeader.Attributes
1411 EFI_GUIDED_SECTION_AUTH_STATUS_VAL
1412 bit as clear, AuthenticationStatus
1413 must return zero. Both local bits
1414 (19:16) and aggregate bits (3:0)
1415 in AuthenticationStatus are
1416 returned by ExtractSection().
1417 These bits reflect the status of
1418 the extraction operation. The bit
1419 pattern in both regions must be
1420 the same, as the local and
1421 aggregate authentication statuses
1422 have equivalent meaning at this
1423 level. If the function returns
1424 anything other than EFI_SUCCESS,
1425 the value of AuthenticationStatus
1429 @retval EFI_SUCCESS The InputSection was successfully
1430 processed and the section contents were
1433 @retval EFI_OUT_OF_RESOURCES The system has insufficient
1434 resources to process the
1437 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
1438 not match this instance of the
1439 GUIDed Section Extraction
1445 CustomGuidedSectionExtract (
1446 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*This
,
1447 IN CONST VOID
*InputSection
,
1448 OUT VOID
**OutputBuffer
,
1449 OUT UINTN
*OutputSize
,
1450 OUT UINT32
*AuthenticationStatus
1454 VOID
*ScratchBuffer
;
1455 VOID
*AllocatedOutputBuffer
;
1456 UINT32 OutputBufferSize
;
1457 UINT32 ScratchBufferSize
;
1458 UINT16 SectionAttribute
;
1461 // Init local variable
1463 ScratchBuffer
= NULL
;
1464 AllocatedOutputBuffer
= NULL
;
1467 // Call GetInfo to get the size and attribute of input guided section data.
1469 Status
= ExtractGuidedSectionGetInfo (
1476 if (EFI_ERROR (Status
)) {
1477 DEBUG ((DEBUG_ERROR
, "GetInfo from guided section Failed - %r\n", Status
));
1481 if (ScratchBufferSize
> 0) {
1483 // Allocate scratch buffer
1485 ScratchBuffer
= AllocatePool (ScratchBufferSize
);
1486 if (ScratchBuffer
== NULL
) {
1487 return EFI_OUT_OF_RESOURCES
;
1491 if (OutputBufferSize
> 0) {
1493 // Allocate output buffer
1495 AllocatedOutputBuffer
= AllocatePool (OutputBufferSize
);
1496 if (AllocatedOutputBuffer
== NULL
) {
1497 FreePool (ScratchBuffer
);
1498 return EFI_OUT_OF_RESOURCES
;
1500 *OutputBuffer
= AllocatedOutputBuffer
;
1504 // Call decode function to extract raw data from the guided section.
1506 Status
= ExtractGuidedSectionDecode (
1510 AuthenticationStatus
1512 if (EFI_ERROR (Status
)) {
1516 if (AllocatedOutputBuffer
!= NULL
) {
1517 CoreFreePool (AllocatedOutputBuffer
);
1519 if (ScratchBuffer
!= NULL
) {
1520 CoreFreePool (ScratchBuffer
);
1522 DEBUG ((DEBUG_ERROR
, "Extract guided section Failed - %r\n", Status
));
1526 if (*OutputBuffer
!= AllocatedOutputBuffer
) {
1528 // OutputBuffer was returned as a different value,
1529 // so copy section contents to the allocated memory buffer.
1531 CopyMem (AllocatedOutputBuffer
, *OutputBuffer
, OutputBufferSize
);
1532 *OutputBuffer
= AllocatedOutputBuffer
;
1536 // Set real size of output buffer.
1538 *OutputSize
= (UINTN
) OutputBufferSize
;
1541 // Free unused scratch buffer.
1543 if (ScratchBuffer
!= NULL
) {
1544 CoreFreePool (ScratchBuffer
);