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