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