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