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