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