]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
[Description]:
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / SectionExtraction / CoreSectionExtraction.c
CommitLineData
797a9d67 1/**@file\r
28a00297 2 Section Extraction Protocol implementation.\r
3 \r
4 Stream database is implemented as a linked list of section streams,\r
5 where each stream contains a linked list of children, which may be leaves or\r
6 encapsulations. \r
7 \r
8 Children that are encapsulations generate new stream entries\r
9 when they are created. Streams can also be created by calls to \r
10 SEP->OpenSectionStream().\r
11 \r
12 The database is only created far enough to return the requested data from\r
13 any given stream, or to determine that the requested data is not found.\r
14 \r
15 If a GUIDed encapsulation is encountered, there are three possiblilites.\r
16 \r
17 1) A support protocol is found, in which the stream is simply processed with\r
18 the support protocol.\r
19 \r
20 2) A support protocol is not found, but the data is available to be read\r
21 without processing. In this case, the database is built up through the\r
22 recursions to return the data, and a RPN event is set that will enable\r
23 the stream in question to be refreshed if and when the required section\r
24 extraction protocol is published.This insures the AuthenticationStatus \r
25 does not become stale in the cache.\r
26 \r
27 3) A support protocol is not found, and the data is not available to be read\r
28 without it. This results in EFI_PROTOCOL_ERROR.\r
797a9d67 29 \r
30Copyright (c) 2006 - 2007, Intel Corporation \r
31All rights reserved. This program and the accompanying materials \r
32are licensed and made available under the terms and conditions of the BSD License \r
33which accompanies this distribution. The full text of the license may be found at \r
34http://opensource.org/licenses/bsd-license.php \r
35 \r
36THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
37WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
38\r
39**/\r
28a00297 40\r
41#include <DxeMain.h>\r
42\r
43//\r
44// Local defines and typedefs\r
45//\r
46#define CORE_SECTION_CHILD_SIGNATURE EFI_SIGNATURE_32('S','X','C','S')\r
47#define CHILD_SECTION_NODE_FROM_LINK(Node) \\r
48 CR (Node, CORE_SECTION_CHILD_NODE, Link, CORE_SECTION_CHILD_SIGNATURE)\r
49\r
50typedef struct {\r
51 UINT32 Signature;\r
52 LIST_ENTRY Link;\r
53 UINT32 Type;\r
54 UINT32 Size;\r
55 //\r
56 // StreamBase + OffsetInStream == pointer to section header in stream. The\r
57 // stream base is always known when walking the sections within.\r
58 //\r
59 UINT32 OffsetInStream;\r
60 //\r
61 // Then EncapsulatedStreamHandle below is always 0 if the section is NOT an\r
62 // encapsulating section. Otherwise, it contains the stream handle\r
63 // of the encapsulated stream. This handle is ALWAYS produced any time an\r
64 // encapsulating child is encountered, irrespective of whether the\r
65 // encapsulated stream is processed further.\r
66 //\r
67 UINTN EncapsulatedStreamHandle;\r
68 EFI_GUID *EncapsulationGuid;\r
69} CORE_SECTION_CHILD_NODE;\r
70\r
71#define CORE_SECTION_STREAM_SIGNATURE EFI_SIGNATURE_32('S','X','S','S')\r
72#define STREAM_NODE_FROM_LINK(Node) \\r
73 CR (Node, CORE_SECTION_STREAM_NODE, Link, CORE_SECTION_STREAM_SIGNATURE)\r
74\r
75typedef struct {\r
76 UINT32 Signature;\r
77 LIST_ENTRY Link;\r
78 UINTN StreamHandle;\r
79 UINT8 *StreamBuffer;\r
80 UINTN StreamLength;\r
81 LIST_ENTRY Children;\r
82 //\r
83 // Authentication status is from GUIDed encapsulations.\r
84 //\r
85 UINT32 AuthenticationStatus;\r
86} CORE_SECTION_STREAM_NODE;\r
87\r
88#define NULL_STREAM_HANDLE 0\r
89\r
90typedef struct {\r
91 CORE_SECTION_CHILD_NODE *ChildNode;\r
92 CORE_SECTION_STREAM_NODE *ParentStream;\r
93 VOID *Registration;\r
94 EFI_EVENT Event;\r
95} RPN_EVENT_CONTEXT;\r
96 \r
97 \r
98\r
99//\r
100// Local prototypes\r
101//\r
102\r
103STATIC\r
104BOOLEAN\r
105ChildIsType (\r
106 IN CORE_SECTION_STREAM_NODE *Stream,\r
107 IN CORE_SECTION_CHILD_NODE *Child,\r
108 IN EFI_SECTION_TYPE SearchType,\r
109 IN EFI_GUID *SectionDefinitionGuid\r
110 );\r
111\r
d1f07630 112#if 0\r
28a00297 113STATIC\r
114VOID\r
115EFIAPI\r
116NotifyGuidedExtraction (\r
117 IN EFI_EVENT Event,\r
118 IN VOID *RpnContext\r
119 );\r
d1f07630 120#endif\r
28a00297 121\r
d1f07630 122#if 0\r
28a00297 123STATIC\r
124VOID\r
125CreateGuidedExtractionRpnEvent (\r
126 IN CORE_SECTION_STREAM_NODE *ParentStream,\r
127 IN CORE_SECTION_CHILD_NODE *ChildNode\r
128 );\r
d1f07630 129#endif\r
28a00297 130\r
28a00297 131STATIC\r
132EFI_STATUS\r
133FindStreamNode (\r
134 IN UINTN SearchHandle,\r
135 OUT CORE_SECTION_STREAM_NODE **FoundStream\r
136 );\r
137 \r
138STATIC\r
139EFI_STATUS\r
140FindChildNode (\r
141 IN CORE_SECTION_STREAM_NODE *SourceStream,\r
142 IN EFI_SECTION_TYPE SearchType,\r
143 IN UINTN *SectionInstance,\r
144 IN EFI_GUID *SectionDefinitionGuid,\r
145 OUT CORE_SECTION_CHILD_NODE **FoundChild,\r
146 OUT CORE_SECTION_STREAM_NODE **FoundStream,\r
147 OUT UINT32 *AuthenticationStatus\r
148 );\r
149 \r
150STATIC\r
151EFI_STATUS\r
152CreateChildNode (\r
153 IN CORE_SECTION_STREAM_NODE *Stream,\r
154 IN UINT32 ChildOffset,\r
155 OUT CORE_SECTION_CHILD_NODE **ChildNode\r
156 );\r
157 \r
158STATIC\r
159VOID\r
160FreeChildNode (\r
161 IN CORE_SECTION_CHILD_NODE *ChildNode\r
162 );\r
163 \r
164STATIC\r
165EFI_STATUS\r
166OpenSectionStreamEx (\r
167 IN UINTN SectionStreamLength,\r
168 IN VOID *SectionStream,\r
169 IN BOOLEAN AllocateBuffer,\r
170 IN UINT32 AuthenticationStatus, \r
171 OUT UINTN *SectionStreamHandle\r
172 );\r
173 \r
174STATIC\r
175BOOLEAN\r
176IsValidSectionStream (\r
177 IN VOID *SectionStream,\r
178 IN UINTN SectionStreamLength\r
179 );\r
d8c79a81
LG
180\r
181EFI_STATUS\r
797a9d67 182EFIAPI\r
18fd8d65 183CustomGuidedSectionExtract (\r
797a9d67 184 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,\r
d8c79a81
LG
185 IN CONST VOID *InputSection,\r
186 OUT VOID **OutputBuffer,\r
187 OUT UINTN *OutputSize,\r
188 OUT UINT32 *AuthenticationStatus\r
189 ); \r
28a00297 190//\r
191// Module globals\r
192//\r
193LIST_ENTRY mStreamRoot = INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot);\r
194\r
195EFI_HANDLE mSectionExtractionHandle = NULL;\r
196\r
18fd8d65
LG
197EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL mCustomGuidedSectionExtractionProtocol = {\r
198 CustomGuidedSectionExtract\r
d8c79a81 199};\r
28a00297 200 \r
201EFI_STATUS\r
202EFIAPI\r
203InitializeSectionExtraction (\r
204 IN EFI_HANDLE ImageHandle,\r
205 IN EFI_SYSTEM_TABLE *SystemTable\r
206 )\r
207/*++\r
208\r
209Routine Description: \r
210 Entry point of the section extraction code. Initializes an instance of the \r
211 section extraction interface and installs it on a new handle.\r
212\r
213Arguments: \r
214 ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver\r
215 SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table \r
216\r
217Returns: \r
218 EFI_SUCCESS: Driver initialized successfully\r
219 EFI_OUT_OF_RESOURCES: Could not allocate needed resources\r
220\r
221--*/\r
222{\r
223 EFI_STATUS Status;\r
18fd8d65
LG
224 EFI_GUID *ExtractHandlerGuidTable;\r
225 UINTN ExtractHandlerNumber;\r
28a00297 226\r
d8c79a81 227 //\r
18fd8d65 228 // Get custom extract guided section method guid list \r
d8c79a81 229 //\r
18fd8d65 230 ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);\r
797a9d67 231 \r
232 Status = EFI_SUCCESS;\r
d8c79a81 233 //\r
18fd8d65 234 // Install custom guided extraction protocol \r
d8c79a81 235 //\r
18fd8d65 236 while (ExtractHandlerNumber-- > 0) {\r
d8c79a81
LG
237 Status = CoreInstallProtocolInterface (\r
238 &mSectionExtractionHandle,\r
18fd8d65 239 &ExtractHandlerGuidTable [ExtractHandlerNumber],\r
d8c79a81 240 EFI_NATIVE_INTERFACE,\r
18fd8d65 241 &mCustomGuidedSectionExtractionProtocol\r
d8c79a81
LG
242 );\r
243 ASSERT_EFI_ERROR (Status);\r
244 }\r
d8c79a81 245\r
28a00297 246 return Status;\r
247}\r
248\r
28a00297 249EFI_STATUS\r
250EFIAPI\r
251OpenSectionStream (\r
28a00297 252 IN UINTN SectionStreamLength,\r
253 IN VOID *SectionStream,\r
254 OUT UINTN *SectionStreamHandle\r
255 )\r
256/*++\r
257\r
258Routine Description:\r
259 SEP member function. This function creates and returns a new section stream\r
260 handle to represent the new section stream.\r
261\r
262Arguments:\r
263 This - Indicates the calling context.\r
264 SectionStreamLength - Size in bytes of the section stream.\r
265 SectionStream - Buffer containing the new section stream.\r
266 SectionStreamHandle - A pointer to a caller allocated UINTN that on output\r
267 contains the new section stream handle.\r
268\r
269Returns:\r
270 EFI_SUCCESS\r
271 EFI_OUT_OF_RESOURCES - memory allocation failed.\r
272 EFI_INVALID_PARAMETER - section stream does not end concident with end of\r
273 last section.\r
274\r
275--*/\r
276{\r
277 //\r
278 // Check to see section stream looks good...\r
279 //\r
280 if (!IsValidSectionStream (SectionStream, SectionStreamLength)) {\r
281 return EFI_INVALID_PARAMETER;\r
282 }\r
283 \r
284 return OpenSectionStreamEx ( \r
285 SectionStreamLength, \r
286 SectionStream,\r
287 TRUE,\r
288 0,\r
289 SectionStreamHandle\r
290 );\r
291}\r
292 \r
28a00297 293EFI_STATUS\r
294EFIAPI\r
295GetSection (\r
28a00297 296 IN UINTN SectionStreamHandle,\r
297 IN EFI_SECTION_TYPE *SectionType,\r
298 IN EFI_GUID *SectionDefinitionGuid,\r
299 IN UINTN SectionInstance,\r
300 IN VOID **Buffer,\r
301 IN OUT UINTN *BufferSize,\r
302 OUT UINT32 *AuthenticationStatus\r
303 )\r
304/*++\r
305\r
306Routine Description:\r
307 SEP member function. Retrieves requested section from section stream.\r
308\r
309Arguments: \r
28a00297 310 SectionStreamHandle: The section stream from which to extract the requested\r
311 section.\r
312 SectionType: A pointer to the type of section to search for.\r
313 SectionDefinitionGuid: If the section type is EFI_SECTION_GUID_DEFINED, then\r
314 SectionDefinitionGuid indicates which of these types\r
315 of sections to search for.\r
316 SectionInstance: Indicates which instance of the requested section to\r
317 return.\r
318 Buffer: Double indirection to buffer. If *Buffer is non-null on\r
319 input, then the buffer is caller allocated. If\r
320 *Buffer is NULL, then the buffer is callee allocated.\r
321 In either case, the requried buffer size is returned\r
322 in *BufferSize.\r
323 BufferSize: On input, indicates the size of *Buffer if *Buffer is\r
324 non-null on input. On output, indicates the required\r
325 size (allocated size if callee allocated) of *Buffer.\r
326 AuthenticationStatus: Indicates the authentication status of the retrieved\r
327 section.\r
328\r
329Returns: \r
330 EFI_SUCCESS: Section was retrieved successfully\r
331 EFI_PROTOCOL_ERROR: A GUID defined section was encountered in the section \r
332 stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED\r
333 bit set, but there was no corresponding GUIDed Section \r
334 Extraction Protocol in the handle database. *Buffer is \r
335 unmodified.\r
336 EFI_NOT_FOUND: An error was encountered when parsing the SectionStream.\r
337 This indicates the SectionStream is not correctly \r
338 formatted.\r
339 EFI_NOT_FOUND: The requested section does not exist.\r
340 EFI_OUT_OF_RESOURCES: The system has insufficient resources to process the \r
341 request.\r
342 EFI_INVALID_PARAMETER: The SectionStreamHandle does not exist.\r
343 EFI_WARN_TOO_SMALL: The size of the caller allocated input buffer is \r
344 insufficient to contain the requested section. The \r
345 input buffer is filled and contents are section contents\r
346 are truncated.\r
347\r
348--*/\r
349{\r
350 CORE_SECTION_STREAM_NODE *StreamNode;\r
351 EFI_TPL OldTpl;\r
352 EFI_STATUS Status;\r
353 CORE_SECTION_CHILD_NODE *ChildNode;\r
354 CORE_SECTION_STREAM_NODE *ChildStreamNode;\r
355 UINTN CopySize;\r
356 UINT32 ExtractedAuthenticationStatus;\r
357 UINTN Instance;\r
358 UINT8 *CopyBuffer;\r
359 UINTN SectionSize;\r
360 \r
f58f873c 361\r
28a00297 362 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
363 Instance = SectionInstance + 1;\r
f58f873c 364 \r
28a00297 365 //\r
366 // Locate target stream\r
367 //\r
368 Status = FindStreamNode (SectionStreamHandle, &StreamNode);\r
369 if (EFI_ERROR (Status)) {\r
370 Status = EFI_INVALID_PARAMETER;\r
371 goto GetSection_Done;\r
372 }\r
373 \r
374 //\r
375 // Found the stream, now locate and return the appropriate section\r
376 //\r
377 if (SectionType == NULL) {\r
378 //\r
379 // SectionType == NULL means return the WHOLE section stream...\r
380 //\r
381 CopySize = StreamNode->StreamLength;\r
382 CopyBuffer = StreamNode->StreamBuffer;\r
383 *AuthenticationStatus = StreamNode->AuthenticationStatus;\r
384 } else {\r
385 //\r
386 // There's a requested section type, so go find it and return it...\r
387 //\r
388 Status = FindChildNode (\r
389 StreamNode, \r
390 *SectionType, \r
391 &Instance, \r
392 SectionDefinitionGuid,\r
393 &ChildNode,\r
394 &ChildStreamNode, \r
395 &ExtractedAuthenticationStatus\r
396 );\r
397 if (EFI_ERROR (Status)) {\r
398 goto GetSection_Done;\r
399 }\r
400 CopySize = ChildNode->Size - sizeof (EFI_COMMON_SECTION_HEADER);\r
401 CopyBuffer = ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream + sizeof (EFI_COMMON_SECTION_HEADER);\r
402 *AuthenticationStatus = ExtractedAuthenticationStatus;\r
403 } \r
404 \r
405 SectionSize = CopySize; \r
406 if (*Buffer != NULL) {\r
407 //\r
408 // Caller allocated buffer. Fill to size and return required size...\r
409 //\r
410 if (*BufferSize < CopySize) {\r
411 Status = EFI_WARN_BUFFER_TOO_SMALL;\r
412 CopySize = *BufferSize;\r
413 }\r
414 } else {\r
415 //\r
416 // Callee allocated buffer. Allocate buffer and return size.\r
417 //\r
f58f873c 418 *Buffer = CoreAllocateBootServicesPool (CopySize);\r
28a00297 419 if (*Buffer == NULL) {\r
420 Status = EFI_OUT_OF_RESOURCES;\r
421 goto GetSection_Done;\r
422 }\r
423 }\r
424 CopyMem (*Buffer, CopyBuffer, CopySize);\r
425 *BufferSize = SectionSize;\r
426 \r
427GetSection_Done:\r
428 CoreRestoreTpl (OldTpl);\r
429 return Status;\r
430}\r
431\r
432\r
28a00297 433EFI_STATUS\r
434EFIAPI\r
435CloseSectionStream (\r
28a00297 436 IN UINTN StreamHandleToClose\r
437 )\r
438/*++\r
439\r
440Routine Description:\r
441 SEP member function. Deletes an existing section stream\r
442\r
443Arguments:\r
444 This - Indicates the calling context.\r
445 StreamHandleToClose - Indicates the stream to close\r
446\r
447Returns:\r
448 EFI_SUCCESS\r
449 EFI_OUT_OF_RESOURCES - memory allocation failed.\r
450 EFI_INVALID_PARAMETER - section stream does not end concident with end of\r
451 last section.\r
452\r
453--*/\r
454{\r
455 CORE_SECTION_STREAM_NODE *StreamNode;\r
456 EFI_TPL OldTpl;\r
457 EFI_STATUS Status;\r
458 LIST_ENTRY *Link;\r
459 CORE_SECTION_CHILD_NODE *ChildNode;\r
460 \r
461 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
462 \r
463 //\r
464 // Locate target stream\r
465 //\r
466 Status = FindStreamNode (StreamHandleToClose, &StreamNode);\r
467 if (!EFI_ERROR (Status)) {\r
468 //\r
469 // Found the stream, so close it\r
470 //\r
471 RemoveEntryList (&StreamNode->Link);\r
472 while (!IsListEmpty (&StreamNode->Children)) {\r
473 Link = GetFirstNode (&StreamNode->Children);\r
474 ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link);\r
475 FreeChildNode (ChildNode);\r
476 }\r
477 CoreFreePool (StreamNode->StreamBuffer);\r
478 CoreFreePool (StreamNode);\r
479 Status = EFI_SUCCESS;\r
480 } else {\r
481 Status = EFI_INVALID_PARAMETER;\r
482 }\r
483 \r
484 CoreRestoreTpl (OldTpl);\r
485 return Status;\r
486}\r
487\r
488\r
489STATIC\r
490BOOLEAN\r
491ChildIsType (\r
492 IN CORE_SECTION_STREAM_NODE *Stream,\r
493 IN CORE_SECTION_CHILD_NODE *Child,\r
494 IN EFI_SECTION_TYPE SearchType,\r
495 IN EFI_GUID *SectionDefinitionGuid\r
496 )\r
497/*++\r
498\r
499Routine Description:\r
500 Worker function. Determine if the input stream:child matches the input type.\r
501\r
502Arguments:\r
503 Stream - Indicates the section stream associated with the child\r
504 Child - Indicates the child to check\r
505 SearchType - Indicates the type of section to check against for\r
506 SectionDefinitionGuid - Indicates the GUID to check against if the type is\r
507 EFI_SECTION_GUID_DEFINED\r
508Returns:\r
509 TRUE - The child matches\r
510 FALSE - The child doesn't match\r
511\r
512--*/\r
513{\r
514 EFI_GUID_DEFINED_SECTION *GuidedSection;\r
515 \r
516 if (SearchType == EFI_SECTION_ALL) {\r
517 return TRUE;\r
518 }\r
519 if (Child->Type != SearchType) {\r
520 return FALSE;\r
521 }\r
522 if (SearchType != EFI_SECTION_GUID_DEFINED) {\r
523 return TRUE;\r
524 }\r
525 GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);\r
526 return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid);\r
527}\r
528\r
529\r
530STATIC\r
531EFI_STATUS\r
532FindChildNode (\r
533 IN CORE_SECTION_STREAM_NODE *SourceStream,\r
534 IN EFI_SECTION_TYPE SearchType,\r
535 IN OUT UINTN *SectionInstance,\r
536 IN EFI_GUID *SectionDefinitionGuid,\r
537 OUT CORE_SECTION_CHILD_NODE **FoundChild,\r
538 OUT CORE_SECTION_STREAM_NODE **FoundStream,\r
539 OUT UINT32 *AuthenticationStatus\r
540 )\r
541/*++\r
542\r
543Routine Description:\r
544 Worker function Recursively searches / builds section stream database\r
545 looking for requested section.\r
546\r
547Arguments:\r
548 SourceStream - Indicates the section stream in which to do the search.\r
549 SearchType - Indicates the type of section to search for.\r
550 SectionInstance - Indicates which instance of section to find. This is\r
551 an in/out parameter to deal with recursions.\r
552 SectionDefinitionGuid - Guid of section definition\r
553 FoundChild - Output indicating the child node that is found.\r
554 FoundStream - Output indicating which section stream the child was\r
555 found in. If this stream was generated as a result of\r
556 an encapsulation section, the streamhandle is visible\r
557 within the SEP driver only.\r
558 AuthenticationStatus- Indicates the authentication status of the found section.\r
559\r
560Returns:\r
561 EFI_SUCCESS - Child node was found and returned.\r
562 EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
563 EFI_NOT_FOUND - Requested child node does not exist.\r
564 EFI_PROTOCOL_ERROR - a required GUIDED section extraction protocol does not\r
565 exist\r
566\r
567--*/\r
568{\r
569 CORE_SECTION_CHILD_NODE *CurrentChildNode;\r
570 CORE_SECTION_CHILD_NODE *RecursedChildNode;\r
571 CORE_SECTION_STREAM_NODE *RecursedFoundStream;\r
572 UINT32 NextChildOffset;\r
573 EFI_STATUS ErrorStatus;\r
574 EFI_STATUS Status;\r
575 \r
576 CurrentChildNode = NULL;\r
577 ErrorStatus = EFI_NOT_FOUND;\r
578 \r
579 if (SourceStream->StreamLength == 0) {\r
580 return EFI_NOT_FOUND;\r
581 }\r
582 \r
583 if (IsListEmpty (&SourceStream->Children) && \r
584 SourceStream->StreamLength > sizeof (EFI_COMMON_SECTION_HEADER)) {\r
585 //\r
586 // This occurs when a section stream exists, but no child sections\r
587 // have been parsed out yet. Therefore, extract the first child and add it\r
588 // to the list of children so we can get started.\r
589 //\r
590 Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);\r
591 if (EFI_ERROR (Status)) {\r
592 return Status;\r
593 }\r
594 }\r
595 \r
596 //\r
597 // At least one child has been parsed out of the section stream. So, walk\r
598 // through the sections that have already been parsed out looking for the\r
599 // requested section, if necessary, continue parsing section stream and\r
600 // adding children until either the requested section is found, or we run\r
601 // out of data\r
602 //\r
603 CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children));\r
604\r
605 for (;;) {\r
606 if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) {\r
607 //\r
608 // The type matches, so check the instance count to see if it's the one we want\r
609 //\r
610 (*SectionInstance)--;\r
611 if (*SectionInstance == 0) {\r
612 //\r
613 // Got it!\r
614 //\r
615 *FoundChild = CurrentChildNode;\r
616 *FoundStream = SourceStream;\r
617 *AuthenticationStatus = SourceStream->AuthenticationStatus;\r
618 return EFI_SUCCESS;\r
619 }\r
620 }\r
621 \r
622 if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {\r
623 //\r
624 // If the current node is an encapsulating node, recurse into it...\r
625 //\r
626 Status = FindChildNode (\r
627 (CORE_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle,\r
628 SearchType,\r
629 SectionInstance,\r
630 SectionDefinitionGuid,\r
631 &RecursedChildNode,\r
632 &RecursedFoundStream,\r
633 AuthenticationStatus\r
634 );\r
635 //\r
636 // If the status is not EFI_SUCCESS, just save the error code and continue\r
637 // to find the request child node in the rest stream.\r
638 //\r
639 if (*SectionInstance == 0) {\r
640 ASSERT_EFI_ERROR (Status);\r
641 *FoundChild = RecursedChildNode;\r
642 *FoundStream = RecursedFoundStream;\r
643 return EFI_SUCCESS;\r
644 } else {\r
645 ErrorStatus = Status;\r
646 }\r
647 }\r
648 \r
649 if (!IsNodeAtEnd (&SourceStream->Children, &CurrentChildNode->Link)) {\r
650 //\r
651 // We haven't found the child node we're interested in yet, but there's\r
652 // still more nodes that have already been parsed so get the next one\r
653 // and continue searching..\r
654 //\r
655 CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream->Children, &CurrentChildNode->Link));\r
656 } else {\r
657 //\r
658 // We've exhausted children that have already been parsed, so see if\r
659 // there's any more data and continue parsing out more children if there\r
660 // is.\r
661 //\r
662 NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size;\r
663 //\r
664 // Round up to 4 byte boundary\r
665 //\r
666 NextChildOffset += 3;\r
667 NextChildOffset &= ~(UINTN)3;\r
668 if (NextChildOffset <= SourceStream->StreamLength - sizeof (EFI_COMMON_SECTION_HEADER)) {\r
669 //\r
670 // There's an unparsed child remaining in the stream, so create a new child node\r
671 //\r
672 Status = CreateChildNode (SourceStream, NextChildOffset, &CurrentChildNode);\r
673 if (EFI_ERROR (Status)) {\r
674 return Status;\r
675 }\r
676 } else {\r
677 ASSERT (EFI_ERROR (ErrorStatus));\r
678 return ErrorStatus;\r
679 }\r
680 }\r
681 }\r
682}\r
683\r
684\r
685STATIC\r
686EFI_STATUS\r
687CreateChildNode (\r
688 IN CORE_SECTION_STREAM_NODE *Stream,\r
689 IN UINT32 ChildOffset,\r
690 OUT CORE_SECTION_CHILD_NODE **ChildNode\r
691 )\r
692/*++\r
693\r
694Routine Description:\r
695 Worker function. Constructor for new child nodes.\r
696\r
697Arguments:\r
698 Stream - Indicates the section stream in which to add the child.\r
699 ChildOffset - Indicates the offset in Stream that is the beginning\r
700 of the child section.\r
701 ChildNode - Indicates the Callee allocated and initialized child.\r
702\r
703Returns:\r
704 EFI_SUCCESS - Child node was found and returned.\r
705 EFI_OUT_OF_RESOURCES- Memory allocation failed.\r
706 EFI_PROTOCOL_ERROR - Encapsulation sections produce new stream handles when\r
707 the child node is created. If the section type is GUID\r
708 defined, and the extraction GUID does not exist, and\r
709 producing the stream requires the GUID, then a protocol\r
710 error is generated and no child is produced.\r
711 Values returned by OpenSectionStreamEx.\r
712\r
713--*/\r
714{\r
715 EFI_STATUS Status;\r
716 EFI_COMMON_SECTION_HEADER *SectionHeader;\r
717 EFI_COMPRESSION_SECTION *CompressionHeader;\r
718 EFI_GUID_DEFINED_SECTION *GuidedHeader;\r
d8c79a81 719 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
28a00297 720 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;\r
721 VOID *NewStreamBuffer;\r
722 VOID *ScratchBuffer;\r
723 UINT32 ScratchSize;\r
724 UINTN NewStreamBufferSize;\r
725 UINT32 AuthenticationStatus;\r
726 UINT32 SectionLength;\r
727 \r
728 CORE_SECTION_CHILD_NODE *Node;\r
729\r
730 SectionHeader = (EFI_COMMON_SECTION_HEADER *) (Stream->StreamBuffer + ChildOffset);\r
731\r
732 //\r
733 // Allocate a new node\r
734 //\r
735 *ChildNode = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_CHILD_NODE));\r
736 Node = *ChildNode;\r
737 if (Node == NULL) {\r
738 return EFI_OUT_OF_RESOURCES;\r
739 }\r
740 \r
741 //\r
742 // Now initialize it\r
743 //\r
744 Node->Signature = CORE_SECTION_CHILD_SIGNATURE;\r
745 Node->Type = SectionHeader->Type;\r
746 Node->Size = SECTION_SIZE (SectionHeader);\r
747 Node->OffsetInStream = ChildOffset;\r
748 Node->EncapsulatedStreamHandle = NULL_STREAM_HANDLE;\r
749 Node->EncapsulationGuid = NULL;\r
750 \r
751 //\r
752 // If it's an encapsulating section, then create the new section stream also\r
753 //\r
754 switch (Node->Type) {\r
755 case EFI_SECTION_COMPRESSION:\r
756 //\r
757 // Get the CompressionSectionHeader\r
758 //\r
759 ASSERT (Node->Size >= sizeof (EFI_COMPRESSION_SECTION));\r
760 \r
761 CompressionHeader = (EFI_COMPRESSION_SECTION *) SectionHeader;\r
762 \r
763 //\r
764 // Allocate space for the new stream\r
765 //\r
766 if (CompressionHeader->UncompressedLength > 0) {\r
767 NewStreamBufferSize = CompressionHeader->UncompressedLength;\r
768 NewStreamBuffer = CoreAllocateBootServicesPool (NewStreamBufferSize);\r
769 if (NewStreamBuffer == NULL) {\r
770 CoreFreePool (Node);\r
771 return EFI_OUT_OF_RESOURCES;\r
772 }\r
773 \r
774 if (CompressionHeader->CompressionType == EFI_NOT_COMPRESSED) {\r
775 //\r
776 // stream is not actually compressed, just encapsulated. So just copy it.\r
777 //\r
778 CopyMem (NewStreamBuffer, CompressionHeader + 1, NewStreamBufferSize);\r
779 } else if (CompressionHeader->CompressionType == EFI_STANDARD_COMPRESSION) {\r
780 //\r
781 // Only support the EFI_SATNDARD_COMPRESSION algorithm.\r
782 // \r
783\r
784 //\r
785 // Decompress the stream\r
786 //\r
787 Status = CoreLocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **)&Decompress);\r
788 \r
789 ASSERT_EFI_ERROR (Status);\r
790 \r
791 Status = Decompress->GetInfo (\r
792 Decompress,\r
793 CompressionHeader + 1,\r
794 Node->Size - sizeof (EFI_COMPRESSION_SECTION),\r
795 (UINT32 *)&NewStreamBufferSize,\r
796 &ScratchSize\r
797 );\r
798 ASSERT_EFI_ERROR (Status);\r
799 ASSERT (NewStreamBufferSize == CompressionHeader->UncompressedLength);\r
800\r
801 ScratchBuffer = CoreAllocateBootServicesPool (ScratchSize);\r
802 if (ScratchBuffer == NULL) {\r
803 CoreFreePool (Node);\r
804 CoreFreePool (NewStreamBuffer);\r
805 return EFI_OUT_OF_RESOURCES;\r
806 }\r
807\r
808 Status = Decompress->Decompress (\r
809 Decompress,\r
810 CompressionHeader + 1,\r
811 Node->Size - sizeof (EFI_COMPRESSION_SECTION),\r
812 NewStreamBuffer,\r
813 (UINT32)NewStreamBufferSize,\r
814 ScratchBuffer,\r
815 ScratchSize\r
816 );\r
817 ASSERT_EFI_ERROR (Status);\r
818 CoreFreePool (ScratchBuffer); \r
819 }\r
820 } else {\r
821 NewStreamBuffer = NULL;\r
822 NewStreamBufferSize = 0;\r
823 }\r
824 \r
825 Status = OpenSectionStreamEx (\r
826 NewStreamBufferSize,\r
827 NewStreamBuffer,\r
828 FALSE,\r
829 Stream->AuthenticationStatus,\r
830 &Node->EncapsulatedStreamHandle\r
831 );\r
832 if (EFI_ERROR (Status)) {\r
833 CoreFreePool (Node);\r
834 CoreFreePool (NewStreamBuffer);\r
835 return Status;\r
836 }\r
837 break;\r
838\r
839 case EFI_SECTION_GUID_DEFINED:\r
840 GuidedHeader = (EFI_GUID_DEFINED_SECTION *) SectionHeader;\r
841 Node->EncapsulationGuid = &GuidedHeader->SectionDefinitionGuid;\r
842 Status = CoreLocateProtocol (Node->EncapsulationGuid, NULL, (VOID **)&GuidedExtraction);\r
843 if (!EFI_ERROR (Status)) {\r
844 //\r
845 // NewStreamBuffer is always allocated by ExtractSection... No caller\r
846 // allocation here.\r
847 //\r
848 Status = GuidedExtraction->ExtractSection (\r
849 GuidedExtraction,\r
850 GuidedHeader,\r
851 &NewStreamBuffer,\r
852 &NewStreamBufferSize,\r
853 &AuthenticationStatus\r
854 );\r
855 if (EFI_ERROR (Status)) {\r
856 CoreFreePool (*ChildNode);\r
857 return EFI_PROTOCOL_ERROR;\r
858 }\r
859 \r
860 //\r
861 // Make sure we initialize the new stream with the correct \r
862 // authentication status for both aggregate and local status fields.\r
863 //\r
864 if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {\r
865 //\r
866 // OR in the parent stream's aggregate status.\r
867 //\r
797a9d67 868 AuthenticationStatus |= Stream->AuthenticationStatus & EFI_AUTH_STATUS_ALL;\r
28a00297 869 } else {\r
870 //\r
871 // since there's no authentication data contributed by the section,\r
872 // just inherit the full value from our immediate parent.\r
873 //\r
874 AuthenticationStatus = Stream->AuthenticationStatus;\r
875 }\r
876 \r
877 Status = OpenSectionStreamEx (\r
878 NewStreamBufferSize,\r
879 NewStreamBuffer,\r
880 FALSE,\r
881 AuthenticationStatus,\r
882 &Node->EncapsulatedStreamHandle\r
883 );\r
884 if (EFI_ERROR (Status)) {\r
885 CoreFreePool (*ChildNode);\r
886 CoreFreePool (NewStreamBuffer);\r
887 return Status;\r
888 }\r
889 } else {\r
890 //\r
891 // There's no GUIDed section extraction protocol available.\r
892 //\r
893 if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {\r
894 //\r
895 // If the section REQUIRES an extraction protocol, then we're toast\r
896 //\r
897 CoreFreePool (*ChildNode);\r
898 return EFI_PROTOCOL_ERROR;\r
899 }\r
900 \r
901 //\r
902 // Figure out the proper authentication status\r
903 //\r
904 AuthenticationStatus = Stream->AuthenticationStatus;\r
28a00297 905 \r
906 SectionLength = SECTION_SIZE (GuidedHeader);\r
907 Status = OpenSectionStreamEx (\r
908 SectionLength - GuidedHeader->DataOffset,\r
909 (UINT8 *) GuidedHeader + GuidedHeader->DataOffset,\r
910 TRUE,\r
911 AuthenticationStatus,\r
912 &Node->EncapsulatedStreamHandle\r
913 );\r
914 if (EFI_ERROR (Status)) {\r
915 CoreFreePool (Node);\r
916 return Status;\r
917 }\r
918 }\r
919 \r
28a00297 920 break;\r
921\r
922 default:\r
923 \r
924 //\r
925 // Nothing to do if it's a leaf\r
926 //\r
927 break;\r
928 }\r
929 \r
930 //\r
931 // Last, add the new child node to the stream\r
932 //\r
933 InsertTailList (&Stream->Children, &Node->Link);\r
934\r
935 return EFI_SUCCESS;\r
936}\r
937\r
938\r
d1f07630 939#if 0\r
28a00297 940STATIC\r
941VOID\r
942CreateGuidedExtractionRpnEvent (\r
943 IN CORE_SECTION_STREAM_NODE *ParentStream,\r
944 IN CORE_SECTION_CHILD_NODE *ChildNode\r
945 )\r
946/*++\r
947\r
948Routine Description:\r
949 Worker function. Constructor for RPN event if needed to keep AuthenticationStatus\r
950 cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...\r
951\r
952Arguments:\r
953 ParentStream - Indicates the parent of the ecnapsulation section (child)\r
954 ChildNode - Indicates the child node that is the encapsulation section.\r
955\r
956Returns:\r
957 None\r
958\r
959--*/\r
960{\r
961 RPN_EVENT_CONTEXT *Context;\r
962 \r
963 //\r
964 // Allocate new event structure and context\r
965 //\r
966 Context = CoreAllocateBootServicesPool (sizeof (RPN_EVENT_CONTEXT));\r
967 ASSERT (Context != NULL);\r
968 \r
969 Context->ChildNode = ChildNode;\r
970 Context->ParentStream = ParentStream;\r
971 \r
972 Context->Event = CoreCreateProtocolNotifyEvent (\r
973 Context->ChildNode->EncapsulationGuid,\r
974 TPL_NOTIFY,\r
975 NotifyGuidedExtraction,\r
976 Context,\r
977 &Context->Registration,\r
978 FALSE\r
979 );\r
980}\r
d1f07630 981#endif\r
982\r
983\r
984#if 0\r
28a00297 985STATIC\r
986VOID\r
987EFIAPI\r
988NotifyGuidedExtraction (\r
989 IN EFI_EVENT Event,\r
990 IN VOID *RpnContext\r
991 )\r
992/*++\r
993\r
994Routine Description:\r
995 RPN callback function. Removes a stale section stream and re-initializes it\r
996 with an updated AuthenticationStatus.\r
997\r
998Arguments:\r
999 Event - The event that fired\r
1000 RpnContext - A pointer to the context that allows us to identify\r
1001 the relevent encapsulation...\r
1002\r
1003Returns:\r
1004 None\r
1005\r
1006--*/\r
1007{\r
1008 EFI_STATUS Status;\r
1009 EFI_GUID_DEFINED_SECTION *GuidedHeader;\r
1010 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;\r
1011 VOID *NewStreamBuffer;\r
1012 UINTN NewStreamBufferSize;\r
1013 UINT32 AuthenticationStatus;\r
1014 RPN_EVENT_CONTEXT *Context;\r
1015 \r
1016 Context = RpnContext;\r
1017 \r
797a9d67 1018 Status = CloseSectionStream (Context->ChildNode->EncapsulatedStreamHandle);\r
28a00297 1019 if (!EFI_ERROR (Status)) {\r
1020 //\r
1021 // The stream closed successfully, so re-open the stream with correct AuthenticationStatus\r
1022 //\r
1023 \r
1024 GuidedHeader = (EFI_GUID_DEFINED_SECTION *) \r
1025 (Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream);\r
1026 ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED);\r
1027 \r
1028 Status = CoreLocateProtocol (Context->ChildNode->EncapsulationGuid, NULL, (VOID **)&GuidedExtraction);\r
1029 ASSERT_EFI_ERROR (Status);\r
1030\r
1031 \r
1032 Status = GuidedExtraction->ExtractSection (\r
1033 GuidedExtraction,\r
1034 GuidedHeader,\r
1035 &NewStreamBuffer,\r
1036 &NewStreamBufferSize,\r
1037 &AuthenticationStatus\r
1038 );\r
1039 ASSERT_EFI_ERROR (Status);\r
1040 //\r
1041 // OR in the parent stream's aggregagate status.\r
1042 //\r
797a9d67 1043 AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AUTH_STATUS_ALL;\r
28a00297 1044 Status = OpenSectionStreamEx (\r
1045 NewStreamBufferSize,\r
1046 NewStreamBuffer,\r
1047 FALSE,\r
1048 AuthenticationStatus,\r
1049 &Context->ChildNode->EncapsulatedStreamHandle\r
1050 );\r
1051 ASSERT_EFI_ERROR (Status);\r
1052 }\r
1053\r
1054 //\r
1055 // If above, the stream did not close successfully, it indicates it's\r
1056 // alread been closed by someone, so just destroy the event and be done with\r
1057 // it.\r
1058 //\r
1059 \r
1060 CoreCloseEvent (Event);\r
1061 CoreFreePool (Context);\r
1062} \r
d1f07630 1063#endif\r
1064\r
28a00297 1065\r
1066STATIC\r
1067VOID\r
1068FreeChildNode (\r
1069 IN CORE_SECTION_CHILD_NODE *ChildNode\r
1070 )\r
1071/*++\r
1072\r
1073Routine Description:\r
1074 Worker function. Destructor for child nodes.\r
1075\r
1076Arguments:\r
1077 ChildNode - Indicates the node to destroy\r
1078\r
1079Returns:\r
1080 none\r
1081\r
1082--*/\r
1083{\r
1084 ASSERT (ChildNode->Signature == CORE_SECTION_CHILD_SIGNATURE);\r
1085 //\r
1086 // Remove the child from it's list\r
1087 //\r
1088 RemoveEntryList (&ChildNode->Link);\r
1089 \r
1090 if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {\r
1091 //\r
1092 // If it's an encapsulating section, we close the resulting section stream.\r
1093 // CloseSectionStream will free all memory associated with the stream.\r
1094 //\r
797a9d67 1095 CloseSectionStream (ChildNode->EncapsulatedStreamHandle);\r
28a00297 1096 }\r
1097 //\r
1098 // Last, free the child node itself\r
1099 //\r
1100 CoreFreePool (ChildNode);\r
1101} \r
1102\r
1103\r
1104STATIC\r
1105EFI_STATUS\r
1106OpenSectionStreamEx (\r
1107 IN UINTN SectionStreamLength,\r
1108 IN VOID *SectionStream,\r
1109 IN BOOLEAN AllocateBuffer,\r
1110 IN UINT32 AuthenticationStatus, \r
1111 OUT UINTN *SectionStreamHandle\r
1112 )\r
1113/*++\r
1114\r
1115 Routine Description:\r
1116 Worker function. Constructor for section streams.\r
1117\r
1118 Arguments:\r
1119 SectionStreamLength - Size in bytes of the section stream.\r
1120 SectionStream - Buffer containing the new section stream.\r
1121 AllocateBuffer - Indicates whether the stream buffer is to be copied\r
1122 or the input buffer is to be used in place.\r
1123 AuthenticationStatus- Indicates the default authentication status for the\r
1124 new stream.\r
1125 SectionStreamHandle - A pointer to a caller allocated section stream handle.\r
1126\r
1127 Returns:\r
1128 EFI_SUCCESS - Stream was added to stream database.\r
1129 EFI_OUT_OF_RESOURCES - memory allocation failed.\r
1130\r
1131--*/\r
1132{\r
1133 CORE_SECTION_STREAM_NODE *NewStream;\r
1134 EFI_TPL OldTpl;\r
1135 \r
1136 //\r
1137 // Allocate a new stream\r
1138 //\r
1139 NewStream = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_STREAM_NODE));\r
1140 if (NewStream == NULL) {\r
1141 return EFI_OUT_OF_RESOURCES;\r
1142 }\r
1143 \r
1144 if (AllocateBuffer) { \r
1145 //\r
1146 // if we're here, we're double buffering, allocate the buffer and copy the\r
1147 // data in\r
1148 //\r
1149 if (SectionStreamLength > 0) {\r
1150 NewStream->StreamBuffer = CoreAllocateBootServicesPool (SectionStreamLength); \r
1151 if (NewStream->StreamBuffer == NULL) {\r
1152 CoreFreePool (NewStream);\r
1153 return EFI_OUT_OF_RESOURCES;\r
1154 }\r
1155 //\r
1156 // Copy in stream data\r
1157 //\r
1158 CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength);\r
1159 } else {\r
1160 //\r
1161 // It's possible to have a zero length section stream.\r
1162 //\r
1163 NewStream->StreamBuffer = NULL;\r
1164 }\r
1165 } else {\r
1166 //\r
1167 // If were here, the caller has supplied the buffer (it's an internal call)\r
1168 // so just assign the buffer. This happens when we open section streams\r
1169 // as a result of expanding an encapsulating section.\r
1170 //\r
1171 NewStream->StreamBuffer = SectionStream;\r
1172 }\r
1173 \r
1174 //\r
1175 // Initialize the rest of the section stream\r
1176 //\r
1177 NewStream->Signature = CORE_SECTION_STREAM_SIGNATURE;\r
1178 NewStream->StreamHandle = (UINTN) NewStream;\r
1179 NewStream->StreamLength = SectionStreamLength;\r
1180 InitializeListHead (&NewStream->Children);\r
1181 NewStream->AuthenticationStatus = AuthenticationStatus;\r
1182 \r
1183 //\r
1184 // Add new stream to stream list\r
1185 //\r
1186 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
1187 InsertTailList (&mStreamRoot, &NewStream->Link);\r
1188 CoreRestoreTpl (OldTpl);\r
1189\r
1190 *SectionStreamHandle = NewStream->StreamHandle;\r
1191 \r
1192 return EFI_SUCCESS;\r
1193}\r
1194\r
1195\r
1196STATIC\r
1197EFI_STATUS\r
1198FindStreamNode (\r
1199 IN UINTN SearchHandle,\r
1200 OUT CORE_SECTION_STREAM_NODE **FoundStream\r
1201 )\r
1202/*++\r
1203\r
1204 Routine Description:\r
1205 Worker function. Search stream database for requested stream handle.\r
1206\r
1207 Arguments:\r
1208 SearchHandle - Indicates which stream to look for.\r
1209 FoundStream - Output pointer to the found stream.\r
1210\r
1211 Returns:\r
1212 EFI_SUCCESS - StreamHandle was found and *FoundStream contains\r
1213 the stream node.\r
1214 EFI_NOT_FOUND - SearchHandle was not found in the stream database.\r
1215\r
1216--*/\r
1217{ \r
1218 CORE_SECTION_STREAM_NODE *StreamNode;\r
1219 \r
1220 if (!IsListEmpty (&mStreamRoot)) {\r
1221 StreamNode = STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot));\r
1222 for (;;) {\r
1223 if (StreamNode->StreamHandle == SearchHandle) {\r
1224 *FoundStream = StreamNode;\r
1225 return EFI_SUCCESS;\r
1226 } else if (IsNodeAtEnd (&mStreamRoot, &StreamNode->Link)) {\r
1227 break;\r
1228 } else {\r
1229 StreamNode = STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot, &StreamNode->Link));\r
1230 }\r
1231 }\r
1232 }\r
1233 \r
1234 return EFI_NOT_FOUND;\r
1235}\r
1236\r
1237\r
1238STATIC\r
1239BOOLEAN\r
1240IsValidSectionStream (\r
1241 IN VOID *SectionStream,\r
1242 IN UINTN SectionStreamLength\r
1243 )\r
1244/*++\r
1245\r
1246Routine Description:\r
1247 Check if a stream is valid.\r
1248\r
1249Arguments:\r
1250 SectionStream - The section stream to be checked\r
1251 SectionStreamLength - The length of section stream\r
1252\r
1253Returns:\r
1254 TRUE\r
1255 FALSE\r
1256\r
1257--*/\r
1258{\r
1259 UINTN TotalLength;\r
1260 UINTN SectionLength;\r
1261 EFI_COMMON_SECTION_HEADER *SectionHeader;\r
1262 EFI_COMMON_SECTION_HEADER *NextSectionHeader;\r
1263\r
1264 TotalLength = 0;\r
1265 SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream;\r
1266 \r
1267 while (TotalLength < SectionStreamLength) {\r
1268 SectionLength = SECTION_SIZE (SectionHeader);\r
1269 TotalLength += SectionLength;\r
1270\r
1271 if (TotalLength == SectionStreamLength) {\r
1272 return TRUE; \r
1273 }\r
1274\r
1275 //\r
1276 // Move to the next byte following the section...\r
1277 //\r
1278 SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);\r
1279 \r
1280 //\r
1281 // Figure out where the next section begins\r
1282 //\r
1283 NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) SectionHeader + 3);\r
1284 NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader & ~(UINTN)3);\r
1285 TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;\r
1286 SectionHeader = NextSectionHeader;\r
1287 }\r
1288\r
1289 ASSERT (FALSE);\r
1290 return FALSE;\r
1291}\r
d8c79a81
LG
1292\r
1293/**\r
1294 The ExtractSection() function processes the input section and\r
1295 allocates a buffer from the pool in which it returns the section\r
1296 contents. If the section being extracted contains\r
1297 authentication information (the section's\r
1298 GuidedSectionHeader.Attributes field has the\r
1299 EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values\r
1300 returned in AuthenticationStatus must reflect the results of\r
1301 the authentication operation. Depending on the algorithm and\r
1302 size of the encapsulated data, the time that is required to do\r
1303 a full authentication may be prohibitively long for some\r
1304 classes of systems. To indicate this, use\r
1305 EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by\r
1306 the security policy driver (see the Platform Initialization\r
1307 Driver Execution Environment Core Interface Specification for\r
1308 more details and the GUID definition). If the\r
1309 EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle\r
1310 database, then, if possible, full authentication should be\r
1311 skipped and the section contents simply returned in the\r
1312 OutputBuffer. In this case, the\r
1313 EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus\r
1314 must be set on return. ExtractSection() is callable only from\r
1315 TPL_NOTIFY and below. Behavior of ExtractSection() at any\r
1316 EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is\r
1317 defined in RaiseTPL() in the UEFI 2.0 specification.\r
1318\r
1319 \r
1320 @param This Indicates the\r
1321 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.\r
1322 \r
1323 @param InputSection Buffer containing the input GUIDed section\r
1324 to be processed. OutputBuffer OutputBuffer\r
1325 is allocated from boot services pool\r
1326 memory and contains the new section\r
1327 stream. The caller is responsible for\r
1328 freeing this buffer.\r
1329\r
1330 @param OutputSize A pointer to a caller-allocated UINTN in\r
1331 which the size of OutputBuffer allocation\r
1332 is stored. If the function returns\r
1333 anything other than EFI_SUCCESS, the value\r
1334 of OutputSize is undefined.\r
1335\r
1336 @param AuthenticationStatus A pointer to a caller-allocated\r
1337 UINT32 that indicates the\r
1338 authentication status of the\r
1339 output buffer. If the input\r
1340 section's\r
1341 GuidedSectionHeader.Attributes\r
1342 field has the\r
1343 EFI_GUIDED_SECTION_AUTH_STATUS_VAL\r
1344 bit as clear, AuthenticationStatus\r
1345 must return zero. Both local bits\r
1346 (19:16) and aggregate bits (3:0)\r
1347 in AuthenticationStatus are\r
1348 returned by ExtractSection().\r
1349 These bits reflect the status of\r
1350 the extraction operation. The bit\r
1351 pattern in both regions must be\r
1352 the same, as the local and\r
1353 aggregate authentication statuses\r
1354 have equivalent meaning at this\r
1355 level. If the function returns\r
1356 anything other than EFI_SUCCESS,\r
1357 the value of AuthenticationStatus\r
1358 is undefined.\r
1359\r
1360\r
1361 @retval EFI_SUCCESS The InputSection was successfully\r
1362 processed and the section contents were\r
1363 returned.\r
1364\r
1365 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
1366 resources to process the\r
1367 request.\r
1368\r
1369 @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
1370 not match this instance of the\r
1371 GUIDed Section Extraction\r
1372 Protocol.\r
1373\r
1374**/\r
1375EFI_STATUS\r
797a9d67 1376EFIAPI\r
18fd8d65 1377CustomGuidedSectionExtract (\r
d8c79a81
LG
1378 IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,\r
1379 IN CONST VOID *InputSection,\r
1380 OUT VOID **OutputBuffer,\r
1381 OUT UINTN *OutputSize,\r
1382 OUT UINT32 *AuthenticationStatus\r
1383 )\r
1384{\r
1385 EFI_STATUS Status;\r
18fd8d65
LG
1386 VOID *ScratchBuffer;\r
1387 VOID *AllocatedOutputBuffer;\r
1388 UINT32 OutputBufferSize;\r
1389 UINT32 ScratchBufferSize;\r
1390 UINT16 SectionAttribute;\r
d8c79a81
LG
1391 \r
1392 //\r
18fd8d65 1393 // Init local variable\r
d8c79a81 1394 //\r
18fd8d65
LG
1395 ScratchBuffer = NULL;\r
1396 AllocatedOutputBuffer = NULL;\r
1397\r
d8c79a81 1398 //\r
18fd8d65 1399 // Call GetInfo to get the size and attribute of input guided section data.\r
d8c79a81 1400 //\r
18fd8d65
LG
1401 Status = ExtractGuidedSectionGetInfo (\r
1402 InputSection,\r
1403 &OutputBufferSize,\r
1404 &ScratchBufferSize,\r
1405 &SectionAttribute\r
1406 );\r
1407 \r
d8c79a81 1408 if (EFI_ERROR (Status)) {\r
18fd8d65
LG
1409 DEBUG ((EFI_D_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
1410 return Status;\r
1411 }\r
1412 \r
1413 if (ScratchBufferSize != 0) {\r
d8c79a81 1414 //\r
18fd8d65 1415 // Allocate scratch buffer\r
d8c79a81 1416 //\r
18fd8d65
LG
1417 ScratchBuffer = CoreAllocateBootServicesPool (ScratchBufferSize);\r
1418 if (ScratchBuffer == NULL) {\r
1419 return EFI_OUT_OF_RESOURCES;\r
1420 }\r
d8c79a81
LG
1421 }\r
1422\r
18fd8d65
LG
1423 if (OutputBufferSize > 0) { \r
1424 //\r
1425 // Allocate output buffer\r
1426 //\r
1427 AllocatedOutputBuffer = CoreAllocateBootServicesPool (OutputBufferSize);\r
1428 if (AllocatedOutputBuffer == NULL) {\r
1429 return EFI_OUT_OF_RESOURCES;\r
1430 }\r
1431 *OutputBuffer = AllocatedOutputBuffer;\r
d8c79a81
LG
1432 }\r
1433\r
1434 //\r
18fd8d65 1435 // Call decode function to extract raw data from the guided section.\r
d8c79a81 1436 //\r
18fd8d65
LG
1437 Status = ExtractGuidedSectionDecode (\r
1438 InputSection, \r
1439 OutputBuffer,\r
1440 ScratchBuffer,\r
1441 AuthenticationStatus\r
1442 );\r
d8c79a81
LG
1443 if (EFI_ERROR (Status)) {\r
1444 //\r
18fd8d65 1445 // Decode failed\r
d8c79a81 1446 //\r
18fd8d65
LG
1447 if (AllocatedOutputBuffer != NULL) {\r
1448 CoreFreePool (AllocatedOutputBuffer);\r
1449 }\r
1450 if (ScratchBuffer != NULL) {\r
1451 CoreFreePool (ScratchBuffer);\r
1452 }\r
d8c79a81
LG
1453 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));\r
1454 return Status;\r
1455 }\r
18fd8d65
LG
1456\r
1457 if (*OutputBuffer != AllocatedOutputBuffer) {\r
1458 //\r
1459 // OutputBuffer was returned as a different value, \r
1460 // so copy section contents to the allocated memory buffer.\r
1461 // \r
1462 CopyMem (AllocatedOutputBuffer, *OutputBuffer, OutputBufferSize);\r
1463 *OutputBuffer = AllocatedOutputBuffer;\r
1464 }\r
1465\r
1466 //\r
1467 // Set real size of output buffer.\r
1468 //\r
1469 *OutputSize = (UINTN) OutputBufferSize;\r
1470\r
d8c79a81
LG
1471 //\r
1472 // Free unused scratch buffer.\r
1473 //\r
18fd8d65
LG
1474 if (ScratchBuffer != NULL) {\r
1475 CoreFreePool (ScratchBuffer);\r
1476 }\r
1477\r
d8c79a81 1478 return EFI_SUCCESS;\r
702887db 1479}\r