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