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 - 2008, Intel Corporation. <BR>
31 All rights reserved. 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 EFI_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
;
69 } CORE_SECTION_CHILD_NODE
;
71 #define CORE_SECTION_STREAM_SIGNATURE EFI_SIGNATURE_32('S','X','S','S')
72 #define STREAM_NODE_FROM_LINK(Node) \
73 CR (Node, CORE_SECTION_STREAM_NODE, Link, CORE_SECTION_STREAM_SIGNATURE)
83 // Authentication status is from GUIDed encapsulations.
85 UINT32 AuthenticationStatus
;
86 } CORE_SECTION_STREAM_NODE
;
88 #define NULL_STREAM_HANDLE 0
91 CORE_SECTION_CHILD_NODE
*ChildNode
;
92 CORE_SECTION_STREAM_NODE
*ParentStream
;
104 Worker function. Determine if the input stream:child matches the input type.
106 @param Stream Indicates the section stream associated with the
108 @param Child Indicates the child to check
109 @param SearchType Indicates the type of section to check against
111 @param SectionDefinitionGuid Indicates the GUID to check against if the type
112 is EFI_SECTION_GUID_DEFINED
114 @retval TRUE The child matches
115 @retval FALSE The child doesn't match
120 IN CORE_SECTION_STREAM_NODE
*Stream
,
121 IN CORE_SECTION_CHILD_NODE
*Child
,
122 IN EFI_SECTION_TYPE SearchType
,
123 IN EFI_GUID
*SectionDefinitionGuid
128 RPN callback function. Removes a stale section stream and re-initializes it
129 with an updated AuthenticationStatus.
131 @param Event The event that fired
132 @param RpnContext A pointer to the context that allows us to
133 identify the relevent encapsulation...
138 NotifyGuidedExtraction (
146 Worker function. Constructor for RPN event if needed to keep AuthenticationStatus
147 cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...
149 @param ParentStream Indicates the parent of the ecnapsulation
151 @param ChildNode Indicates the child node that is the
152 encapsulation section.
156 CreateGuidedExtractionRpnEvent (
157 IN CORE_SECTION_STREAM_NODE
*ParentStream
,
158 IN CORE_SECTION_CHILD_NODE
*ChildNode
163 Worker function. Search stream database for requested stream handle.
165 @param SearchHandle Indicates which stream to look for.
166 @param FoundStream Output pointer to the found stream.
168 @retval EFI_SUCCESS StreamHandle was found and *FoundStream contains
170 @retval EFI_NOT_FOUND SearchHandle was not found in the stream
176 IN UINTN SearchHandle
,
177 OUT CORE_SECTION_STREAM_NODE
**FoundStream
181 Worker function Recursively searches / builds section stream database
182 looking for requested section.
184 @param SourceStream Indicates the section stream in which to do the
186 @param SearchType Indicates the type of section to search for.
187 @param SectionInstance Indicates which instance of section to find.
188 This is an in/out parameter to deal with
190 @param SectionDefinitionGuid Guid of section definition
191 @param FoundChild Output indicating the child node that is found.
192 @param FoundStream Output indicating which section stream the child
193 was found in. If this stream was generated as a
194 result of an encapsulation section, the
195 streamhandle is visible within the SEP driver
197 @param AuthenticationStatus Indicates the authentication status of the found section.
199 @retval EFI_SUCCESS Child node was found and returned.
200 EFI_OUT_OF_RESOURCES- Memory allocation failed.
201 @retval EFI_NOT_FOUND Requested child node does not exist.
202 @retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol
208 IN CORE_SECTION_STREAM_NODE
*SourceStream
,
209 IN EFI_SECTION_TYPE SearchType
,
210 IN OUT UINTN
*SectionInstance
,
211 IN EFI_GUID
*SectionDefinitionGuid
,
212 OUT CORE_SECTION_CHILD_NODE
**FoundChild
,
213 OUT CORE_SECTION_STREAM_NODE
**FoundStream
,
214 OUT UINT32
*AuthenticationStatus
218 Worker function. Constructor for new child nodes.
220 @param Stream Indicates the section stream in which to add the
222 @param ChildOffset Indicates the offset in Stream that is the
223 beginning of the child section.
224 @param ChildNode Indicates the Callee allocated and initialized
227 @retval EFI_SUCCESS Child node was found and returned.
228 EFI_OUT_OF_RESOURCES- Memory allocation failed.
229 @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream
230 handles when the child node is created. If the
231 section type is GUID defined, and the extraction
232 GUID does not exist, and producing the stream
233 requires the GUID, then a protocol error is
234 generated and no child is produced. Values
235 returned by OpenSectionStreamEx.
240 IN CORE_SECTION_STREAM_NODE
*Stream
,
241 IN UINT32 ChildOffset
,
242 OUT CORE_SECTION_CHILD_NODE
**ChildNode
246 Worker function. Destructor for child nodes.
248 @param ChildNode Indicates the node to destroy
253 IN CORE_SECTION_CHILD_NODE
*ChildNode
257 Worker function. Constructor for section streams.
259 @param SectionStreamLength Size in bytes of the section stream.
260 @param SectionStream Buffer containing the new section stream.
261 @param AllocateBuffer Indicates whether the stream buffer is to be
262 copied or the input buffer is to be used in
263 place. AuthenticationStatus- Indicates the
264 default authentication status for the new
266 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
267 indicates the authentication status of the
268 output buffer. If the input section's
269 GuidedSectionHeader.Attributes field
270 has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID
271 bit as clear, AuthenticationStatus must return
272 zero. Both local bits (19:16) and aggregate
273 bits (3:0) in AuthenticationStatus are returned
274 by ExtractSection(). These bits reflect the
275 status of the extraction operation. The bit
276 pattern in both regions must be the same, as
277 the local and aggregate authentication statuses
278 have equivalent meaning at this level. If the
279 function returns anything other than
280 EFI_SUCCESS, the value of *AuthenticationStatus
282 @param SectionStreamHandle A pointer to a caller allocated section stream
285 @retval EFI_SUCCESS Stream was added to stream database.
286 @retval EFI_OUT_OF_RESOURCES memory allocation failed.
290 OpenSectionStreamEx (
291 IN UINTN SectionStreamLength
,
292 IN VOID
*SectionStream
,
293 IN BOOLEAN AllocateBuffer
,
294 IN UINT32 AuthenticationStatus
,
295 OUT UINTN
*SectionStreamHandle
299 Check if a stream is valid.
301 @param SectionStream The section stream to be checked
302 @param SectionStreamLength The length of section stream
304 @return A boolean value indicating the validness of the section stream.
308 IsValidSectionStream (
309 IN VOID
*SectionStream
,
310 IN UINTN SectionStreamLength
314 The ExtractSection() function processes the input section and
315 allocates a buffer from the pool in which it returns the section
316 contents. If the section being extracted contains
317 authentication information (the section's
318 GuidedSectionHeader.Attributes field has the
319 EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
320 returned in AuthenticationStatus must reflect the results of
321 the authentication operation. Depending on the algorithm and
322 size of the encapsulated data, the time that is required to do
323 a full authentication may be prohibitively long for some
324 classes of systems. To indicate this, use
325 EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
326 the security policy driver (see the Platform Initialization
327 Driver Execution Environment Core Interface Specification for
328 more details and the GUID definition). If the
329 EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
330 database, then, if possible, full authentication should be
331 skipped and the section contents simply returned in the
332 OutputBuffer. In this case, the
333 EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
334 must be set on return. ExtractSection() is callable only from
335 TPL_NOTIFY and below. Behavior of ExtractSection() at any
336 EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
337 defined in RaiseTPL() in the UEFI 2.0 specification.
340 @param This Indicates the
341 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
343 @param InputSection Buffer containing the input GUIDed section
344 to be processed. OutputBuffer OutputBuffer
345 is allocated from boot services pool
346 memory and contains the new section
347 stream. The caller is responsible for
349 @param OutputBuffer *OutputBuffer is allocated from boot services
350 pool memory and contains the new section stream.
351 The caller is responsible for freeing this buffer.
352 @param OutputSize A pointer to a caller-allocated UINTN in
353 which the size of OutputBuffer allocation
354 is stored. If the function returns
355 anything other than EFI_SUCCESS, the value
356 of OutputSize is undefined.
358 @param AuthenticationStatus A pointer to a caller-allocated
359 UINT32 that indicates the
360 authentication status of the
361 output buffer. If the input
363 GuidedSectionHeader.Attributes
365 EFI_GUIDED_SECTION_AUTH_STATUS_VAL
366 bit as clear, AuthenticationStatus
367 must return zero. Both local bits
368 (19:16) and aggregate bits (3:0)
369 in AuthenticationStatus are
370 returned by ExtractSection().
371 These bits reflect the status of
372 the extraction operation. The bit
373 pattern in both regions must be
374 the same, as the local and
375 aggregate authentication statuses
376 have equivalent meaning at this
377 level. If the function returns
378 anything other than EFI_SUCCESS,
379 the value of AuthenticationStatus
383 @retval EFI_SUCCESS The InputSection was successfully
384 processed and the section contents were
387 @retval EFI_OUT_OF_RESOURCES The system has insufficient
388 resources to process the
391 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
392 not match this instance of the
393 GUIDed Section Extraction
399 CustomGuidedSectionExtract (
400 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*This
,
401 IN CONST VOID
*InputSection
,
402 OUT VOID
**OutputBuffer
,
403 OUT UINTN
*OutputSize
,
404 OUT UINT32
*AuthenticationStatus
409 LIST_ENTRY mStreamRoot
= INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot
);
411 EFI_HANDLE mSectionExtractionHandle
= NULL
;
413 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL mCustomGuidedSectionExtractionProtocol
= {
414 CustomGuidedSectionExtract
419 Entry point of the section extraction code. Initializes an instance of the
420 section extraction interface and installs it on a new handle.
422 @param ImageHandle A handle for the image that is initializing this driver
423 @param SystemTable A pointer to the EFI system table
425 @retval EFI_SUCCESS Driver initialized successfully
426 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
431 InitializeSectionExtraction (
432 IN EFI_HANDLE ImageHandle
,
433 IN EFI_SYSTEM_TABLE
*SystemTable
437 EFI_GUID
*ExtractHandlerGuidTable
;
438 UINTN ExtractHandlerNumber
;
441 // Get custom extract guided section method guid list
443 ExtractHandlerNumber
= ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable
);
445 Status
= EFI_SUCCESS
;
447 // Install custom guided extraction protocol
449 while (ExtractHandlerNumber
-- > 0) {
450 Status
= CoreInstallProtocolInterface (
451 &mSectionExtractionHandle
,
452 &ExtractHandlerGuidTable
[ExtractHandlerNumber
],
453 EFI_NATIVE_INTERFACE
,
454 &mCustomGuidedSectionExtractionProtocol
456 ASSERT_EFI_ERROR (Status
);
464 SEP member function. This function creates and returns a new section stream
465 handle to represent the new section stream.
467 @param SectionStreamLength Size in bytes of the section stream.
468 @param SectionStream Buffer containing the new section stream.
469 @param SectionStreamHandle A pointer to a caller allocated UINTN that on
470 output contains the new section stream handle.
472 @retval EFI_SUCCESS The section stream is created successfully.
473 @retval EFI_OUT_OF_RESOURCES memory allocation failed.
474 @retval EFI_INVALID_PARAMETER Section stream does not end concident with end
481 IN UINTN SectionStreamLength
,
482 IN VOID
*SectionStream
,
483 OUT UINTN
*SectionStreamHandle
487 // Check to see section stream looks good...
489 if (!IsValidSectionStream (SectionStream
, SectionStreamLength
)) {
490 return EFI_INVALID_PARAMETER
;
493 return OpenSectionStreamEx (
504 SEP member function. Retrieves requested section from section stream.
506 @param SectionStreamHandle The section stream from which to extract the
508 @param SectionType A pointer to the type of section to search for.
509 @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED,
510 then SectionDefinitionGuid indicates which of
511 these types of sections to search for.
512 @param SectionInstance Indicates which instance of the requested
514 @param Buffer Double indirection to buffer. If *Buffer is
515 non-null on input, then the buffer is caller
516 allocated. If Buffer is NULL, then the buffer
517 is callee allocated. In either case, the
518 requried buffer size is returned in *BufferSize.
519 @param BufferSize On input, indicates the size of *Buffer if
520 *Buffer is non-null on input. On output,
521 indicates the required size (allocated size if
522 callee allocated) of *Buffer.
523 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
524 indicates the authentication status of the
525 output buffer. If the input section's
526 GuidedSectionHeader.Attributes field
527 has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID
528 bit as clear, AuthenticationStatus must return
529 zero. Both local bits (19:16) and aggregate
530 bits (3:0) in AuthenticationStatus are returned
531 by ExtractSection(). These bits reflect the
532 status of the extraction operation. The bit
533 pattern in both regions must be the same, as
534 the local and aggregate authentication statuses
535 have equivalent meaning at this level. If the
536 function returns anything other than
537 EFI_SUCCESS, the value of *AuthenticationStatus
540 @retval EFI_SUCCESS Section was retrieved successfully
541 @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the
542 section stream with its
543 EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set,
544 but there was no corresponding GUIDed Section
545 Extraction Protocol in the handle database.
546 *Buffer is unmodified.
547 @retval EFI_NOT_FOUND An error was encountered when parsing the
548 SectionStream. This indicates the SectionStream
549 is not correctly formatted.
550 @retval EFI_NOT_FOUND The requested section does not exist.
551 @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process
553 @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist.
554 @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is
555 insufficient to contain the requested section.
556 The input buffer is filled and section contents
563 IN UINTN SectionStreamHandle
,
564 IN EFI_SECTION_TYPE
*SectionType
,
565 IN EFI_GUID
*SectionDefinitionGuid
,
566 IN UINTN SectionInstance
,
568 IN OUT UINTN
*BufferSize
,
569 OUT UINT32
*AuthenticationStatus
572 CORE_SECTION_STREAM_NODE
*StreamNode
;
575 CORE_SECTION_CHILD_NODE
*ChildNode
;
576 CORE_SECTION_STREAM_NODE
*ChildStreamNode
;
578 UINT32 ExtractedAuthenticationStatus
;
584 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
585 Instance
= SectionInstance
+ 1;
588 // Locate target stream
590 Status
= FindStreamNode (SectionStreamHandle
, &StreamNode
);
591 if (EFI_ERROR (Status
)) {
592 Status
= EFI_INVALID_PARAMETER
;
593 goto GetSection_Done
;
597 // Found the stream, now locate and return the appropriate section
599 if (SectionType
== NULL
) {
601 // SectionType == NULL means return the WHOLE section stream...
603 CopySize
= StreamNode
->StreamLength
;
604 CopyBuffer
= StreamNode
->StreamBuffer
;
605 *AuthenticationStatus
= StreamNode
->AuthenticationStatus
;
608 // There's a requested section type, so go find it and return it...
610 Status
= FindChildNode (
614 SectionDefinitionGuid
,
617 &ExtractedAuthenticationStatus
619 if (EFI_ERROR (Status
)) {
620 goto GetSection_Done
;
622 CopySize
= ChildNode
->Size
- sizeof (EFI_COMMON_SECTION_HEADER
);
623 CopyBuffer
= ChildStreamNode
->StreamBuffer
+ ChildNode
->OffsetInStream
+ sizeof (EFI_COMMON_SECTION_HEADER
);
624 *AuthenticationStatus
= ExtractedAuthenticationStatus
;
627 SectionSize
= CopySize
;
628 if (*Buffer
!= NULL
) {
630 // Caller allocated buffer. Fill to size and return required size...
632 if (*BufferSize
< CopySize
) {
633 Status
= EFI_WARN_BUFFER_TOO_SMALL
;
634 CopySize
= *BufferSize
;
638 // Callee allocated buffer. Allocate buffer and return size.
640 *Buffer
= CoreAllocateBootServicesPool (CopySize
);
641 if (*Buffer
== NULL
) {
642 Status
= EFI_OUT_OF_RESOURCES
;
643 goto GetSection_Done
;
646 CopyMem (*Buffer
, CopyBuffer
, CopySize
);
647 *BufferSize
= SectionSize
;
650 CoreRestoreTpl (OldTpl
);
657 SEP member function. Deletes an existing section stream
659 @param StreamHandleToClose Indicates the stream to close
661 @retval EFI_SUCCESS The section stream is closed sucessfully.
662 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
663 @retval EFI_INVALID_PARAMETER Section stream does not end concident with end
670 IN UINTN StreamHandleToClose
673 CORE_SECTION_STREAM_NODE
*StreamNode
;
677 CORE_SECTION_CHILD_NODE
*ChildNode
;
679 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
682 // Locate target stream
684 Status
= FindStreamNode (StreamHandleToClose
, &StreamNode
);
685 if (!EFI_ERROR (Status
)) {
687 // Found the stream, so close it
689 RemoveEntryList (&StreamNode
->Link
);
690 while (!IsListEmpty (&StreamNode
->Children
)) {
691 Link
= GetFirstNode (&StreamNode
->Children
);
692 ChildNode
= CHILD_SECTION_NODE_FROM_LINK (Link
);
693 FreeChildNode (ChildNode
);
695 CoreFreePool (StreamNode
->StreamBuffer
);
696 CoreFreePool (StreamNode
);
697 Status
= EFI_SUCCESS
;
699 Status
= EFI_INVALID_PARAMETER
;
702 CoreRestoreTpl (OldTpl
);
709 Worker function. Determine if the input stream:child matches the input type.
711 @param Stream Indicates the section stream associated with the
713 @param Child Indicates the child to check
714 @param SearchType Indicates the type of section to check against
716 @param SectionDefinitionGuid Indicates the GUID to check against if the type
717 is EFI_SECTION_GUID_DEFINED
719 @retval TRUE The child matches
720 @retval FALSE The child doesn't match
725 IN CORE_SECTION_STREAM_NODE
*Stream
,
726 IN CORE_SECTION_CHILD_NODE
*Child
,
727 IN EFI_SECTION_TYPE SearchType
,
728 IN EFI_GUID
*SectionDefinitionGuid
731 EFI_GUID_DEFINED_SECTION
*GuidedSection
;
733 if (SearchType
== EFI_SECTION_ALL
) {
736 if (Child
->Type
!= SearchType
) {
739 if (SearchType
!= EFI_SECTION_GUID_DEFINED
) {
742 GuidedSection
= (EFI_GUID_DEFINED_SECTION
* )(Stream
->StreamBuffer
+ Child
->OffsetInStream
);
743 return CompareGuid (&GuidedSection
->SectionDefinitionGuid
, SectionDefinitionGuid
);
749 Worker function Recursively searches / builds section stream database
750 looking for requested section.
752 @param SourceStream Indicates the section stream in which to do the
754 @param SearchType Indicates the type of section to search for.
755 @param SectionInstance Indicates which instance of section to find.
756 This is an in/out parameter to deal with
758 @param SectionDefinitionGuid Guid of section definition
759 @param FoundChild Output indicating the child node that is found.
760 @param FoundStream Output indicating which section stream the child
761 was found in. If this stream was generated as a
762 result of an encapsulation section, the
763 streamhandle is visible within the SEP driver
765 @param AuthenticationStatus Indicates the authentication status of the found section.
767 @retval EFI_SUCCESS Child node was found and returned.
768 EFI_OUT_OF_RESOURCES- Memory allocation failed.
769 @retval EFI_NOT_FOUND Requested child node does not exist.
770 @retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol
776 IN CORE_SECTION_STREAM_NODE
*SourceStream
,
777 IN EFI_SECTION_TYPE SearchType
,
778 IN OUT UINTN
*SectionInstance
,
779 IN EFI_GUID
*SectionDefinitionGuid
,
780 OUT CORE_SECTION_CHILD_NODE
**FoundChild
,
781 OUT CORE_SECTION_STREAM_NODE
**FoundStream
,
782 OUT UINT32
*AuthenticationStatus
785 CORE_SECTION_CHILD_NODE
*CurrentChildNode
;
786 CORE_SECTION_CHILD_NODE
*RecursedChildNode
;
787 CORE_SECTION_STREAM_NODE
*RecursedFoundStream
;
788 UINT32 NextChildOffset
;
789 EFI_STATUS ErrorStatus
;
792 CurrentChildNode
= NULL
;
793 ErrorStatus
= EFI_NOT_FOUND
;
795 if (SourceStream
->StreamLength
== 0) {
796 return EFI_NOT_FOUND
;
799 if (IsListEmpty (&SourceStream
->Children
) &&
800 SourceStream
->StreamLength
>= sizeof (EFI_COMMON_SECTION_HEADER
)) {
802 // This occurs when a section stream exists, but no child sections
803 // have been parsed out yet. Therefore, extract the first child and add it
804 // to the list of children so we can get started.
805 // Section stream may contain an array of zero or more bytes.
806 // So, its size should be >= the size of commen section header.
808 Status
= CreateChildNode (SourceStream
, 0, &CurrentChildNode
);
809 if (EFI_ERROR (Status
)) {
815 // At least one child has been parsed out of the section stream. So, walk
816 // through the sections that have already been parsed out looking for the
817 // requested section, if necessary, continue parsing section stream and
818 // adding children until either the requested section is found, or we run
821 CurrentChildNode
= CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream
->Children
));
824 if (ChildIsType (SourceStream
, CurrentChildNode
, SearchType
, SectionDefinitionGuid
)) {
826 // The type matches, so check the instance count to see if it's the one we want
828 (*SectionInstance
)--;
829 if (*SectionInstance
== 0) {
833 *FoundChild
= CurrentChildNode
;
834 *FoundStream
= SourceStream
;
835 *AuthenticationStatus
= SourceStream
->AuthenticationStatus
;
840 if (CurrentChildNode
->EncapsulatedStreamHandle
!= NULL_STREAM_HANDLE
) {
842 // If the current node is an encapsulating node, recurse into it...
844 Status
= FindChildNode (
845 (CORE_SECTION_STREAM_NODE
*)CurrentChildNode
->EncapsulatedStreamHandle
,
848 SectionDefinitionGuid
,
850 &RecursedFoundStream
,
854 // If the status is not EFI_SUCCESS, just save the error code and continue
855 // to find the request child node in the rest stream.
857 if (*SectionInstance
== 0) {
858 ASSERT_EFI_ERROR (Status
);
859 *FoundChild
= RecursedChildNode
;
860 *FoundStream
= RecursedFoundStream
;
863 ErrorStatus
= Status
;
867 if (!IsNodeAtEnd (&SourceStream
->Children
, &CurrentChildNode
->Link
)) {
869 // We haven't found the child node we're interested in yet, but there's
870 // still more nodes that have already been parsed so get the next one
871 // and continue searching..
873 CurrentChildNode
= CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream
->Children
, &CurrentChildNode
->Link
));
876 // We've exhausted children that have already been parsed, so see if
877 // there's any more data and continue parsing out more children if there
880 NextChildOffset
= CurrentChildNode
->OffsetInStream
+ CurrentChildNode
->Size
;
882 // Round up to 4 byte boundary
884 NextChildOffset
+= 3;
885 NextChildOffset
&= ~(UINTN
)3;
886 if (NextChildOffset
<= SourceStream
->StreamLength
- sizeof (EFI_COMMON_SECTION_HEADER
)) {
888 // There's an unparsed child remaining in the stream, so create a new child node
890 Status
= CreateChildNode (SourceStream
, NextChildOffset
, &CurrentChildNode
);
891 if (EFI_ERROR (Status
)) {
895 ASSERT (EFI_ERROR (ErrorStatus
));
905 Worker function. Constructor for new child nodes.
907 @param Stream Indicates the section stream in which to add the
909 @param ChildOffset Indicates the offset in Stream that is the
910 beginning of the child section.
911 @param ChildNode Indicates the Callee allocated and initialized
914 @retval EFI_SUCCESS Child node was found and returned.
915 EFI_OUT_OF_RESOURCES- Memory allocation failed.
916 @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream
917 handles when the child node is created. If the
918 section type is GUID defined, and the extraction
919 GUID does not exist, and producing the stream
920 requires the GUID, then a protocol error is
921 generated and no child is produced. Values
922 returned by OpenSectionStreamEx.
927 IN CORE_SECTION_STREAM_NODE
*Stream
,
928 IN UINT32 ChildOffset
,
929 OUT CORE_SECTION_CHILD_NODE
**ChildNode
933 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
934 EFI_COMPRESSION_SECTION
*CompressionHeader
;
935 EFI_GUID_DEFINED_SECTION
*GuidedHeader
;
936 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
937 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*GuidedExtraction
;
938 VOID
*NewStreamBuffer
;
941 UINTN NewStreamBufferSize
;
942 UINT32 AuthenticationStatus
;
943 UINT32 SectionLength
;
945 CORE_SECTION_CHILD_NODE
*Node
;
947 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) (Stream
->StreamBuffer
+ ChildOffset
);
950 // Allocate a new node
952 *ChildNode
= CoreAllocateBootServicesPool (sizeof (CORE_SECTION_CHILD_NODE
));
955 return EFI_OUT_OF_RESOURCES
;
961 Node
->Signature
= CORE_SECTION_CHILD_SIGNATURE
;
962 Node
->Type
= SectionHeader
->Type
;
963 Node
->Size
= SECTION_SIZE (SectionHeader
);
964 Node
->OffsetInStream
= ChildOffset
;
965 Node
->EncapsulatedStreamHandle
= NULL_STREAM_HANDLE
;
966 Node
->EncapsulationGuid
= NULL
;
969 // If it's an encapsulating section, then create the new section stream also
971 switch (Node
->Type
) {
972 case EFI_SECTION_COMPRESSION
:
974 // Get the CompressionSectionHeader
976 ASSERT (Node
->Size
>= sizeof (EFI_COMPRESSION_SECTION
));
978 CompressionHeader
= (EFI_COMPRESSION_SECTION
*) SectionHeader
;
981 // Allocate space for the new stream
983 if (CompressionHeader
->UncompressedLength
> 0) {
984 NewStreamBufferSize
= CompressionHeader
->UncompressedLength
;
985 NewStreamBuffer
= CoreAllocateBootServicesPool (NewStreamBufferSize
);
986 if (NewStreamBuffer
== NULL
) {
988 return EFI_OUT_OF_RESOURCES
;
991 if (CompressionHeader
->CompressionType
== EFI_NOT_COMPRESSED
) {
993 // stream is not actually compressed, just encapsulated. So just copy it.
995 CopyMem (NewStreamBuffer
, CompressionHeader
+ 1, NewStreamBufferSize
);
996 } else if (CompressionHeader
->CompressionType
== EFI_STANDARD_COMPRESSION
) {
998 // Only support the EFI_SATNDARD_COMPRESSION algorithm.
1002 // Decompress the stream
1004 Status
= CoreLocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**)&Decompress
);
1006 ASSERT_EFI_ERROR (Status
);
1008 Status
= Decompress
->GetInfo (
1010 CompressionHeader
+ 1,
1011 Node
->Size
- sizeof (EFI_COMPRESSION_SECTION
),
1012 (UINT32
*)&NewStreamBufferSize
,
1015 ASSERT_EFI_ERROR (Status
);
1016 ASSERT (NewStreamBufferSize
== CompressionHeader
->UncompressedLength
);
1018 ScratchBuffer
= CoreAllocateBootServicesPool (ScratchSize
);
1019 if (ScratchBuffer
== NULL
) {
1020 CoreFreePool (Node
);
1021 CoreFreePool (NewStreamBuffer
);
1022 return EFI_OUT_OF_RESOURCES
;
1025 Status
= Decompress
->Decompress (
1027 CompressionHeader
+ 1,
1028 Node
->Size
- sizeof (EFI_COMPRESSION_SECTION
),
1030 (UINT32
)NewStreamBufferSize
,
1034 ASSERT_EFI_ERROR (Status
);
1035 CoreFreePool (ScratchBuffer
);
1038 NewStreamBuffer
= NULL
;
1039 NewStreamBufferSize
= 0;
1042 Status
= OpenSectionStreamEx (
1043 NewStreamBufferSize
,
1046 Stream
->AuthenticationStatus
,
1047 &Node
->EncapsulatedStreamHandle
1049 if (EFI_ERROR (Status
)) {
1050 CoreFreePool (Node
);
1051 CoreFreePool (NewStreamBuffer
);
1056 case EFI_SECTION_GUID_DEFINED
:
1057 GuidedHeader
= (EFI_GUID_DEFINED_SECTION
*) SectionHeader
;
1058 Node
->EncapsulationGuid
= &GuidedHeader
->SectionDefinitionGuid
;
1059 Status
= CoreLocateProtocol (Node
->EncapsulationGuid
, NULL
, (VOID
**)&GuidedExtraction
);
1060 if (!EFI_ERROR (Status
)) {
1062 // NewStreamBuffer is always allocated by ExtractSection... No caller
1065 Status
= GuidedExtraction
->ExtractSection (
1069 &NewStreamBufferSize
,
1070 &AuthenticationStatus
1072 if (EFI_ERROR (Status
)) {
1073 CoreFreePool (*ChildNode
);
1074 return EFI_PROTOCOL_ERROR
;
1078 // Make sure we initialize the new stream with the correct
1079 // authentication status for both aggregate and local status fields.
1081 if (GuidedHeader
->Attributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) {
1083 // OR in the parent stream's aggregate status.
1085 AuthenticationStatus
|= Stream
->AuthenticationStatus
& EFI_AUTH_STATUS_ALL
;
1088 // since there's no authentication data contributed by the section,
1089 // just inherit the full value from our immediate parent.
1091 AuthenticationStatus
= Stream
->AuthenticationStatus
;
1094 Status
= OpenSectionStreamEx (
1095 NewStreamBufferSize
,
1098 AuthenticationStatus
,
1099 &Node
->EncapsulatedStreamHandle
1101 if (EFI_ERROR (Status
)) {
1102 CoreFreePool (*ChildNode
);
1103 CoreFreePool (NewStreamBuffer
);
1108 // There's no GUIDed section extraction protocol available.
1110 if (GuidedHeader
->Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) {
1112 // If the section REQUIRES an extraction protocol, then we're toast
1114 CoreFreePool (*ChildNode
);
1115 return EFI_PROTOCOL_ERROR
;
1119 // Figure out the proper authentication status
1121 AuthenticationStatus
= Stream
->AuthenticationStatus
;
1123 SectionLength
= SECTION_SIZE (GuidedHeader
);
1124 Status
= OpenSectionStreamEx (
1125 SectionLength
- GuidedHeader
->DataOffset
,
1126 (UINT8
*) GuidedHeader
+ GuidedHeader
->DataOffset
,
1128 AuthenticationStatus
,
1129 &Node
->EncapsulatedStreamHandle
1131 if (EFI_ERROR (Status
)) {
1132 CoreFreePool (Node
);
1142 // Nothing to do if it's a leaf
1148 // Last, add the new child node to the stream
1150 InsertTailList (&Stream
->Children
, &Node
->Link
);
1158 Worker function. Constructor for RPN event if needed to keep AuthenticationStatus
1159 cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...
1161 @param ParentStream Indicates the parent of the ecnapsulation
1163 @param ChildNode Indicates the child node that is the
1164 encapsulation section.
1168 CreateGuidedExtractionRpnEvent (
1169 IN CORE_SECTION_STREAM_NODE
*ParentStream
,
1170 IN CORE_SECTION_CHILD_NODE
*ChildNode
1173 RPN_EVENT_CONTEXT
*Context
;
1176 // Allocate new event structure and context
1178 Context
= CoreAllocateBootServicesPool (sizeof (RPN_EVENT_CONTEXT
));
1179 ASSERT (Context
!= NULL
);
1181 Context
->ChildNode
= ChildNode
;
1182 Context
->ParentStream
= ParentStream
;
1184 Context
->Event
= CoreCreateProtocolNotifyEvent (
1185 Context
->ChildNode
->EncapsulationGuid
,
1187 NotifyGuidedExtraction
,
1189 &Context
->Registration
,
1198 RPN callback function. Removes a stale section stream and re-initializes it
1199 with an updated AuthenticationStatus.
1201 @param Event The event that fired
1202 @param RpnContext A pointer to the context that allows us to
1203 identify the relevent encapsulation...
1208 NotifyGuidedExtraction (
1214 EFI_GUID_DEFINED_SECTION
*GuidedHeader
;
1215 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*GuidedExtraction
;
1216 VOID
*NewStreamBuffer
;
1217 UINTN NewStreamBufferSize
;
1218 UINT32 AuthenticationStatus
;
1219 RPN_EVENT_CONTEXT
*Context
;
1221 Context
= RpnContext
;
1223 Status
= CloseSectionStream (Context
->ChildNode
->EncapsulatedStreamHandle
);
1224 if (!EFI_ERROR (Status
)) {
1226 // The stream closed successfully, so re-open the stream with correct AuthenticationStatus
1229 GuidedHeader
= (EFI_GUID_DEFINED_SECTION
*)
1230 (Context
->ParentStream
->StreamBuffer
+ Context
->ChildNode
->OffsetInStream
);
1231 ASSERT (GuidedHeader
->CommonHeader
.Type
== EFI_SECTION_GUID_DEFINED
);
1233 Status
= CoreLocateProtocol (Context
->ChildNode
->EncapsulationGuid
, NULL
, (VOID
**)&GuidedExtraction
);
1234 ASSERT_EFI_ERROR (Status
);
1237 Status
= GuidedExtraction
->ExtractSection (
1241 &NewStreamBufferSize
,
1242 &AuthenticationStatus
1244 ASSERT_EFI_ERROR (Status
);
1246 // OR in the parent stream's aggregagate status.
1248 AuthenticationStatus
|= Context
->ParentStream
->AuthenticationStatus
& EFI_AUTH_STATUS_ALL
;
1249 Status
= OpenSectionStreamEx (
1250 NewStreamBufferSize
,
1253 AuthenticationStatus
,
1254 &Context
->ChildNode
->EncapsulatedStreamHandle
1256 ASSERT_EFI_ERROR (Status
);
1260 // If above, the stream did not close successfully, it indicates it's
1261 // alread been closed by someone, so just destroy the event and be done with
1265 CoreCloseEvent (Event
);
1266 CoreFreePool (Context
);
1271 Worker function. Destructor for child nodes.
1273 @param ChildNode Indicates the node to destroy
1278 IN CORE_SECTION_CHILD_NODE
*ChildNode
1281 ASSERT (ChildNode
->Signature
== CORE_SECTION_CHILD_SIGNATURE
);
1283 // Remove the child from it's list
1285 RemoveEntryList (&ChildNode
->Link
);
1287 if (ChildNode
->EncapsulatedStreamHandle
!= NULL_STREAM_HANDLE
) {
1289 // If it's an encapsulating section, we close the resulting section stream.
1290 // CloseSectionStream will free all memory associated with the stream.
1292 CloseSectionStream (ChildNode
->EncapsulatedStreamHandle
);
1295 // Last, free the child node itself
1297 CoreFreePool (ChildNode
);
1303 Worker function. Constructor for section streams.
1305 @param SectionStreamLength Size in bytes of the section stream.
1306 @param SectionStream Buffer containing the new section stream.
1307 @param AllocateBuffer Indicates whether the stream buffer is to be
1308 copied or the input buffer is to be used in
1309 place. AuthenticationStatus- Indicates the
1310 default authentication status for the new
1312 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
1313 indicates the authentication status of the
1314 output buffer. If the input section's
1315 GuidedSectionHeader.Attributes field
1316 has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID
1317 bit as clear, AuthenticationStatus must return
1318 zero. Both local bits (19:16) and aggregate
1319 bits (3:0) in AuthenticationStatus are returned
1320 by ExtractSection(). These bits reflect the
1321 status of the extraction operation. The bit
1322 pattern in both regions must be the same, as
1323 the local and aggregate authentication statuses
1324 have equivalent meaning at this level. If the
1325 function returns anything other than
1326 EFI_SUCCESS, the value of *AuthenticationStatus
1328 @param SectionStreamHandle A pointer to a caller allocated section stream
1331 @retval EFI_SUCCESS Stream was added to stream database.
1332 @retval EFI_OUT_OF_RESOURCES memory allocation failed.
1336 OpenSectionStreamEx (
1337 IN UINTN SectionStreamLength
,
1338 IN VOID
*SectionStream
,
1339 IN BOOLEAN AllocateBuffer
,
1340 IN UINT32 AuthenticationStatus
,
1341 OUT UINTN
*SectionStreamHandle
1344 CORE_SECTION_STREAM_NODE
*NewStream
;
1348 // Allocate a new stream
1350 NewStream
= CoreAllocateBootServicesPool (sizeof (CORE_SECTION_STREAM_NODE
));
1351 if (NewStream
== NULL
) {
1352 return EFI_OUT_OF_RESOURCES
;
1355 if (AllocateBuffer
) {
1357 // if we're here, we're double buffering, allocate the buffer and copy the
1360 if (SectionStreamLength
> 0) {
1361 NewStream
->StreamBuffer
= CoreAllocateBootServicesPool (SectionStreamLength
);
1362 if (NewStream
->StreamBuffer
== NULL
) {
1363 CoreFreePool (NewStream
);
1364 return EFI_OUT_OF_RESOURCES
;
1367 // Copy in stream data
1369 CopyMem (NewStream
->StreamBuffer
, SectionStream
, SectionStreamLength
);
1372 // It's possible to have a zero length section stream.
1374 NewStream
->StreamBuffer
= NULL
;
1378 // If were here, the caller has supplied the buffer (it's an internal call)
1379 // so just assign the buffer. This happens when we open section streams
1380 // as a result of expanding an encapsulating section.
1382 NewStream
->StreamBuffer
= SectionStream
;
1386 // Initialize the rest of the section stream
1388 NewStream
->Signature
= CORE_SECTION_STREAM_SIGNATURE
;
1389 NewStream
->StreamHandle
= (UINTN
) NewStream
;
1390 NewStream
->StreamLength
= SectionStreamLength
;
1391 InitializeListHead (&NewStream
->Children
);
1392 NewStream
->AuthenticationStatus
= AuthenticationStatus
;
1395 // Add new stream to stream list
1397 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1398 InsertTailList (&mStreamRoot
, &NewStream
->Link
);
1399 CoreRestoreTpl (OldTpl
);
1401 *SectionStreamHandle
= NewStream
->StreamHandle
;
1409 Worker function. Search stream database for requested stream handle.
1411 @param SearchHandle Indicates which stream to look for.
1412 @param FoundStream Output pointer to the found stream.
1414 @retval EFI_SUCCESS StreamHandle was found and *FoundStream contains
1416 @retval EFI_NOT_FOUND SearchHandle was not found in the stream
1422 IN UINTN SearchHandle
,
1423 OUT CORE_SECTION_STREAM_NODE
**FoundStream
1426 CORE_SECTION_STREAM_NODE
*StreamNode
;
1428 if (!IsListEmpty (&mStreamRoot
)) {
1429 StreamNode
= STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot
));
1431 if (StreamNode
->StreamHandle
== SearchHandle
) {
1432 *FoundStream
= StreamNode
;
1434 } else if (IsNodeAtEnd (&mStreamRoot
, &StreamNode
->Link
)) {
1437 StreamNode
= STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot
, &StreamNode
->Link
));
1442 return EFI_NOT_FOUND
;
1448 Check if a stream is valid.
1450 @param SectionStream The section stream to be checked
1451 @param SectionStreamLength The length of section stream
1453 @return A boolean value indicating the validness of the section stream.
1457 IsValidSectionStream (
1458 IN VOID
*SectionStream
,
1459 IN UINTN SectionStreamLength
1463 UINTN SectionLength
;
1464 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1465 EFI_COMMON_SECTION_HEADER
*NextSectionHeader
;
1468 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*)SectionStream
;
1470 while (TotalLength
< SectionStreamLength
) {
1471 SectionLength
= SECTION_SIZE (SectionHeader
);
1472 TotalLength
+= SectionLength
;
1474 if (TotalLength
== SectionStreamLength
) {
1479 // Move to the next byte following the section...
1481 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ SectionLength
);
1484 // Figure out where the next section begins
1486 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) SectionHeader
+ 3);
1487 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) NextSectionHeader
& ~(UINTN
)3);
1488 TotalLength
+= (UINTN
) NextSectionHeader
- (UINTN
) SectionHeader
;
1489 SectionHeader
= NextSectionHeader
;
1497 The ExtractSection() function processes the input section and
1498 allocates a buffer from the pool in which it returns the section
1499 contents. If the section being extracted contains
1500 authentication information (the section's
1501 GuidedSectionHeader.Attributes field has the
1502 EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
1503 returned in AuthenticationStatus must reflect the results of
1504 the authentication operation. Depending on the algorithm and
1505 size of the encapsulated data, the time that is required to do
1506 a full authentication may be prohibitively long for some
1507 classes of systems. To indicate this, use
1508 EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
1509 the security policy driver (see the Platform Initialization
1510 Driver Execution Environment Core Interface Specification for
1511 more details and the GUID definition). If the
1512 EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
1513 database, then, if possible, full authentication should be
1514 skipped and the section contents simply returned in the
1515 OutputBuffer. In this case, the
1516 EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
1517 must be set on return. ExtractSection() is callable only from
1518 TPL_NOTIFY and below. Behavior of ExtractSection() at any
1519 EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
1520 defined in RaiseTPL() in the UEFI 2.0 specification.
1523 @param This Indicates the
1524 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
1526 @param InputSection Buffer containing the input GUIDed section
1527 to be processed. OutputBuffer OutputBuffer
1528 is allocated from boot services pool
1529 memory and contains the new section
1530 stream. The caller is responsible for
1531 freeing this buffer.
1532 @param OutputBuffer *OutputBuffer is allocated from boot services
1533 pool memory and contains the new section stream.
1534 The caller is responsible for freeing this buffer.
1535 @param OutputSize A pointer to a caller-allocated UINTN in
1536 which the size of OutputBuffer allocation
1537 is stored. If the function returns
1538 anything other than EFI_SUCCESS, the value
1539 of OutputSize is undefined.
1541 @param AuthenticationStatus A pointer to a caller-allocated
1542 UINT32 that indicates the
1543 authentication status of the
1544 output buffer. If the input
1546 GuidedSectionHeader.Attributes
1548 EFI_GUIDED_SECTION_AUTH_STATUS_VAL
1549 bit as clear, AuthenticationStatus
1550 must return zero. Both local bits
1551 (19:16) and aggregate bits (3:0)
1552 in AuthenticationStatus are
1553 returned by ExtractSection().
1554 These bits reflect the status of
1555 the extraction operation. The bit
1556 pattern in both regions must be
1557 the same, as the local and
1558 aggregate authentication statuses
1559 have equivalent meaning at this
1560 level. If the function returns
1561 anything other than EFI_SUCCESS,
1562 the value of AuthenticationStatus
1566 @retval EFI_SUCCESS The InputSection was successfully
1567 processed and the section contents were
1570 @retval EFI_OUT_OF_RESOURCES The system has insufficient
1571 resources to process the
1574 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
1575 not match this instance of the
1576 GUIDed Section Extraction
1582 CustomGuidedSectionExtract (
1583 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
*This
,
1584 IN CONST VOID
*InputSection
,
1585 OUT VOID
**OutputBuffer
,
1586 OUT UINTN
*OutputSize
,
1587 OUT UINT32
*AuthenticationStatus
1591 VOID
*ScratchBuffer
;
1592 VOID
*AllocatedOutputBuffer
;
1593 UINT32 OutputBufferSize
;
1594 UINT32 ScratchBufferSize
;
1595 UINT16 SectionAttribute
;
1598 // Init local variable
1600 ScratchBuffer
= NULL
;
1601 AllocatedOutputBuffer
= NULL
;
1604 // Call GetInfo to get the size and attribute of input guided section data.
1606 Status
= ExtractGuidedSectionGetInfo (
1613 if (EFI_ERROR (Status
)) {
1614 DEBUG ((DEBUG_ERROR
, "GetInfo from guided section Failed - %r\n", Status
));
1618 if (ScratchBufferSize
!= 0) {
1620 // Allocate scratch buffer
1622 ScratchBuffer
= CoreAllocateBootServicesPool (ScratchBufferSize
);
1623 if (ScratchBuffer
== NULL
) {
1624 return EFI_OUT_OF_RESOURCES
;
1628 if (OutputBufferSize
> 0) {
1630 // Allocate output buffer
1632 AllocatedOutputBuffer
= CoreAllocateBootServicesPool (OutputBufferSize
);
1633 if (AllocatedOutputBuffer
== NULL
) {
1634 return EFI_OUT_OF_RESOURCES
;
1636 *OutputBuffer
= AllocatedOutputBuffer
;
1640 // Call decode function to extract raw data from the guided section.
1642 Status
= ExtractGuidedSectionDecode (
1646 AuthenticationStatus
1648 if (EFI_ERROR (Status
)) {
1652 if (AllocatedOutputBuffer
!= NULL
) {
1653 CoreFreePool (AllocatedOutputBuffer
);
1655 if (ScratchBuffer
!= NULL
) {
1656 CoreFreePool (ScratchBuffer
);
1658 DEBUG ((DEBUG_ERROR
, "Extract guided section Failed - %r\n", Status
));
1662 if (*OutputBuffer
!= AllocatedOutputBuffer
) {
1664 // OutputBuffer was returned as a different value,
1665 // so copy section contents to the allocated memory buffer.
1667 CopyMem (AllocatedOutputBuffer
, *OutputBuffer
, OutputBufferSize
);
1668 *OutputBuffer
= AllocatedOutputBuffer
;
1672 // Set real size of output buffer.
1674 *OutputSize
= (UINTN
) OutputBufferSize
;
1677 // Free unused scratch buffer.
1679 if (ScratchBuffer
!= NULL
) {
1680 CoreFreePool (ScratchBuffer
);