Original BdsLibMatchDevicePaths() excludes end node when comparing 2 devices paths...
[people/mcb30/edk2.git] / edk2 / EdkNt32Pkg / Library / EdkGenericBdsLib / BdsMisc.c
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, &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
191 EFI_STATUS\r
192 BdsLibRegisterNewOption (\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
200 Routine 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
207 Arguments:\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
218 Returns:\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
377 BDS_COMMON_OPTION *\r
378 BdsLibVariableToOption (\r
379   IN OUT LIST_ENTRY               *BdsCommonOptionList,\r
380   IN  CHAR16                      *VariableName\r
381   )\r
382 /*++\r
383 \r
384 Routine 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
389 Arguments:\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
395 Returns:\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
495 EFI_STATUS\r
496 BdsLibBuildOptionFromVar (\r
497   IN  LIST_ENTRY                  *BdsCommonOptionList,\r
498   IN  CHAR16                      *VariableName\r
499   )\r
500 /*++\r
501 \r
502 Routine Description:\r
503 \r
504   Process BootOrder, or DriverOrder variables, by calling\r
505   BdsLibVariableToOption () for each UINT16 in the variables.\r
506 \r
507 Arguments:\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
514 Returns:\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
561 EFI_STATUS\r
562 BdsLibGetBootMode (\r
563   OUT EFI_BOOT_MODE       *BootMode\r
564   )\r
565 /*++\r
566 \r
567 Routine Description:\r
568 \r
569   Get boot mode by looking up configuration table and parsing HOB list\r
570 \r
571 Arguments:\r
572 \r
573   BootMode - Boot mode from PEI handoff HOB.\r
574 \r
575 Returns:\r
576 \r
577   EFI_SUCCESS - Successfully get boot mode\r
578   \r
579   EFI_NOT_FOUND - Can not find the current system boot mode\r
580 \r
581 --*/\r
582 {\r
583   EFI_HOB_HANDOFF_INFO_TABLE        *HobList;\r
584 \r
585   HobList = GetHobList ();\r
586   ASSERT (HobList->Header.HobType == EFI_HOB_TYPE_HANDOFF);\r
587   *BootMode = HobList->BootMode;\r
588 \r
589   return EFI_SUCCESS;\r
590 }\r
591 \r
592 VOID *\r
593 BdsLibGetVariableAndSize (\r
594   IN  CHAR16              *Name,\r
595   IN  EFI_GUID            *VendorGuid,\r
596   OUT UINTN               *VariableSize\r
597   )\r
598 /*++\r
599 \r
600 Routine Description:\r
601 \r
602   Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
603   buffer, and the size of the buffer. If failure return NULL.\r
604 \r
605 Arguments:\r
606 \r
607   Name       - String part of EFI variable name\r
608 \r
609   VendorGuid - GUID part of EFI variable name\r
610 \r
611   VariableSize - Returns the size of the EFI variable that was read\r
612 \r
613 Returns:\r
614 \r
615   Dynamically allocated memory that contains a copy of the EFI variable.\r
616   Caller is responsible freeing the buffer.\r
617 \r
618   NULL - Variable was not read\r
619 \r
620 --*/\r
621 {\r
622   EFI_STATUS  Status;\r
623   UINTN       BufferSize;\r
624   VOID        *Buffer;\r
625 \r
626   Buffer = NULL;\r
627 \r
628   //\r
629   // Pass in a zero size buffer to find the required buffer size.\r
630   //\r
631   BufferSize  = 0;\r
632   Status      = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
633   if (Status == EFI_BUFFER_TOO_SMALL) {\r
634     //\r
635     // Allocate the buffer to return\r
636     //\r
637     Buffer = AllocateZeroPool (BufferSize);\r
638     if (Buffer == NULL) {\r
639       return NULL;\r
640     }\r
641     //\r
642     // Read variable into the allocated buffer.\r
643     //\r
644     Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
645     if (EFI_ERROR (Status)) {\r
646       BufferSize = 0;\r
647     }\r
648   }\r
649 \r
650   *VariableSize = BufferSize;\r
651   return Buffer;\r
652 }\r
653 \r
654 BOOLEAN\r
655 BdsLibMatchDevicePaths (\r
656   IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
657   IN  EFI_DEVICE_PATH_PROTOCOL  *Single\r
658   )\r
659 /*++\r
660 \r
661 Routine Description:\r
662 \r
663   Function compares a device path data structure to that of all the nodes of a\r
664   second device path instance.\r
665 \r
666 Arguments:\r
667 \r
668   Multi        - A pointer to a multi-instance device path data structure.\r
669 \r
670   Single       - A pointer to a single-instance device path data structure.\r
671 \r
672 Returns:\r
673 \r
674   TRUE   - If the Single is contained within Multi\r
675   \r
676   FALSE  - The Single is not match within Multi\r
677   \r
678 \r
679 --*/\r
680 {\r
681   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
682   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
683   UINTN                     Size;\r
684 \r
685   if (!Multi || !Single) {\r
686     return FALSE;\r
687   }\r
688 \r
689   DevicePath      = Multi;\r
690   DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);\r
691 \r
692   //\r
693   // Search for the match of 'Single' in 'Multi'\r
694   //\r
695   while (DevicePathInst != NULL) {\r
696     //\r
697     // If the single device path is found in multiple device paths,\r
698     // return success\r
699     //\r
700     if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
701       gBS->FreePool (DevicePathInst);\r
702       return TRUE;\r
703     }\r
704 \r
705     gBS->FreePool (DevicePathInst);\r
706     DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
707   }\r
708 \r
709   return FALSE;\r
710 }\r
711 \r
712 EFI_STATUS\r
713 BdsLibOutputStrings (\r
714   IN EFI_SIMPLE_TEXT_OUT_PROTOCOL   *ConOut,\r
715   ...\r
716   )\r
717 /*++\r
718 \r
719 Routine Description:\r
720 \r
721   This function prints a series of strings.\r
722 \r
723 Arguments:\r
724 \r
725   ConOut               - Pointer to EFI_SIMPLE_TEXT_OUT_PROTOCOL\r
726 \r
727   ...                  - A variable argument list containing series of strings,\r
728                          the last string must be NULL.\r
729 \r
730 Returns:\r
731 \r
732   EFI_SUCCESS          - Success print out the string using ConOut.\r
733   \r
734   EFI_STATUS           - Return the status of the ConOut->OutputString ().\r
735 \r
736 --*/\r
737 {\r
738   VA_LIST     args;\r
739   EFI_STATUS  Status;\r
740   CHAR16      *String;\r
741 \r
742   Status = EFI_SUCCESS;\r
743   VA_START (args, ConOut);\r
744 \r
745   while (!EFI_ERROR (Status)) {\r
746     //\r
747     // If String is NULL, then it's the end of the list\r
748     //\r
749     String = VA_ARG (args, CHAR16 *);\r
750     if (!String) {\r
751       break;\r
752     }\r
753 \r
754     Status = ConOut->OutputString (ConOut, String);\r
755 \r
756     if (EFI_ERROR (Status)) {\r
757       break;\r
758     }\r
759   }\r
760 \r
761   return Status;\r
762 }\r
763 \r
764 //\r
765 //  Following are BDS Lib functions which  contain all the code about setup browser reset reminder feature.\r
766 //  Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser  if \r
767 //  user change any option setting which needs a reset to be effective, and  the reset will be applied according to  the user selection.\r
768 //\r
769 \r
770 VOID\r
771 EnableResetReminderFeature (\r
772   VOID\r
773   )\r
774 /*++\r
775 \r
776 Routine Description:\r
777  \r
778   Enable the setup browser reset reminder feature.\r
779   This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.\r
780 \r
781 Arguments:\r
782 \r
783   VOID\r
784 \r
785 Returns:\r
786 \r
787   VOID\r
788 \r
789 --*/\r
790 {\r
791   mFeaturerSwitch = TRUE;\r
792\r
793 \r
794 VOID\r
795 DisableResetReminderFeature (\r
796   VOID\r
797   )\r
798 /*++\r
799 \r
800 Routine Description:\r
801  \r
802   Disable the setup browser reset reminder feature.\r
803   This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.\r
804   \r
805 Arguments:\r
806 \r
807   VOID\r
808 \r
809 Returns:\r
810 \r
811   VOID\r
812 \r
813 --*/\r
814 {\r
815   mFeaturerSwitch = FALSE;\r
816\r
817 \r
818 VOID\r
819 EnableResetRequired (\r
820   VOID\r
821   )\r
822 /*++\r
823 \r
824 Routine Description:\r
825  \r
826    Record the info that  a reset is required.\r
827    A  module boolean variable is used to record whether a reset is required. \r
828   \r
829 Arguments:\r
830 \r
831   VOID\r
832 \r
833 Returns:\r
834 \r
835   VOID\r
836 \r
837 --*/\r
838 {\r
839   mResetRequired = TRUE;\r
840\r
841 \r
842 VOID\r
843 DisableResetRequired (\r
844   VOID\r
845   )\r
846 /*++\r
847 \r
848 Routine Description:\r
849 \r
850    Record the info that  no reset is required.\r
851    A  module boolean variable is used to record whether a reset is required. \r
852 \r
853 Arguments:\r
854 \r
855   VOID\r
856 \r
857 Returns:\r
858 \r
859   VOID\r
860 \r
861 --*/\r
862 {\r
863   mResetRequired = FALSE;\r
864\r
865 \r
866 BOOLEAN\r
867 IsResetReminderFeatureEnable (\r
868   VOID\r
869   )\r
870 /*++\r
871 \r
872 Routine Description:\r
873  \r
874   Check whether platform policy enable the reset reminder feature. The default is enabled.\r
875 \r
876 Arguments:\r
877 \r
878   VOID\r
879 \r
880 Returns:\r
881 \r
882   VOID\r
883 \r
884 --*/\r
885 {\r
886   return mFeaturerSwitch;\r
887 }\r
888 \r
889 BOOLEAN\r
890 IsResetRequired (\r
891   VOID\r
892   )\r
893 /*++\r
894 \r
895 Routine Description:\r
896  \r
897   Check if  user changed any option setting which needs a system reset to be effective.\r
898   \r
899 Arguments:\r
900 \r
901   VOID\r
902 \r
903 Returns:\r
904 \r
905   VOID\r
906 \r
907 --*/\r
908 {\r
909   return mResetRequired;\r
910 }\r
911 \r
912 VOID\r
913 SetupResetReminder (\r
914   VOID\r
915   )\r
916 /*++\r
917 \r
918 Routine Description:\r
919  \r
920   Check whether a reset is needed, and finish the reset reminder feature.\r
921   If a reset is needed, Popup a menu to notice user, and finish the feature \r
922   according to the user selection.\r
923 \r
924 Arguments:\r
925 \r
926   VOID\r
927 \r
928 Returns:\r
929 \r
930   VOID\r
931 \r
932 --*/\r
933 {\r
934   EFI_STATUS                    Status;\r
935   EFI_FORM_BROWSER_PROTOCOL     *Browser;\r
936   EFI_INPUT_KEY                 Key;  \r
937   CHAR16                        *StringBuffer1;\r
938   CHAR16                        *StringBuffer2;    \r
939 \r
940 \r
941   //\r
942   //check any reset required change is applied? if yes, reset system\r
943   //\r
944   if (IsResetReminderFeatureEnable ()) {\r
945     if (IsResetRequired ()) {\r
946     \r
947       Status = gBS->LocateProtocol (\r
948                       &gEfiFormBrowserProtocolGuid,\r
949                       NULL,\r
950                       &Browser\r
951                       );      \r
952                       \r
953       StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
954       ASSERT (StringBuffer1 != NULL);\r
955       StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
956       ASSERT (StringBuffer2 != NULL);      \r
957       StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");\r
958       StrCpy (StringBuffer2, L"Enter (YES)  /   Esc (NO)");      \r
959       //\r
960       // Popup a menu to notice user\r
961       // \r
962       do {\r
963         Browser->CreatePopUp (2, TRUE, 0, NULL, &Key, StringBuffer1, StringBuffer2);\r
964       } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); \r
965       \r
966       gBS->FreePool (StringBuffer1);      \r
967       gBS->FreePool (StringBuffer2);            \r
968       //\r
969       // If the user hits the YES Response key, reset\r
970       //\r
971       if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
972         gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
973       }\r
974       gST->ConOut->ClearScreen (gST->ConOut);\r
975     } \r
976   } \r
977\r