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