Provide UI for generating Apriori file of PEI or DXE phase. The module order informat...
[mirror_edk2.git] / EdkNt32Pkg / Library / EdkGenericBdsLib / BdsMisc.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 BdsMisc.c\r
15\r
16Abstract:\r
17\r
18 Misc BDS library function\r
19\r
20--*/\r
21\r
22extern UINT16 gPlatformBootTimeOutDefault;\r
23\r
24UINT16\r
25BdsLibGetTimeout (\r
26 VOID\r
27 )\r
28/*++\r
29\r
30Routine Description:\r
31 \r
32 Return the default value for system Timeout variable.\r
33\r
34Arguments:\r
35\r
36 None\r
37\r
38Returns:\r
39 \r
40 Timeout value.\r
41\r
42--*/\r
43{\r
44 UINT16 Timeout;\r
45 UINTN Size;\r
46 EFI_STATUS Status;\r
47\r
48 //\r
49 // Return Timeout variable or 0xffff if no valid\r
50 // Timeout variable exists.\r
51 //\r
52 Size = sizeof (UINT16);\r
53 Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);\r
54 if (!EFI_ERROR (Status)) {\r
55 return Timeout;\r
56 }\r
57 //\r
58 // To make the current EFI Automatic-Test activity possible, just add\r
59 // following code to make AutoBoot enabled when this variable is not\r
60 // present.\r
61 // This code should be removed later.\r
62 //\r
63 Timeout = gPlatformBootTimeOutDefault;\r
64\r
65 //\r
66 // Notes: Platform should set default variable if non exists on all error cases!!!\r
67 //\r
68 Status = gRT->SetVariable (\r
69 L"Timeout",\r
70 &gEfiGlobalVariableGuid,\r
71 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
72 sizeof (UINT16),\r
73 &Timeout\r
74 );\r
75 return Timeout;\r
76}\r
77\r
78VOID\r
79BdsLibLoadDrivers (\r
80 IN LIST_ENTRY *BdsDriverLists\r
81 )\r
82/*++\r
83\r
84Routine Description:\r
85 \r
86 The function will go through the driver optoin link list, load and start\r
87 every driver the driver optoin device path point to.\r
88\r
89Arguments:\r
90\r
91 BdsDriverLists - The header of the current driver option link list\r
92\r
93Returns:\r
94 \r
95 None\r
96\r
97--*/\r
98{\r
99 EFI_STATUS Status;\r
100 LIST_ENTRY *Link;\r
101 BDS_COMMON_OPTION *Option;\r
102 EFI_HANDLE ImageHandle;\r
103 EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
104 UINTN ExitDataSize;\r
105 CHAR16 *ExitData;\r
106 BOOLEAN ReconnectAll;\r
107\r
108 ReconnectAll = FALSE;\r
109\r
110 //\r
111 // Process the driver option\r
112 //\r
113 for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {\r
114 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
115 //\r
116 // If a load option is not marked as LOAD_OPTION_ACTIVE,\r
117 // the boot manager will not automatically load the option.\r
118 //\r
119 if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {\r
120 continue;\r
121 }\r
122 //\r
123 // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
124 // then all of the EFI drivers in the system will be disconnected and\r
125 // reconnected after the last driver load option is processed.\r
126 //\r
127 if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {\r
128 ReconnectAll = TRUE;\r
129 }\r
130 //\r
131 // Make sure the driver path is connected.\r
132 //\r
133 BdsLibConnectDevicePath (Option->DevicePath);\r
134\r
135 //\r
136 // Load and start the image that Driver#### describes\r
137 //\r
138 Status = gBS->LoadImage (\r
139 FALSE,\r
140 mBdsImageHandle,\r
141 Option->DevicePath,\r
142 NULL,\r
143 0,\r
144 &ImageHandle\r
145 );\r
146\r
147 if (!EFI_ERROR (Status)) {\r
148 gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, &ImageInfo);\r
149\r
150 //\r
151 // Verify whether this image is a driver, if not,\r
152 // exit it and continue to parse next load option\r
153 //\r
154 if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {\r
155 gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
156 continue;\r
157 }\r
158\r
159 if (Option->LoadOptionsSize != 0) {\r
160 ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
161 ImageInfo->LoadOptions = Option->LoadOptions;\r
162 }\r
163 //\r
164 // Before calling the image, enable the Watchdog Timer for\r
165 // the 5 Minute period\r
166 //\r
167 gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
168\r
169 Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);\r
170 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Driver Return Status = %r\n", Status));\r
171\r
172 //\r
173 // Clear the Watchdog Timer after the image returns\r
174 //\r
175 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
176 }\r
177 }\r
178 //\r
179 // Process the LOAD_OPTION_FORCE_RECONNECT driver option\r
180 //\r
181 if (ReconnectAll) {\r
182 BdsLibDisconnectAllEfi ();\r
183 BdsLibConnectAll ();\r
184 }\r
185\r
186}\r
187\r
188EFI_STATUS\r
189BdsLibRegisterNewOption (\r
190 IN LIST_ENTRY *BdsOptionList,\r
191 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
192 IN CHAR16 *String,\r
193 IN CHAR16 *VariableName\r
194 )\r
195/*++\r
196\r
197Routine Description:\r
198 \r
199 This function will register the new boot#### or driver#### option base on\r
200 the VariableName. The new registered boot#### or driver#### will be linked\r
201 to BdsOptionList and also update to the VariableName. After the boot#### or\r
202 driver#### updated, the BootOrder or DriverOrder will also be updated.\r
203\r
204Arguments:\r
205\r
206 BdsOptionList - The header of the boot#### or driver#### link list\r
207 \r
208 DevicePath - The device path which the boot####\r
209 or driver#### option present\r
210 \r
211 String - The description of the boot#### or driver####\r
212 \r
213 VariableName - Indicate if the boot#### or driver#### option\r
214\r
215Returns:\r
216 \r
217 EFI_SUCCESS - The boot#### or driver#### have been success registered\r
218 \r
219 EFI_STATUS - Return the status of gRT->SetVariable ().\r
220\r
221--*/\r
222{\r
223 EFI_STATUS Status;\r
224 UINTN Index;\r
225 UINT16 MaxOptionNumber;\r
226 UINT16 RegisterOptionNumber;\r
227 UINT16 *TempOptionPtr;\r
228 UINTN TempOptionSize;\r
229 UINT16 *OptionOrderPtr;\r
230 VOID *OptionPtr;\r
231 UINTN OptionSize;\r
232 UINT8 *TempPtr;\r
233 EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
234 CHAR16 *Description;\r
235 CHAR16 OptionName[10];\r
236 BOOLEAN UpdateBootDevicePath;\r
237\r
238 OptionPtr = NULL;\r
239 OptionSize = 0;\r
240 TempPtr = NULL;\r
241 OptionDevicePath = NULL;\r
242 Description = NULL;\r
243 MaxOptionNumber = 0;\r
244 OptionOrderPtr = NULL;\r
245 UpdateBootDevicePath = FALSE;\r
246 ZeroMem (OptionName, sizeof (OptionName));\r
247\r
248 TempOptionSize = 0;\r
249 TempOptionPtr = BdsLibGetVariableAndSize (\r
250 VariableName,\r
251 &gEfiGlobalVariableGuid,\r
252 &TempOptionSize\r
253 );\r
254 //\r
255 // Compare with current option variable\r
256 //\r
257 for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {\r
258 //\r
259 // Got the max option#### number\r
260 //\r
261 if (MaxOptionNumber < TempOptionPtr[Index]) {\r
262 MaxOptionNumber = TempOptionPtr[Index];\r
263 }\r
264\r
265 if (*VariableName == 'B') {\r
266 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);\r
267 } else {\r
268 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);\r
269 }\r
270\r
271 OptionPtr = BdsLibGetVariableAndSize (\r
272 OptionName,\r
273 &gEfiGlobalVariableGuid,\r
274 &OptionSize\r
275 );\r
276 TempPtr = OptionPtr;\r
277 TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
278 Description = (CHAR16 *) TempPtr;\r
279 TempPtr += StrSize ((CHAR16 *) TempPtr);\r
280 OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
281\r
282 //\r
283 // Notes: the description may will change base on the GetStringToken\r
284 //\r
285 if (CompareMem (Description, String, StrSize (Description)) == 0) {\r
286 if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {\r
287 //\r
288 // Got the option, so just return\r
289 //\r
290 gBS->FreePool (OptionPtr);\r
291 gBS->FreePool (TempOptionPtr);\r
292 return EFI_SUCCESS;\r
293 } else {\r
294 //\r
295 // Boot device path changed, need update.\r
296 //\r
297 UpdateBootDevicePath = TRUE;\r
298 break;\r
299 }\r
300 }\r
301\r
302 gBS->FreePool (OptionPtr);\r
303 }\r
304\r
305 OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String) + GetDevicePathSize (DevicePath);\r
306 OptionPtr = AllocateZeroPool (OptionSize);\r
307 TempPtr = OptionPtr;\r
308 *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;\r
309 TempPtr += sizeof (UINT32);\r
310 *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);\r
311 TempPtr += sizeof (UINT16);\r
312 CopyMem (TempPtr, String, StrSize (String));\r
313 TempPtr += StrSize (String);\r
314 CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));\r
315\r
316 if (UpdateBootDevicePath) {\r
317 //\r
318 // The number in option#### to be updated\r
319 //\r
320 RegisterOptionNumber = TempOptionPtr[Index];\r
321 } else {\r
322 //\r
323 // The new option#### number\r
324 //\r
325 RegisterOptionNumber = MaxOptionNumber + 1;\r
326 }\r
327\r
328 if (*VariableName == 'B') {\r
329 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);\r
330 } else {\r
331 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);\r
332 }\r
333\r
334 Status = gRT->SetVariable (\r
335 OptionName,\r
336 &gEfiGlobalVariableGuid,\r
337 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
338 OptionSize,\r
339 OptionPtr\r
340 );\r
341 if (EFI_ERROR (Status) || UpdateBootDevicePath) {\r
342 gBS->FreePool (OptionPtr);\r
343 gBS->FreePool (TempOptionPtr);\r
344 return Status;\r
345 }\r
346\r
347 gBS->FreePool (OptionPtr);\r
348\r
349 //\r
350 // Update the option order variable\r
351 //\r
352 OptionOrderPtr = AllocateZeroPool ((Index + 1) * sizeof (UINT16));\r
353 CopyMem (OptionOrderPtr, TempOptionPtr, Index * sizeof (UINT16));\r
354 OptionOrderPtr[Index] = RegisterOptionNumber;\r
355 Status = gRT->SetVariable (\r
356 VariableName,\r
357 &gEfiGlobalVariableGuid,\r
358 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
359 (Index + 1) * sizeof (UINT16),\r
360 OptionOrderPtr\r
361 );\r
362 if (EFI_ERROR (Status)) {\r
363 gBS->FreePool (TempOptionPtr);\r
364 gBS->FreePool (OptionOrderPtr);\r
365 return Status;\r
366 }\r
367\r
368 gBS->FreePool (TempOptionPtr);\r
369 gBS->FreePool (OptionOrderPtr);\r
370\r
371 return EFI_SUCCESS;\r
372}\r
373\r
374BDS_COMMON_OPTION *\r
375BdsLibVariableToOption (\r
376 IN OUT LIST_ENTRY *BdsCommonOptionList,\r
377 IN CHAR16 *VariableName\r
378 )\r
379/*++\r
380\r
381Routine Description:\r
382\r
383 Build the boot#### or driver#### option from the VariableName, the \r
384 build boot#### or driver#### will also be linked to BdsCommonOptionList\r
385 \r
386Arguments:\r
387\r
388 BdsCommonOptionList - The header of the boot#### or driver#### option link list\r
389\r
390 VariableName - EFI Variable name indicate if it is boot#### or driver####\r
391\r
392Returns:\r
393\r
394 BDS_COMMON_OPTION - Get the option just been created\r
395\r
396 NULL - Failed to get the new option\r
397\r
398--*/\r
399{\r
400 UINT32 Attribute;\r
401 UINT16 FilePathSize;\r
402 UINT8 *Variable;\r
403 UINT8 *TempPtr;\r
404 UINTN VariableSize;\r
405 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
406 BDS_COMMON_OPTION *Option;\r
407 VOID *LoadOptions;\r
408 UINT32 LoadOptionsSize;\r
409 CHAR16 *Description;\r
410\r
411 //\r
412 // Read the variable. We will never free this data.\r
413 //\r
414 Variable = BdsLibGetVariableAndSize (\r
415 VariableName,\r
416 &gEfiGlobalVariableGuid,\r
417 &VariableSize\r
418 );\r
419 if (Variable == NULL) {\r
420 return NULL;\r
421 }\r
422 //\r
423 // Notes: careful defined the variable of Boot#### or\r
424 // Driver####, consider use some macro to abstract the code\r
425 //\r
426 //\r
427 // Get the option attribute\r
428 //\r
429 TempPtr = Variable;\r
430 Attribute = *(UINT32 *) Variable;\r
431 TempPtr += sizeof (UINT32);\r
432\r
433 //\r
434 // Get the option's device path size\r
435 //\r
436 FilePathSize = *(UINT16 *) TempPtr;\r
437 TempPtr += sizeof (UINT16);\r
438\r
439 //\r
440 // Get the option's description string\r
441 //\r
442 Description = (CHAR16 *) TempPtr;\r
443\r
444 //\r
445 // Get the option's description string size\r
446 //\r
447 TempPtr += StrSize ((CHAR16 *) TempPtr);\r
448\r
449 //\r
450 // Get the option's device path\r
451 //\r
452 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
453 TempPtr += FilePathSize;\r
454\r
455 LoadOptions = TempPtr;\r
456 LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));\r
457\r
458 //\r
459 // The Console variables may have multiple device paths, so make\r
460 // an Entry for each one.\r
461 //\r
462 Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));\r
463 if (Option == NULL) {\r
464 return NULL;\r
465 }\r
466\r
467 Option->Signature = BDS_LOAD_OPTION_SIGNATURE;\r
468 Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
469 CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
470 Option->Attribute = Attribute;\r
471 Option->Description = AllocateZeroPool (StrSize (Description));\r
472 CopyMem (Option->Description, Description, StrSize (Description));\r
473 Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);\r
474 CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);\r
475 Option->LoadOptionsSize = LoadOptionsSize;\r
476\r
477 //\r
478 // Insert active entry to BdsDeviceList\r
479 //\r
480 if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {\r
481 InsertTailList (BdsCommonOptionList, &Option->Link);\r
482 gBS->FreePool (Variable);\r
483 return Option;\r
484 }\r
485\r
486 gBS->FreePool (Variable);\r
487 gBS->FreePool (Option);\r
488 return NULL;\r
489\r
490}\r
491\r
492EFI_STATUS\r
493BdsLibBuildOptionFromVar (\r
494 IN LIST_ENTRY *BdsCommonOptionList,\r
495 IN CHAR16 *VariableName\r
496 )\r
497/*++\r
498\r
499Routine Description:\r
500\r
501 Process BootOrder, or DriverOrder variables, by calling\r
502 BdsLibVariableToOption () for each UINT16 in the variables.\r
503\r
504Arguments:\r
505\r
506 BdsCommonOptionList - The header of the option list base on variable\r
507 VariableName\r
508\r
509 VariableName - EFI Variable name indicate the BootOrder or DriverOrder\r
510\r
511Returns:\r
512\r
513 EFI_SUCCESS - Success create the boot option or driver option list\r
514\r
515 EFI_OUT_OF_RESOURCES - Failed to get the boot option or driver option list\r
516\r
517--*/\r
518{\r
519 UINT16 *OptionOrder;\r
520 UINTN OptionOrderSize;\r
521 UINTN Index;\r
522 BDS_COMMON_OPTION *Option;\r
523 CHAR16 OptionName[20];\r
524\r
525 //\r
526 // Zero Buffer in order to get all BOOT#### variables\r
527 //\r
528 ZeroMem (OptionName, sizeof (OptionName));\r
529\r
530 //\r
531 // Read the BootOrder, or DriverOrder variable.\r
532 //\r
533 OptionOrder = BdsLibGetVariableAndSize (\r
534 VariableName,\r
535 &gEfiGlobalVariableGuid,\r
536 &OptionOrderSize\r
537 );\r
538 if (OptionOrder == NULL) {\r
539 return EFI_OUT_OF_RESOURCES;\r
540 }\r
541\r
542 for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {\r
543 if (*VariableName == 'B') {\r
544 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);\r
545 } else {\r
546 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);\r
547 }\r
548 Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName);\r
549 Option->BootCurrent = OptionOrder[Index];\r
550\r
551 }\r
552\r
553 gBS->FreePool (OptionOrder);\r
554\r
555 return EFI_SUCCESS;\r
556}\r
557\r
558EFI_STATUS\r
559BdsLibGetBootMode (\r
560 OUT EFI_BOOT_MODE *BootMode\r
561 )\r
562/*++\r
563\r
564Routine Description:\r
565\r
566 Get boot mode by looking up configuration table and parsing HOB list\r
567\r
568Arguments:\r
569\r
570 BootMode - Boot mode from PEI handoff HOB.\r
571\r
572Returns:\r
573\r
574 EFI_SUCCESS - Successfully get boot mode\r
575 \r
576 EFI_NOT_FOUND - Can not find the current system boot mode\r
577\r
578--*/\r
579{\r
580 EFI_HOB_HANDOFF_INFO_TABLE *HobList;\r
581\r
582 HobList = GetHobList ();\r
583 ASSERT (HobList->Header.HobType == EFI_HOB_TYPE_HANDOFF);\r
584 *BootMode = HobList->BootMode;\r
585\r
586 return EFI_SUCCESS;\r
587}\r
588\r
589VOID *\r
590BdsLibGetVariableAndSize (\r
591 IN CHAR16 *Name,\r
592 IN EFI_GUID *VendorGuid,\r
593 OUT UINTN *VariableSize\r
594 )\r
595/*++\r
596\r
597Routine Description:\r
598\r
599 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
600 buffer, and the size of the buffer. If failure return NULL.\r
601\r
602Arguments:\r
603\r
604 Name - String part of EFI variable name\r
605\r
606 VendorGuid - GUID part of EFI variable name\r
607\r
608 VariableSize - Returns the size of the EFI variable that was read\r
609\r
610Returns:\r
611\r
612 Dynamically allocated memory that contains a copy of the EFI variable.\r
613 Caller is responsible freeing the buffer.\r
614\r
615 NULL - Variable was not read\r
616\r
617--*/\r
618{\r
619 EFI_STATUS Status;\r
620 UINTN BufferSize;\r
621 VOID *Buffer;\r
622\r
623 Buffer = NULL;\r
624\r
625 //\r
626 // Pass in a zero size buffer to find the required buffer size.\r
627 //\r
628 BufferSize = 0;\r
629 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
630 if (Status == EFI_BUFFER_TOO_SMALL) {\r
631 //\r
632 // Allocate the buffer to return\r
633 //\r
634 Buffer = AllocateZeroPool (BufferSize);\r
635 if (Buffer == NULL) {\r
636 return NULL;\r
637 }\r
638 //\r
639 // Read variable into the allocated buffer.\r
640 //\r
641 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
642 if (EFI_ERROR (Status)) {\r
643 BufferSize = 0;\r
644 }\r
645 }\r
646\r
647 *VariableSize = BufferSize;\r
648 return Buffer;\r
649}\r
650\r
651BOOLEAN\r
652BdsLibMatchDevicePaths (\r
653 IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
654 IN EFI_DEVICE_PATH_PROTOCOL *Single\r
655 )\r
656/*++\r
657\r
658Routine Description:\r
659\r
660 Function compares a device path data structure to that of all the nodes of a\r
661 second device path instance.\r
662\r
663Arguments:\r
664\r
665 Multi - A pointer to a multi-instance device path data structure.\r
666\r
667 Single - A pointer to a single-instance device path data structure.\r
668\r
669Returns:\r
670\r
671 TRUE - If the Single is contained within Multi\r
672 \r
673 FALSE - The Single is not match within Multi\r
674 \r
675\r
676--*/\r
677{\r
678 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
679 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
680 UINTN Size;\r
681\r
682 if (!Multi || !Single) {\r
683 return FALSE;\r
684 }\r
685\r
686 DevicePath = Multi;\r
687 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
688 Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
689\r
690 //\r
691 // Search for the match of 'Single' in 'Multi'\r
692 //\r
693 while (DevicePathInst != NULL) {\r
694 //\r
695 // If the single device path is found in multiple device paths,\r
696 // return success\r
697 //\r
698 if (Size == 0) {\r
699 return FALSE;\r
700 }\r
701\r
702 if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
703 return TRUE;\r
704 }\r
705\r
706 gBS->FreePool (DevicePathInst);\r
707 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
708 Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
709 }\r
710\r
711 return FALSE;\r
712}\r
713\r
714EFI_STATUS\r
715BdsLibOutputStrings (\r
716 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut,\r
717 ...\r
718 )\r
719/*++\r
720\r
721Routine Description:\r
722\r
723 This function prints a series of strings.\r
724\r
725Arguments:\r
726\r
727 ConOut - Pointer to EFI_SIMPLE_TEXT_OUT_PROTOCOL\r
728\r
729 ... - A variable argument list containing series of strings,\r
730 the last string must be NULL.\r
731\r
732Returns:\r
733\r
734 EFI_SUCCESS - Success print out the string using ConOut.\r
735 \r
736 EFI_STATUS - Return the status of the ConOut->OutputString ().\r
737\r
738--*/\r
739{\r
740 VA_LIST args;\r
741 EFI_STATUS Status;\r
742 CHAR16 *String;\r
743\r
744 Status = EFI_SUCCESS;\r
745 VA_START (args, ConOut);\r
746\r
747 while (!EFI_ERROR (Status)) {\r
748 //\r
749 // If String is NULL, then it's the end of the list\r
750 //\r
751 String = VA_ARG (args, CHAR16 *);\r
752 if (!String) {\r
753 break;\r
754 }\r
755\r
756 Status = ConOut->OutputString (ConOut, String);\r
757\r
758 if (EFI_ERROR (Status)) {\r
759 break;\r
760 }\r
761 }\r
762\r
763 return Status;\r
764}\r