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