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