newline added at end
[people/mcb30/edk2.git] / edk2 / EdkUnixPkg / Library / EdkGenericBdsLib / BdsMisc.c.orig
1 /*++\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   BdsMisc.c\r
15 \r
16 Abstract:\r
17 \r
18   Misc BDS library function\r
19 \r
20 --*/\r
21 \r
22 #define MAX_STRING_LEN        200\r
23 static BOOLEAN   mFeaturerSwitch = TRUE;\r
24 static BOOLEAN   mResetRequired  = FALSE;\r
25 extern UINT16 gPlatformBootTimeOutDefault;\r
26 \r
27 UINT16\r
28 BdsLibGetTimeout (\r
29   VOID\r
30   )\r
31 /*++\r
32 \r
33 Routine Description:\r
34   \r
35   Return the default value for system Timeout variable.\r
36 \r
37 Arguments:\r
38 \r
39   None\r
40 \r
41 Returns:\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
81 VOID\r
82 BdsLibLoadDrivers (\r
83   IN LIST_ENTRY               *BdsDriverLists\r
84   )\r
85 /*++\r
86 \r
87 Routine 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
92 Arguments:\r
93 \r
94   BdsDriverLists   - The header of the current driver option link list\r
95 \r
96 Returns:\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
192 EFI_STATUS\r
193 BdsLibRegisterNewOption (\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
201 Routine 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
208 Arguments:\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
219 Returns:\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
378 BDS_COMMON_OPTION *\r
379 BdsLibVariableToOption (\r
380   IN OUT LIST_ENTRY               *BdsCommonOptionList,\r
381   IN  CHAR16                      *VariableName\r
382   )\r
383 /*++\r
384 \r
385 Routine 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
390 Arguments:\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
396 Returns:\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
496 EFI_STATUS\r
497 BdsLibBuildOptionFromVar (\r
498   IN  LIST_ENTRY                  *BdsCommonOptionList,\r
499   IN  CHAR16                      *VariableName\r
500   )\r
501 /*++\r
502 \r
503 Routine Description:\r
504 \r
505   Process BootOrder, or DriverOrder variables, by calling\r
506   BdsLibVariableToOption () for each UINT16 in the variables.\r
507 \r
508 Arguments:\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
515 Returns:\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
562 EFI_STATUS\r
563 BdsLibGetBootMode (\r
564   OUT EFI_BOOT_MODE       *BootMode\r
565   )\r
566 /*++\r
567 \r
568 Routine Description:\r
569 \r
570   Get boot mode by looking up configuration table and parsing HOB list\r
571 \r
572 Arguments:\r
573 \r
574   BootMode - Boot mode from PEI handoff HOB.\r
575 \r
576 Returns:\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
593 VOID *\r
594 BdsLibGetVariableAndSize (\r
595   IN  CHAR16              *Name,\r
596   IN  EFI_GUID            *VendorGuid,\r
597   OUT UINTN               *VariableSize\r
598   )\r
599 /*++\r
600 \r
601 Routine 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
606 Arguments:\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
614 Returns:\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
655 BOOLEAN\r
656 BdsLibMatchDevicePaths (\r
657   IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
658   IN  EFI_DEVICE_PATH_PROTOCOL  *Single\r
659   )\r
660 /*++\r
661 \r
662 Routine 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
667 Arguments:\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
673 Returns:\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   Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
693 \r
694   //\r
695   // Search for the match of 'Single' in 'Multi'\r
696   //\r
697   while (DevicePathInst != NULL) {\r
698     //\r
699     // If the single device path is found in multiple device paths,\r
700     // return success\r
701     //\r
702     if (Size == 0) {\r
703       return FALSE;\r
704     }\r
705 \r
706     if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
707       return TRUE;\r
708     }\r
709 \r
710     gBS->FreePool (DevicePathInst);\r
711     DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
712     Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
713   }\r
714 \r
715   return FALSE;\r
716 }\r
717 \r
718 EFI_STATUS\r
719 BdsLibOutputStrings (\r
720   IN EFI_SIMPLE_TEXT_OUT_PROTOCOL   *ConOut,\r
721   ...\r
722   )\r
723 /*++\r
724 \r
725 Routine Description:\r
726 \r
727   This function prints a series of strings.\r
728 \r
729 Arguments:\r
730 \r
731   ConOut               - Pointer to EFI_SIMPLE_TEXT_OUT_PROTOCOL\r
732 \r
733   ...                  - A variable argument list containing series of strings,\r
734                          the last string must be NULL.\r
735 \r
736 Returns:\r
737 \r
738   EFI_SUCCESS          - Success print out the string using ConOut.\r
739   \r
740   EFI_STATUS           - Return the status of the ConOut->OutputString ().\r
741 \r
742 --*/\r
743 {\r
744   VA_LIST     args;\r
745   EFI_STATUS  Status;\r
746   CHAR16      *String;\r
747 \r
748   Status = EFI_SUCCESS;\r
749   VA_START (args, ConOut);\r
750 \r
751   while (!EFI_ERROR (Status)) {\r
752     //\r
753     // If String is NULL, then it's the end of the list\r
754     //\r
755     String = VA_ARG (args, CHAR16 *);\r
756     if (!String) {\r
757       break;\r
758     }\r
759 \r
760     Status = ConOut->OutputString (ConOut, String);\r
761 \r
762     if (EFI_ERROR (Status)) {\r
763       break;\r
764     }\r
765   }\r
766 \r
767   return Status;\r
768 }\r
769 \r
770 //\r
771 //  Following are BDS Lib functions which  contain all the code about setup browser reset reminder feature.\r
772 //  Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser  if \r
773 //  user change any option setting which needs a reset to be effective, and  the reset will be applied according to  the user selection.\r
774 //\r
775 \r
776 VOID\r
777 EnableResetReminderFeature (\r
778   VOID\r
779   )\r
780 /*++\r
781 \r
782 Routine Description:\r
783  \r
784   Enable the setup browser reset reminder feature.\r
785   This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.\r
786 \r
787 Arguments:\r
788 \r
789   VOID\r
790 \r
791 Returns:\r
792 \r
793   VOID\r
794 \r
795 --*/\r
796 {\r
797   mFeaturerSwitch = TRUE;\r
798\r
799 \r
800 VOID\r
801 DisableResetReminderFeature (\r
802   VOID\r
803   )\r
804 /*++\r
805 \r
806 Routine Description:\r
807  \r
808   Disable the setup browser reset reminder feature.\r
809   This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.\r
810   \r
811 Arguments:\r
812 \r
813   VOID\r
814 \r
815 Returns:\r
816 \r
817   VOID\r
818 \r
819 --*/\r
820 {\r
821   mFeaturerSwitch = FALSE;\r
822\r
823 \r
824 VOID\r
825 EnableResetRequired (\r
826   VOID\r
827   )\r
828 /*++\r
829 \r
830 Routine Description:\r
831  \r
832    Record the info that  a reset is required.\r
833    A  module boolean variable is used to record whether a reset is required. \r
834   \r
835 Arguments:\r
836 \r
837   VOID\r
838 \r
839 Returns:\r
840 \r
841   VOID\r
842 \r
843 --*/\r
844 {\r
845   mResetRequired = TRUE;\r
846\r
847 \r
848 VOID\r
849 DisableResetRequired (\r
850   VOID\r
851   )\r
852 /*++\r
853 \r
854 Routine Description:\r
855 \r
856    Record the info that  no reset is required.\r
857    A  module boolean variable is used to record whether a reset is required. \r
858 \r
859 Arguments:\r
860 \r
861   VOID\r
862 \r
863 Returns:\r
864 \r
865   VOID\r
866 \r
867 --*/\r
868 {\r
869   mResetRequired = FALSE;\r
870\r
871 \r
872 BOOLEAN\r
873 IsResetReminderFeatureEnable (\r
874   VOID\r
875   )\r
876 /*++\r
877 \r
878 Routine Description:\r
879  \r
880   Check whether platform policy enable the reset reminder feature. The default is enabled.\r
881 \r
882 Arguments:\r
883 \r
884   VOID\r
885 \r
886 Returns:\r
887 \r
888   VOID\r
889 \r
890 --*/\r
891 {\r
892   return mFeaturerSwitch;\r
893 }\r
894 \r
895 BOOLEAN\r
896 IsResetRequired (\r
897   VOID\r
898   )\r
899 /*++\r
900 \r
901 Routine Description:\r
902  \r
903   Check if  user changed any option setting which needs a system reset to be effective.\r
904   \r
905 Arguments:\r
906 \r
907   VOID\r
908 \r
909 Returns:\r
910 \r
911   VOID\r
912 \r
913 --*/\r
914 {\r
915   return mResetRequired;\r
916 }\r
917 \r
918 VOID\r
919 SetupResetReminder (\r
920   VOID\r
921   )\r
922 /*++\r
923 \r
924 Routine Description:\r
925  \r
926   Check whether a reset is needed, and finish the reset reminder feature.\r
927   If a reset is needed, Popup a menu to notice user, and finish the feature \r
928   according to the user selection.\r
929 \r
930 Arguments:\r
931 \r
932   VOID\r
933 \r
934 Returns:\r
935 \r
936   VOID\r
937 \r
938 --*/\r
939 {\r
940   EFI_STATUS                    Status;\r
941   EFI_FORM_BROWSER_PROTOCOL     *Browser;\r
942   EFI_INPUT_KEY                 Key;  \r
943   CHAR16                        *StringBuffer1;\r
944   CHAR16                        *StringBuffer2;    \r
945 \r
946 \r
947   //\r
948   //check any reset required change is applied? if yes, reset system\r
949   //\r
950   if (IsResetReminderFeatureEnable ()) {\r
951     if (IsResetRequired ()) {\r
952     \r
953       Status = gBS->LocateProtocol (\r
954                       &gEfiFormBrowserProtocolGuid,\r
955                       NULL,\r
956                       (VOID **)&Browser\r
957                       );      \r
958                       \r
959       StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
960       ASSERT (StringBuffer1 != NULL);\r
961       StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
962       ASSERT (StringBuffer2 != NULL);      \r
963       StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");\r
964       StrCpy (StringBuffer2, L"Enter (YES)  /   Esc (NO)");      \r
965       //\r
966       // Popup a menu to notice user\r
967       // \r
968       do {\r
969         Browser->CreatePopUp (2, TRUE, 0, NULL, &Key, StringBuffer1, StringBuffer2);\r
970       } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); \r
971       \r
972       gBS->FreePool (StringBuffer1);      \r
973       gBS->FreePool (StringBuffer2);            \r
974       //\r
975       // If the user hits the YES Response key, reset\r
976       //\r
977       if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
978         gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
979       }\r
980       gST->ConOut->ClearScreen (gST->ConOut);\r
981     } \r
982   } \r
983\r