]> git.proxmox.com Git - mirror_edk2.git/blame - EdkUnixPkg/Library/EdkGenericBdsLib/BdsMisc.c
Unix version of EFI emulator
[mirror_edk2.git] / EdkUnixPkg / Library / EdkGenericBdsLib / BdsMisc.c
CommitLineData
c9093a06 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
22#define MAX_STRING_LEN 200\r
23static BOOLEAN mFeaturerSwitch = TRUE;\r
24static BOOLEAN mResetRequired = FALSE;\r
25extern UINT16 gPlatformBootTimeOutDefault;\r
26\r
27UINT16\r
28BdsLibGetTimeout (\r
29 VOID\r
30 )\r
31/*++\r
32\r
33Routine Description:\r
34 \r
35 Return the default value for system Timeout variable.\r
36\r
37Arguments:\r
38\r
39 None\r
40\r
41Returns:\r
42 \r
43 Timeout value.\r
44\r
45--*/\r
46{\r
47 UINT16 Timeout;\r
48 UINTN Size;\r
49 EFI_STATUS Status;\r
50\r
51 //\r
52 // Return Timeout variable or 0xffff if no valid\r
53 // Timeout variable exists.\r
54 //\r
55 Size = sizeof (UINT16);\r
56 Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);\r
57 if (!EFI_ERROR (Status)) {\r
58 return Timeout;\r
59 }\r
60 //\r
61 // To make the current EFI Automatic-Test activity possible, just add\r
62 // following code to make AutoBoot enabled when this variable is not\r
63 // present.\r
64 // This code should be removed later.\r
65 //\r
66 Timeout = gPlatformBootTimeOutDefault;\r
67\r
68 //\r
69 // Notes: Platform should set default variable if non exists on all error cases!!!\r
70 //\r
71 Status = gRT->SetVariable (\r
72 L"Timeout",\r
73 &gEfiGlobalVariableGuid,\r
74 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
75 sizeof (UINT16),\r
76 &Timeout\r
77 );\r
78 return Timeout;\r
79}\r
80\r
81VOID\r
82BdsLibLoadDrivers (\r
83 IN LIST_ENTRY *BdsDriverLists\r
84 )\r
85/*++\r
86\r
87Routine Description:\r
88 \r
89 The function will go through the driver optoin link list, load and start\r
90 every driver the driver optoin device path point to.\r
91\r
92Arguments:\r
93\r
94 BdsDriverLists - The header of the current driver option link list\r
95\r
96Returns:\r
97 \r
98 None\r
99\r
100--*/\r
101{\r
102 EFI_STATUS Status;\r
103 LIST_ENTRY *Link;\r
104 BDS_COMMON_OPTION *Option;\r
105 EFI_HANDLE ImageHandle;\r
106 EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
107 UINTN ExitDataSize;\r
108 CHAR16 *ExitData;\r
109 BOOLEAN ReconnectAll;\r
110\r
111 ReconnectAll = FALSE;\r
112\r
113 //\r
114 // Process the driver option\r
115 //\r
116 for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {\r
117 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
118 //\r
119 // If a load option is not marked as LOAD_OPTION_ACTIVE,\r
120 // the boot manager will not automatically load the option.\r
121 //\r
122 if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {\r
123 continue;\r
124 }\r
125 //\r
126 // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
127 // then all of the EFI drivers in the system will be disconnected and\r
128 // reconnected after the last driver load option is processed.\r
129 //\r
130 if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {\r
131 ReconnectAll = TRUE;\r
132 }\r
133 //\r
134 // Make sure the driver path is connected.\r
135 //\r
136 BdsLibConnectDevicePath (Option->DevicePath);\r
137\r
138 //\r
139 // Load and start the image that Driver#### describes\r
140 //\r
141 Status = gBS->LoadImage (\r
142 FALSE,\r
143 mBdsImageHandle,\r
144 Option->DevicePath,\r
145 NULL,\r
146 0,\r
147 &ImageHandle\r
148 );\r
149\r
150 if (!EFI_ERROR (Status)) {\r
151 gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid,
152 (VOID **)&ImageInfo);\r
153\r
154 //\r
155 // Verify whether this image is a driver, if not,\r
156 // exit it and continue to parse next load option\r
157 //\r
158 if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {\r
159 gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
160 continue;\r
161 }\r
162\r
163 if (Option->LoadOptionsSize != 0) {\r
164 ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
165 ImageInfo->LoadOptions = Option->LoadOptions;\r
166 }\r
167 //\r
168 // Before calling the image, enable the Watchdog Timer for\r
169 // the 5 Minute period\r
170 //\r
171 gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
172\r
173 Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);\r
174 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Driver Return Status = %r\n", Status));\r
175\r
176 //\r
177 // Clear the Watchdog Timer after the image returns\r
178 //\r
179 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
180 }\r
181 }\r
182 //\r
183 // Process the LOAD_OPTION_FORCE_RECONNECT driver option\r
184 //\r
185 if (ReconnectAll) {\r
186 BdsLibDisconnectAllEfi ();\r
187 BdsLibConnectAll ();\r
188 }\r
189\r
190}\r
191\r
192EFI_STATUS\r
193BdsLibRegisterNewOption (\r
194 IN LIST_ENTRY *BdsOptionList,\r
195 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
196 IN CHAR16 *String,\r
197 IN CHAR16 *VariableName\r
198 )\r
199/*++\r
200\r
201Routine Description:\r
202 \r
203 This function will register the new boot#### or driver#### option base on\r
204 the VariableName. The new registered boot#### or driver#### will be linked\r
205 to BdsOptionList and also update to the VariableName. After the boot#### or\r
206 driver#### updated, the BootOrder or DriverOrder will also be updated.\r
207\r
208Arguments:\r
209\r
210 BdsOptionList - The header of the boot#### or driver#### link list\r
211 \r
212 DevicePath - The device path which the boot####\r
213 or driver#### option present\r
214 \r
215 String - The description of the boot#### or driver####\r
216 \r
217 VariableName - Indicate if the boot#### or driver#### option\r
218\r
219Returns:\r
220 \r
221 EFI_SUCCESS - The boot#### or driver#### have been success registered\r
222 \r
223 EFI_STATUS - Return the status of gRT->SetVariable ().\r
224\r
225--*/\r
226{\r
227 EFI_STATUS Status;\r
228 UINTN Index;\r
229 UINT16 MaxOptionNumber;\r
230 UINT16 RegisterOptionNumber;\r
231 UINT16 *TempOptionPtr;\r
232 UINTN TempOptionSize;\r
233 UINT16 *OptionOrderPtr;\r
234 VOID *OptionPtr;\r
235 UINTN OptionSize;\r
236 UINT8 *TempPtr;\r
237 EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
238 CHAR16 *Description;\r
239 CHAR16 OptionName[10];\r
240 BOOLEAN UpdateBootDevicePath;\r
241\r
242 OptionPtr = NULL;\r
243 OptionSize = 0;\r
244 TempPtr = NULL;\r
245 OptionDevicePath = NULL;\r
246 Description = NULL;\r
247 MaxOptionNumber = 0;\r
248 OptionOrderPtr = NULL;\r
249 UpdateBootDevicePath = FALSE;\r
250 ZeroMem (OptionName, sizeof (OptionName));\r
251\r
252 TempOptionSize = 0;\r
253 TempOptionPtr = BdsLibGetVariableAndSize (\r
254 VariableName,\r
255 &gEfiGlobalVariableGuid,\r
256 &TempOptionSize\r
257 );\r
258 //\r
259 // Compare with current option variable\r
260 //\r
261 for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {\r
262 //\r
263 // Got the max option#### number\r
264 //\r
265 if (MaxOptionNumber < TempOptionPtr[Index]) {\r
266 MaxOptionNumber = TempOptionPtr[Index];\r
267 }\r
268\r
269 if (*VariableName == 'B') {\r
270 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);\r
271 } else {\r
272 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);\r
273 }\r
274\r
275 OptionPtr = BdsLibGetVariableAndSize (\r
276 OptionName,\r
277 &gEfiGlobalVariableGuid,\r
278 &OptionSize\r
279 );\r
280 TempPtr = OptionPtr;\r
281 TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
282 Description = (CHAR16 *) TempPtr;\r
283 TempPtr += StrSize ((CHAR16 *) TempPtr);\r
284 OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
285\r
286 //\r
287 // Notes: the description may will change base on the GetStringToken\r
288 //\r
289 if (CompareMem (Description, String, StrSize (Description)) == 0) {\r
290 if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {\r
291 //\r
292 // Got the option, so just return\r
293 //\r
294 gBS->FreePool (OptionPtr);\r
295 gBS->FreePool (TempOptionPtr);\r
296 return EFI_SUCCESS;\r
297 } else {\r
298 //\r
299 // Boot device path changed, need update.\r
300 //\r
301 UpdateBootDevicePath = TRUE;\r
302 break;\r
303 }\r
304 }\r
305\r
306 gBS->FreePool (OptionPtr);\r
307 }\r
308\r
309 OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String) + GetDevicePathSize (DevicePath);\r
310 OptionPtr = AllocateZeroPool (OptionSize);\r
311 TempPtr = OptionPtr;\r
312 *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;\r
313 TempPtr += sizeof (UINT32);\r
314 *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);\r
315 TempPtr += sizeof (UINT16);\r
316 CopyMem (TempPtr, String, StrSize (String));\r
317 TempPtr += StrSize (String);\r
318 CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));\r
319\r
320 if (UpdateBootDevicePath) {\r
321 //\r
322 // The number in option#### to be updated\r
323 //\r
324 RegisterOptionNumber = TempOptionPtr[Index];\r
325 } else {\r
326 //\r
327 // The new option#### number\r
328 //\r
329 RegisterOptionNumber = MaxOptionNumber + 1;\r
330 }\r
331\r
332 if (*VariableName == 'B') {\r
333 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);\r
334 } else {\r
335 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);\r
336 }\r
337\r
338 Status = gRT->SetVariable (\r
339 OptionName,\r
340 &gEfiGlobalVariableGuid,\r
341 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
342 OptionSize,\r
343 OptionPtr\r
344 );\r
345 if (EFI_ERROR (Status) || UpdateBootDevicePath) {\r
346 gBS->FreePool (OptionPtr);\r
347 gBS->FreePool (TempOptionPtr);\r
348 return Status;\r
349 }\r
350\r
351 gBS->FreePool (OptionPtr);\r
352\r
353 //\r
354 // Update the option order variable\r
355 //\r
356 OptionOrderPtr = AllocateZeroPool ((Index + 1) * sizeof (UINT16));\r
357 CopyMem (OptionOrderPtr, TempOptionPtr, Index * sizeof (UINT16));\r
358 OptionOrderPtr[Index] = RegisterOptionNumber;\r
359 Status = gRT->SetVariable (\r
360 VariableName,\r
361 &gEfiGlobalVariableGuid,\r
362 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
363 (Index + 1) * sizeof (UINT16),\r
364 OptionOrderPtr\r
365 );\r
366 if (EFI_ERROR (Status)) {\r
367 gBS->FreePool (TempOptionPtr);\r
368 gBS->FreePool (OptionOrderPtr);\r
369 return Status;\r
370 }\r
371\r
372 gBS->FreePool (TempOptionPtr);\r
373 gBS->FreePool (OptionOrderPtr);\r
374\r
375 return EFI_SUCCESS;\r
376}\r
377\r
378BDS_COMMON_OPTION *\r
379BdsLibVariableToOption (\r
380 IN OUT LIST_ENTRY *BdsCommonOptionList,\r
381 IN CHAR16 *VariableName\r
382 )\r
383/*++\r
384\r
385Routine Description:\r
386\r
387 Build the boot#### or driver#### option from the VariableName, the \r
388 build boot#### or driver#### will also be linked to BdsCommonOptionList\r
389 \r
390Arguments:\r
391\r
392 BdsCommonOptionList - The header of the boot#### or driver#### option link list\r
393\r
394 VariableName - EFI Variable name indicate if it is boot#### or driver####\r
395\r
396Returns:\r
397\r
398 BDS_COMMON_OPTION - Get the option just been created\r
399\r
400 NULL - Failed to get the new option\r
401\r
402--*/\r
403{\r
404 UINT32 Attribute;\r
405 UINT16 FilePathSize;\r
406 UINT8 *Variable;\r
407 UINT8 *TempPtr;\r
408 UINTN VariableSize;\r
409 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
410 BDS_COMMON_OPTION *Option;\r
411 VOID *LoadOptions;\r
412 UINT32 LoadOptionsSize;\r
413 CHAR16 *Description;\r
414\r
415 //\r
416 // Read the variable. We will never free this data.\r
417 //\r
418 Variable = BdsLibGetVariableAndSize (\r
419 VariableName,\r
420 &gEfiGlobalVariableGuid,\r
421 &VariableSize\r
422 );\r
423 if (Variable == NULL) {\r
424 return NULL;\r
425 }\r
426 //\r
427 // Notes: careful defined the variable of Boot#### or\r
428 // Driver####, consider use some macro to abstract the code\r
429 //\r
430 //\r
431 // Get the option attribute\r
432 //\r
433 TempPtr = Variable;\r
434 Attribute = *(UINT32 *) Variable;\r
435 TempPtr += sizeof (UINT32);\r
436\r
437 //\r
438 // Get the option's device path size\r
439 //\r
440 FilePathSize = *(UINT16 *) TempPtr;\r
441 TempPtr += sizeof (UINT16);\r
442\r
443 //\r
444 // Get the option's description string\r
445 //\r
446 Description = (CHAR16 *) TempPtr;\r
447\r
448 //\r
449 // Get the option's description string size\r
450 //\r
451 TempPtr += StrSize ((CHAR16 *) TempPtr);\r
452\r
453 //\r
454 // Get the option's device path\r
455 //\r
456 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
457 TempPtr += FilePathSize;\r
458\r
459 LoadOptions = TempPtr;\r
460 LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));\r
461\r
462 //\r
463 // The Console variables may have multiple device paths, so make\r
464 // an Entry for each one.\r
465 //\r
466 Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));\r
467 if (Option == NULL) {\r
468 return NULL;\r
469 }\r
470\r
471 Option->Signature = BDS_LOAD_OPTION_SIGNATURE;\r
472 Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
473 CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
474 Option->Attribute = Attribute;\r
475 Option->Description = AllocateZeroPool (StrSize (Description));\r
476 CopyMem (Option->Description, Description, StrSize (Description));\r
477 Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);\r
478 CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);\r
479 Option->LoadOptionsSize = LoadOptionsSize;\r
480\r
481 //\r
482 // Insert active entry to BdsDeviceList\r
483 //\r
484 if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {\r
485 InsertTailList (BdsCommonOptionList, &Option->Link);\r
486 gBS->FreePool (Variable);\r
487 return Option;\r
488 }\r
489\r
490 gBS->FreePool (Variable);\r
491 gBS->FreePool (Option);\r
492 return NULL;\r
493\r
494}\r
495\r
496EFI_STATUS\r
497BdsLibBuildOptionFromVar (\r
498 IN LIST_ENTRY *BdsCommonOptionList,\r
499 IN CHAR16 *VariableName\r
500 )\r
501/*++\r
502\r
503Routine Description:\r
504\r
505 Process BootOrder, or DriverOrder variables, by calling\r
506 BdsLibVariableToOption () for each UINT16 in the variables.\r
507\r
508Arguments:\r
509\r
510 BdsCommonOptionList - The header of the option list base on variable\r
511 VariableName\r
512\r
513 VariableName - EFI Variable name indicate the BootOrder or DriverOrder\r
514\r
515Returns:\r
516\r
517 EFI_SUCCESS - Success create the boot option or driver option list\r
518\r
519 EFI_OUT_OF_RESOURCES - Failed to get the boot option or driver option list\r
520\r
521--*/\r
522{\r
523 UINT16 *OptionOrder;\r
524 UINTN OptionOrderSize;\r
525 UINTN Index;\r
526 BDS_COMMON_OPTION *Option;\r
527 CHAR16 OptionName[20];\r
528\r
529 //\r
530 // Zero Buffer in order to get all BOOT#### variables\r
531 //\r
532 ZeroMem (OptionName, sizeof (OptionName));\r
533\r
534 //\r
535 // Read the BootOrder, or DriverOrder variable.\r
536 //\r
537 OptionOrder = BdsLibGetVariableAndSize (\r
538 VariableName,\r
539 &gEfiGlobalVariableGuid,\r
540 &OptionOrderSize\r
541 );\r
542 if (OptionOrder == NULL) {\r
543 return EFI_OUT_OF_RESOURCES;\r
544 }\r
545\r
546 for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {\r
547 if (*VariableName == 'B') {\r
548 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);\r
549 } else {\r
550 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);\r
551 }\r
552 Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName);\r
553 Option->BootCurrent = OptionOrder[Index];\r
554\r
555 }\r
556\r
557 gBS->FreePool (OptionOrder);\r
558\r
559 return EFI_SUCCESS;\r
560}\r
561\r
562EFI_STATUS\r
563BdsLibGetBootMode (\r
564 OUT EFI_BOOT_MODE *BootMode\r
565 )\r
566/*++\r
567\r
568Routine Description:\r
569\r
570 Get boot mode by looking up configuration table and parsing HOB list\r
571\r
572Arguments:\r
573\r
574 BootMode - Boot mode from PEI handoff HOB.\r
575\r
576Returns:\r
577\r
578 EFI_SUCCESS - Successfully get boot mode\r
579 \r
580 EFI_NOT_FOUND - Can not find the current system boot mode\r
581\r
582--*/\r
583{\r
584 EFI_HOB_HANDOFF_INFO_TABLE *HobList;\r
585\r
586 HobList = GetHobList ();\r
587 ASSERT (HobList->Header.HobType == EFI_HOB_TYPE_HANDOFF);\r
588 *BootMode = HobList->BootMode;\r
589\r
590 return EFI_SUCCESS;\r
591}\r
592\r
593VOID *\r
594BdsLibGetVariableAndSize (\r
595 IN CHAR16 *Name,\r
596 IN EFI_GUID *VendorGuid,\r
597 OUT UINTN *VariableSize\r
598 )\r
599/*++\r
600\r
601Routine Description:\r
602\r
603 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
604 buffer, and the size of the buffer. If failure return NULL.\r
605\r
606Arguments:\r
607\r
608 Name - String part of EFI variable name\r
609\r
610 VendorGuid - GUID part of EFI variable name\r
611\r
612 VariableSize - Returns the size of the EFI variable that was read\r
613\r
614Returns:\r
615\r
616 Dynamically allocated memory that contains a copy of the EFI variable.\r
617 Caller is responsible freeing the buffer.\r
618\r
619 NULL - Variable was not read\r
620\r
621--*/\r
622{\r
623 EFI_STATUS Status;\r
624 UINTN BufferSize;\r
625 VOID *Buffer;\r
626\r
627 Buffer = NULL;\r
628\r
629 //\r
630 // Pass in a zero size buffer to find the required buffer size.\r
631 //\r
632 BufferSize = 0;\r
633 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
634 if (Status == EFI_BUFFER_TOO_SMALL) {\r
635 //\r
636 // Allocate the buffer to return\r
637 //\r
638 Buffer = AllocateZeroPool (BufferSize);\r
639 if (Buffer == NULL) {\r
640 return NULL;\r
641 }\r
642 //\r
643 // Read variable into the allocated buffer.\r
644 //\r
645 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
646 if (EFI_ERROR (Status)) {\r
647 BufferSize = 0;\r
648 }\r
649 }\r
650\r
651 *VariableSize = BufferSize;\r
652 return Buffer;\r
653}\r
654\r
655BOOLEAN\r
656BdsLibMatchDevicePaths (\r
657 IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
658 IN EFI_DEVICE_PATH_PROTOCOL *Single\r
659 )\r
660/*++\r
661\r
662Routine Description:\r
663\r
664 Function compares a device path data structure to that of all the nodes of a\r
665 second device path instance.\r
666\r
667Arguments:\r
668\r
669 Multi - A pointer to a multi-instance device path data structure.\r
670\r
671 Single - A pointer to a single-instance device path data structure.\r
672\r
673Returns:\r
674\r
675 TRUE - If the Single is contained within Multi\r
676 \r
677 FALSE - The Single is not match within Multi\r
678 \r
679\r
680--*/\r
681{\r
682 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
683 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
684 UINTN Size;\r
685\r
686 if (!Multi || !Single) {\r
687 return FALSE;\r
688 }\r
689\r
690 DevicePath = Multi;\r
691 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
692\r
693 //\r
694 // Search for the match of 'Single' in 'Multi'\r
695 //\r
696 while (DevicePathInst != NULL) {\r
697 //\r
698 // If the single device path is found in multiple device paths,\r
699 // return success\r
700 //\r
701 if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
702 gBS->FreePool (DevicePathInst);\r
703 return TRUE;\r
704 }\r
705\r
706 gBS->FreePool (DevicePathInst);\r
707 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
708 }\r
709\r
710 return FALSE;\r
711}\r
712\r
713EFI_STATUS\r
714BdsLibOutputStrings (\r
715 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut,\r
716 ...\r
717 )\r
718/*++\r
719\r
720Routine Description:\r
721\r
722 This function prints a series of strings.\r
723\r
724Arguments:\r
725\r
726 ConOut - Pointer to EFI_SIMPLE_TEXT_OUT_PROTOCOL\r
727\r
728 ... - A variable argument list containing series of strings,\r
729 the last string must be NULL.\r
730\r
731Returns:\r
732\r
733 EFI_SUCCESS - Success print out the string using ConOut.\r
734 \r
735 EFI_STATUS - Return the status of the ConOut->OutputString ().\r
736\r
737--*/\r
738{\r
739 VA_LIST args;\r
740 EFI_STATUS Status;\r
741 CHAR16 *String;\r
742\r
743 Status = EFI_SUCCESS;\r
744 VA_START (args, ConOut);\r
745\r
746 while (!EFI_ERROR (Status)) {\r
747 //\r
748 // If String is NULL, then it's the end of the list\r
749 //\r
750 String = VA_ARG (args, CHAR16 *);\r
751 if (!String) {\r
752 break;\r
753 }\r
754\r
755 Status = ConOut->OutputString (ConOut, String);\r
756\r
757 if (EFI_ERROR (Status)) {\r
758 break;\r
759 }\r
760 }\r
761\r
762 return Status;\r
763}\r
764\r
765//\r
766// Following are BDS Lib functions which contain all the code about setup browser reset reminder feature.\r
767// Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser if \r
768// user change any option setting which needs a reset to be effective, and the reset will be applied according to the user selection.\r
769//\r
770\r
771VOID\r
772EnableResetReminderFeature (\r
773 VOID\r
774 )\r
775/*++\r
776\r
777Routine Description:\r
778 \r
779 Enable the setup browser reset reminder feature.\r
780 This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.\r
781\r
782Arguments:\r
783\r
784 VOID\r
785\r
786Returns:\r
787\r
788 VOID\r
789\r
790--*/\r
791{\r
792 mFeaturerSwitch = TRUE;\r
793} \r
794\r
795VOID\r
796DisableResetReminderFeature (\r
797 VOID\r
798 )\r
799/*++\r
800\r
801Routine Description:\r
802 \r
803 Disable the setup browser reset reminder feature.\r
804 This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.\r
805 \r
806Arguments:\r
807\r
808 VOID\r
809\r
810Returns:\r
811\r
812 VOID\r
813\r
814--*/\r
815{\r
816 mFeaturerSwitch = FALSE;\r
817} \r
818\r
819VOID\r
820EnableResetRequired (\r
821 VOID\r
822 )\r
823/*++\r
824\r
825Routine Description:\r
826 \r
827 Record the info that a reset is required.\r
828 A module boolean variable is used to record whether a reset is required. \r
829 \r
830Arguments:\r
831\r
832 VOID\r
833\r
834Returns:\r
835\r
836 VOID\r
837\r
838--*/\r
839{\r
840 mResetRequired = TRUE;\r
841} \r
842\r
843VOID\r
844DisableResetRequired (\r
845 VOID\r
846 )\r
847/*++\r
848\r
849Routine Description:\r
850\r
851 Record the info that no reset is required.\r
852 A module boolean variable is used to record whether a reset is required. \r
853\r
854Arguments:\r
855\r
856 VOID\r
857\r
858Returns:\r
859\r
860 VOID\r
861\r
862--*/\r
863{\r
864 mResetRequired = FALSE;\r
865} \r
866\r
867BOOLEAN\r
868IsResetReminderFeatureEnable (\r
869 VOID\r
870 )\r
871/*++\r
872\r
873Routine Description:\r
874 \r
875 Check whether platform policy enable the reset reminder feature. The default is enabled.\r
876\r
877Arguments:\r
878\r
879 VOID\r
880\r
881Returns:\r
882\r
883 VOID\r
884\r
885--*/\r
886{\r
887 return mFeaturerSwitch;\r
888}\r
889\r
890BOOLEAN\r
891IsResetRequired (\r
892 VOID\r
893 )\r
894/*++\r
895\r
896Routine Description:\r
897 \r
898 Check if user changed any option setting which needs a system reset to be effective.\r
899 \r
900Arguments:\r
901\r
902 VOID\r
903\r
904Returns:\r
905\r
906 VOID\r
907\r
908--*/\r
909{\r
910 return mResetRequired;\r
911}\r
912\r
913VOID\r
914SetupResetReminder (\r
915 VOID\r
916 )\r
917/*++\r
918\r
919Routine Description:\r
920 \r
921 Check whether a reset is needed, and finish the reset reminder feature.\r
922 If a reset is needed, Popup a menu to notice user, and finish the feature \r
923 according to the user selection.\r
924\r
925Arguments:\r
926\r
927 VOID\r
928\r
929Returns:\r
930\r
931 VOID\r
932\r
933--*/\r
934{\r
935 EFI_STATUS Status;\r
936 EFI_FORM_BROWSER_PROTOCOL *Browser;\r
937 EFI_INPUT_KEY Key; \r
938 CHAR16 *StringBuffer1;\r
939 CHAR16 *StringBuffer2; \r
940\r
941\r
942 //\r
943 //check any reset required change is applied? if yes, reset system\r
944 //\r
945 if (IsResetReminderFeatureEnable ()) {\r
946 if (IsResetRequired ()) {\r
947 \r
948 Status = gBS->LocateProtocol (\r
949 &gEfiFormBrowserProtocolGuid,\r
950 NULL,\r
951 (VOID **)&Browser\r
952 ); \r
953 \r
954 StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
955 ASSERT (StringBuffer1 != NULL);\r
956 StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
957 ASSERT (StringBuffer2 != NULL); \r
958 StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");\r
959 StrCpy (StringBuffer2, L"Enter (YES) / Esc (NO)"); \r
960 //\r
961 // Popup a menu to notice user\r
962 // \r
963 do {\r
964 Browser->CreatePopUp (2, TRUE, 0, NULL, &Key, StringBuffer1, StringBuffer2);\r
965 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); \r
966 \r
967 gBS->FreePool (StringBuffer1); \r
968 gBS->FreePool (StringBuffer2); \r
969 //\r
970 // If the user hits the YES Response key, reset\r
971 //\r
972 if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
973 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
974 }\r
975 gST->ConOut->ClearScreen (gST->ConOut);\r
976 } \r
977 } \r
978} \r