]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.c
11b3d32f4c6873fec9e0a6d5639ab079749deaca
[mirror_edk2.git] / MdeModulePkg / Application / PlatOverMngr / PlatOverMngr.c
1 /** @file
2
3 Copyright (c) 2007 - 2008, 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 PlatOverMngr.c
15
16 Abstract:
17
18 A UI driver to offer a UI interface in device manager to let user configue
19 platform override protocol to override the default algorithm for matching
20 drivers to controllers.
21
22 The main flow:
23 1. The UI driver dynamicly locate all controller device path.
24 2. The UI driver dynamicly locate all drivers which support binding protocol.
25 3. The UI driver export and dynamicly update two menu to let user select the
26 mapping between drivers to controllers.
27 4. The UI driver save all the mapping info in NV variables which will be consumed
28 by platform override protocol driver to publish the platform override protocol.
29
30 **/
31
32 #include "PlatOverMngr.h"
33
34 STATIC EFI_GUID mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID;
35
36 STATIC LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);
37
38 STATIC EFI_HANDLE *mDevicePathHandleBuffer;
39 STATIC EFI_HANDLE *mDriverImageHandleBuffer;
40 STATIC EFI_HANDLE mSelectedCtrDPHandle;
41
42 STATIC CFG_PROTOCOL_INVOKER_CHOICE mChoice[MAX_CHOICE_NUM];
43
44 STATIC UINTN mSelectedCtrIndex;
45 STATIC EFI_STRING_ID mControllerToken[MAX_CHOICE_NUM];
46
47 STATIC UINTN mDriverImageHandleCount;
48 STATIC EFI_STRING_ID mDriverImageToken[MAX_CHOICE_NUM];
49 STATIC EFI_STRING_ID mDriverImageFilePathToken[MAX_CHOICE_NUM];
50 STATIC EFI_LOADED_IMAGE_PROTOCOL *mDriverImageProtocol[MAX_CHOICE_NUM];
51 STATIC EFI_DEVICE_PATH_PROTOCOL *mControllerDevicePathProtocol[MAX_CHOICE_NUM];
52 STATIC UINTN mSelectedDriverImageNum;
53 STATIC UINTN mLastSavedDriverImageNum;
54 STATIC CHAR8 mLanguage[RFC_3066_ENTRY_SIZE];
55 STATIC UINT16 mCurrentPage;
56
57 /**
58 The driver Entry Point. The funciton will export a disk device class formset and
59 its callback function to hii database.
60
61 @param ImageHandle The firmware allocated handle for the EFI image.
62 @param SystemTable A pointer to the EFI System Table.
63
64 @retval EFI_SUCCESS The entry point is executed successfully.
65 @retval other Some error occurs when executing this entry point.
66
67 **/
68 EFI_STATUS
69 EFIAPI
70 PlatOverMngrInit (
71 IN EFI_HANDLE ImageHandle,
72 IN EFI_SYSTEM_TABLE *SystemTable
73 )
74 {
75 EFI_STATUS Status;
76 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
77 EFI_HII_PACKAGE_LIST_HEADER *PackageList;
78 EFI_CALLBACK_INFO *CallbackInfo;
79 EFI_HANDLE DriverHandle;
80 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
81
82 //
83 // There should only be one HII protocol
84 //
85 Status = gBS->LocateProtocol (
86 &gEfiHiiDatabaseProtocolGuid,
87 NULL,
88 (VOID **) &HiiDatabase
89 );
90 if (EFI_ERROR (Status)) {
91 return Status ;
92 }
93
94
95 //
96 // There should only be one Form Configuration protocol
97 //
98 Status = gBS->LocateProtocol (
99 &gEfiFormBrowser2ProtocolGuid,
100 NULL,
101 (VOID **) &FormBrowser2
102 );
103 if (EFI_ERROR (Status)) {
104 return Status;;
105 }
106
107
108 CallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO));
109 if (CallbackInfo == NULL) {
110 return EFI_BAD_BUFFER_SIZE;
111 }
112
113 CallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;
114 CallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig;
115 CallbackInfo->ConfigAccess.RouteConfig = PlatOverMngrRouteConfig;
116 CallbackInfo->ConfigAccess.Callback = PlatOverMngrCallback;
117
118 //
119 // Create driver handle used by HII database
120 //
121 Status = HiiLibCreateHiiDriverHandle (&DriverHandle);
122 if (EFI_ERROR (Status)) {
123 return Status;
124 }
125 CallbackInfo->DriverHandle = DriverHandle;
126
127 //
128 // Install Config Access protocol to driver handle
129 //
130 Status = gBS->InstallProtocolInterface (
131 &DriverHandle,
132 &gEfiHiiConfigAccessProtocolGuid,
133 EFI_NATIVE_INTERFACE,
134 &CallbackInfo->ConfigAccess
135 );
136 if (EFI_ERROR (Status)) {
137 return Status;
138 }
139
140 //
141 // Publish our HII data
142 //
143 PackageList = HiiLibPreparePackageList (
144 2,
145 &mPlatformOverridesManagerGuid,
146 VfrBin,
147 PlatOverMngrStrings
148 );
149 ASSERT (PackageList != NULL);
150
151 Status = HiiDatabase->NewPackageList (
152 HiiDatabase,
153 PackageList,
154 DriverHandle,
155 &CallbackInfo->RegisteredHandle
156 );
157 gBS->FreePool (PackageList);
158
159 //
160 // Locate ConfigRouting protocol
161 //
162 Status = gBS->LocateProtocol (
163 &gEfiHiiConfigRoutingProtocolGuid,
164 NULL,
165 (VOID **) &CallbackInfo->HiiConfigRouting
166 );
167 if (EFI_ERROR (Status)) {
168 return Status;
169 }
170
171 //
172 // Clear all the globle variable
173 //
174 mDriverImageHandleCount = 0;
175 mCurrentPage = 0;
176 ZeroMem (mDriverImageToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));
177 ZeroMem (mDriverImageFilePathToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));
178 ZeroMem (mControllerToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));
179 ZeroMem (mDriverImageProtocol, MAX_CHOICE_NUM * sizeof (EFI_LOADED_IMAGE_PROTOCOL *));
180
181 //
182 // Show the page
183 //
184 Status = FormBrowser2->SendForm (
185 FormBrowser2,
186 &CallbackInfo->RegisteredHandle,
187 1,
188 NULL,
189 0,
190 NULL,
191 NULL
192 );
193
194 Status = HiiDatabase->RemovePackageList (HiiDatabase, CallbackInfo->RegisteredHandle);
195 if (EFI_ERROR (Status)) {
196 return Status;
197 }
198
199 return EFI_SUCCESS;
200 }
201
202 /**
203 Do some convertion for the ComponentName2 supported language. It do
204 the convertion just for english language code currently.
205
206 @param ComponentName Pointer to the ComponentName2 protocl pointer.
207 @param Language The language string.
208
209 @return Return the duplication of Language if it is not english otherwise return
210 the supported english language code.
211
212 **/
213 CHAR8 *
214 ConvertComponentName2SupportLanguage (
215 IN EFI_COMPONENT_NAME2_PROTOCOL *ComponentName,
216 IN CHAR8 *Language
217 )
218 {
219 CHAR8 *SupportedLanguages;
220 CHAR8 *LangCode;
221 UINTN Index;
222
223 LangCode = NULL;
224 SupportedLanguages = NULL;
225
226 //
227 // treat all the english language code (en-xx or eng) equally
228 //
229 if ((AsciiStrnCmp (Language, "en-", 3) == 0) || (AsciiStrCmp (Language, "eng") == 0)) {
230 SupportedLanguages = AsciiStrStr (ComponentName->SupportedLanguages, "en");
231 if (SupportedLanguages == NULL) {
232 SupportedLanguages = AsciiStrStr (ComponentName->SupportedLanguages, "eng");
233 }
234 }
235
236 //
237 // duplicate the Language if it is not english
238 //
239 if (SupportedLanguages == NULL) {
240 SupportedLanguages = Language;
241 }
242
243 //
244 // duplicate the returned language code.
245 //
246 if (AsciiStrStr (SupportedLanguages, "-") != NULL) {
247 LangCode = AllocateZeroPool(32);
248 for(Index = 0; (Index < 31) && (SupportedLanguages[Index] != '\0') && (SupportedLanguages[Index] != ';'); Index++) {
249 LangCode[Index] = SupportedLanguages[Index];
250 }
251 LangCode[Index] = '\0';
252 } else {
253 LangCode = AllocateZeroPool(4);
254 for(Index = 0; (Index < 3) && (SupportedLanguages[Index] != '\0'); Index++) {
255 LangCode[Index] = SupportedLanguages[Index];
256 }
257 LangCode[Index] = '\0';
258 }
259 return LangCode;
260 }
261
262 /**
263 Get the ComponentName or ComponentName2 protocol according to the driver binding handle
264
265 @param DriverBindingHandle The Handle of DriverBinding.
266
267 @retval !NULL Pointer into the image name if the image name is found,
268 @retval NULL Pointer to NULL if the image name is not found.
269
270 **/
271 CHAR16 *
272 GetComponentName (
273 IN EFI_HANDLE DriverBindingHandle
274 )
275 {
276 EFI_STATUS Status;
277 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
278 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
279 CHAR8 *SupportedLanguage;
280 CHAR16 *DriverName;
281
282 ComponentName = NULL;
283 ComponentName2 = NULL;
284 Status = gBS->OpenProtocol (
285 DriverBindingHandle,
286 &gEfiComponentName2ProtocolGuid,
287 (VOID **) &ComponentName2,
288 NULL,
289 NULL,
290 EFI_OPEN_PROTOCOL_GET_PROTOCOL
291 );
292 if (EFI_ERROR(Status)) {
293 Status = gBS->OpenProtocol (
294 DriverBindingHandle,
295 &gEfiComponentNameProtocolGuid,
296 (VOID **) &ComponentName,
297 NULL,
298 NULL,
299 EFI_OPEN_PROTOCOL_GET_PROTOCOL
300 );
301 }
302
303 Status = EFI_SUCCESS;
304 DriverName = NULL;
305 if (ComponentName != NULL) {
306 if (ComponentName->GetDriverName != NULL) {
307 Status = ComponentName->GetDriverName (
308 ComponentName,
309 mLanguage,
310 &DriverName
311 );
312 }
313 } else if (ComponentName2 != NULL) {
314 if (ComponentName2->GetDriverName != NULL) {
315 SupportedLanguage = ConvertComponentName2SupportLanguage (ComponentName2, mLanguage);
316 Status = ComponentName2->GetDriverName (
317 ComponentName2,
318 SupportedLanguage,
319 &DriverName
320 );
321 gBS->FreePool (SupportedLanguage);
322 }
323 }
324 if (EFI_ERROR (Status)) {
325 return NULL;
326 }
327
328 return DriverName;
329 }
330
331 /**
332 Get the image name
333
334 @param Image Image to search.
335
336 @retval !NULL Pointer into the image name if the image name is found,
337 @retval NULL Pointer to NULL if the image name is not found.
338
339 **/
340 CHAR16 *
341 GetImageName (
342 EFI_LOADED_IMAGE_PROTOCOL *Image
343 )
344 {
345 EFI_STATUS Status;
346 EFI_DEVICE_PATH_PROTOCOL *DevPath;
347 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
348 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
349 VOID *Buffer;
350 UINTN BufferSize;
351 UINT32 AuthenticationStatus;
352 EFI_GUID *NameGuid;
353 EFI_FIRMWARE_VOLUME2_PROTOCOL *FV2;
354
355 FV2 = NULL;
356 Buffer = NULL;
357 BufferSize = 0;
358
359 if (Image->FilePath == NULL) {
360 return NULL;
361 }
362
363 DevPath = UnpackDevicePath (Image->FilePath);
364
365 if (DevPath == NULL) {
366 return NULL;
367 }
368
369 DevPathNode = DevPath;
370
371 while (!IsDevicePathEnd (DevPathNode)) {
372 //
373 // Find the Fv File path
374 //
375 NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevPathNode);
376 if (NameGuid != NULL) {
377 FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevPathNode;
378 Status = gBS->HandleProtocol (
379 Image->DeviceHandle,
380 &gEfiFirmwareVolume2ProtocolGuid,
381 (VOID **) &FV2
382 );
383 if (!EFI_ERROR (Status)) {
384 Status = FV2->ReadSection (
385 FV2,
386 &FvFilePath->FvFileName,
387 EFI_SECTION_USER_INTERFACE,
388 0,
389 &Buffer,
390 &BufferSize,
391 &AuthenticationStatus
392 );
393 if (!EFI_ERROR (Status)) {
394 break;
395 }
396 Buffer = NULL;
397 }
398 }
399 //
400 // Next device path node
401 //
402 DevPathNode = NextDevicePathNode (DevPathNode);
403 }
404
405 gBS->FreePool (DevPath);
406 return Buffer;
407 }
408
409 /**
410 Prepare the first page to let user select the device controller which need to
411 add mapping drivers.
412
413 @param Private Pointer to EFI_CALLBACK_INFO.
414 @param KeyValue The callback key value of device controller item in first page.
415 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
416
417 @retval EFI_SUCCESS Always returned.
418
419 **/
420 EFI_STATUS
421 UpdateDeviceSelectPage (
422 IN EFI_CALLBACK_INFO *Private,
423 IN UINT16 KeyValue,
424 IN PLAT_OVER_MNGR_DATA *FakeNvData
425 )
426 {
427 EFI_HII_UPDATE_DATA UpdateData;
428 EFI_STATUS Status;
429 UINTN LangSize;
430 UINTN Index;
431 UINTN DevicePathHandleCount;
432 CHAR16 *NewString;
433 EFI_STRING_ID NewStringToken;
434 CHAR16 *ControllerName;
435 EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;
436 EFI_PCI_IO_PROTOCOL *PciIo;
437 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
438 UINTN Len;
439
440 mCurrentPage = FORM_ID_DEVICE;
441 //
442 // Following code will be run if user select 'Refresh' in first page
443 // During first page, user will see all currnet controller device path in system,
444 // select any device path will go to second page to select its overrides drivers
445 //
446
447 LangSize = RFC_3066_ENTRY_SIZE;
448 Status = gRT->GetVariable (
449 L"PlatformLang",
450 &gEfiGlobalVariableGuid,
451 NULL,
452 &LangSize,
453 mLanguage
454 );
455 ASSERT_EFI_ERROR (Status);
456
457 //
458 // Initial the mapping database in memory
459 //
460 FreeMappingDatabase (&mMappingDataBase);
461 Status = InitOverridesMapping (&mMappingDataBase);
462
463 //
464 // Clear all the content in the first page
465 //
466 UpdateData.BufferSize = UPDATE_DATA_SIZE;
467 UpdateData.Offset = 0;
468 UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);
469 ASSERT (UpdateData.Data != NULL);
470 //
471 // Clear first page form
472 //
473 IfrLibUpdateForm (
474 Private->RegisteredHandle,
475 &mPlatformOverridesManagerGuid,
476 FORM_ID_DEVICE,
477 FORM_ID_DEVICE,
478 FALSE,
479 &UpdateData
480 );
481
482 //
483 // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,
484 // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement
485 //
486 NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH);
487 HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH), &NewString);
488 ASSERT (NewString != NULL);
489 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);
490 ASSERT_EFI_ERROR (Status);
491 gBS->FreePool (NewString);
492
493 NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH_HELP);
494 HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH_HELP), &NewString);
495 ASSERT (NewString != NULL);
496 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);
497 ASSERT_EFI_ERROR (Status);
498 gBS->FreePool (NewString);
499 //
500 // created needed controller device item in first page
501 //
502 DevicePathHandleCount = 0;
503 Status = gBS->LocateHandleBuffer (
504 ByProtocol,
505 &gEfiDevicePathProtocolGuid,
506 NULL,
507 &DevicePathHandleCount,
508 &mDevicePathHandleBuffer
509 );
510 if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) {
511 return EFI_SUCCESS;
512 }
513
514 for (Index = 0; Index < DevicePathHandleCount; Index++) {
515 if (FakeNvData->PciDeviceFilter == 0x01) {
516 //
517 // Only care PCI device which contain efi driver in its option rom.
518 //
519
520 //
521 // Check whether it is a pci device
522 //
523 ControllerDevicePath = NULL;
524 Status = gBS->OpenProtocol (
525 mDevicePathHandleBuffer[Index],
526 &gEfiPciIoProtocolGuid,
527 (VOID **) &PciIo,
528 NULL,
529 NULL,
530 EFI_OPEN_PROTOCOL_GET_PROTOCOL
531 );
532 if (EFI_ERROR (Status)) {
533 continue;
534 }
535 //
536 // Check whether it contain efi driver in its option rom
537 //
538 Status = gBS->HandleProtocol(
539 mDevicePathHandleBuffer[Index],
540 &gEfiBusSpecificDriverOverrideProtocolGuid,
541 (VOID **) &BusSpecificDriverOverride
542 );
543 if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {
544 continue;
545 }
546 }
547
548 ControllerDevicePath = NULL;
549 Status = gBS->OpenProtocol (
550 mDevicePathHandleBuffer[Index],
551 &gEfiDevicePathProtocolGuid,
552 (VOID **) &ControllerDevicePath,
553 NULL,
554 NULL,
555 EFI_OPEN_PROTOCOL_GET_PROTOCOL
556 );
557 ASSERT_EFI_ERROR (Status);
558 //
559 // Save the device path protocol interface
560 //
561 mControllerDevicePathProtocol[Index] = ControllerDevicePath;
562
563 //
564 // Get the driver name
565 //
566 ControllerName = DevicePathToStr (ControllerDevicePath);
567
568 //
569 // Export the driver name string and create item in set options page
570 //
571 Len = StrSize (ControllerName);
572 NewString = AllocateZeroPool (Len + StrSize (L"--"));
573 if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) {
574 StrCat (NewString, L"--");
575 } else {
576 StrCat (NewString, L"**");
577 }
578 StrCat (NewString, ControllerName);
579
580 NewStringToken = mControllerToken[Index];
581 if (NewStringToken == 0) {
582 Status = HiiLibNewString (Private->RegisteredHandle, &NewStringToken, NewString);
583 } else {
584 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);
585 }
586 ASSERT_EFI_ERROR (Status);
587 gBS->FreePool (NewString);
588 //
589 // Save the device path string toke for next access use
590 //
591 mControllerToken[Index] = NewStringToken;
592
593 CreateGotoOpCode (
594 FORM_ID_DRIVER,
595 NewStringToken,
596 STRING_TOKEN (STR_GOTO_HELP_DRIVER),
597 EFI_IFR_FLAG_CALLBACK,
598 (UINT16) (Index + KEY_VALUE_DEVICE_OFFSET),
599 &UpdateData
600 );
601 }
602
603 //
604 // Update first page form
605 //
606 IfrLibUpdateForm (
607 Private->RegisteredHandle,
608 &mPlatformOverridesManagerGuid,
609 FORM_ID_DEVICE,
610 FORM_ID_DEVICE,
611 FALSE,
612 &UpdateData
613 );
614
615 gBS->FreePool (UpdateData.Data);
616 return EFI_SUCCESS;
617 }
618
619 /**
620 Prepare to let user select the drivers which need mapping with the device controller
621 selected in first page.
622
623 @param Private Pointer to EFI_CALLBACK_INFO.
624 @param KeyValue The callback key value of device controller item in first page.
625 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
626
627 @retval EFI_SUCCESS Always returned.
628
629 **/
630 EFI_STATUS
631 UpdateBindingDriverSelectPage (
632 IN EFI_CALLBACK_INFO *Private,
633 IN UINT16 KeyValue,
634 IN PLAT_OVER_MNGR_DATA *FakeNvData
635 )
636 {
637 EFI_HII_UPDATE_DATA UpdateData;
638 EFI_STATUS Status;
639 UINTN Index;
640
641 CHAR16 *NewString;
642 EFI_STRING_ID NewStringToken;
643 EFI_STRING_ID NewStringHelpToken;
644 UINTN DriverImageHandleCount;
645
646 EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface;
647 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
648 CHAR16 *DriverName;
649 BOOLEAN FreeDriverName;
650
651 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
652 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
653 EFI_HANDLE DriverBindingHandle;
654 //
655 // If user select a controller item in the first page the following code will be run.
656 // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown
657 //
658 //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols
659 // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.
660 // then use the Component Name Protocol on the same handle as the first matching Driver Binding Protocol to look up the name of the driver.
661 //
662
663 mCurrentPage = FORM_ID_DRIVER;
664 //
665 // Switch the item callback key value to its NO. in mDevicePathHandleBuffer
666 //
667 mSelectedCtrIndex = KeyValue - 0x100;
668 ASSERT (mSelectedCtrIndex < MAX_CHOICE_NUM);
669 mLastSavedDriverImageNum = 0;
670 //
671 // Clear all the content in dynamic page
672 //
673 UpdateData.BufferSize = UPDATE_DATA_SIZE;
674 UpdateData.Offset = 0;
675 UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);
676 ASSERT (UpdateData.Data != NULL);
677 //
678 // Clear second page form
679 //
680 IfrLibUpdateForm (
681 Private->RegisteredHandle,
682 &mPlatformOverridesManagerGuid,
683 FORM_ID_DRIVER,
684 FORM_ID_DRIVER,
685 FALSE,
686 &UpdateData
687 );
688
689 //
690 // Show all driver which support loaded image protocol in second page
691 //
692 DriverImageHandleCount = 0;
693 Status = gBS->LocateHandleBuffer (
694 ByProtocol,
695 &gEfiLoadedImageProtocolGuid,
696 NULL,
697 &DriverImageHandleCount,
698 &mDriverImageHandleBuffer
699 );
700 if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) {
701 return EFI_NOT_FOUND;
702 }
703
704 mDriverImageHandleCount = DriverImageHandleCount;
705 for (Index = 0; Index < DriverImageHandleCount; Index++) {
706 //
707 // Step1: Get the driver image total file path for help string and the driver name.
708 //
709
710 //
711 // Find driver's Loaded Image protocol
712 //
713 LoadedImage =NULL;
714
715 Status = gBS->OpenProtocol (
716 mDriverImageHandleBuffer[Index],
717 &gEfiLoadedImageProtocolGuid,
718 (VOID **) &LoadedImage,
719 NULL,
720 NULL,
721 EFI_OPEN_PROTOCOL_GET_PROTOCOL
722 );
723 if (EFI_ERROR (Status)) {
724 FakeNvData->DriSelection[Index] = 0x00;
725 continue;
726 }
727 mDriverImageProtocol[Index] = LoadedImage;
728 //
729 // Find its related driver binding protocol
730 //
731 DriverBindingInterface = NULL;
732 DriverBindingHandle = NULL;
733 DriverBindingInterface = GetBindingProtocolFromImageHandle (
734 mDriverImageHandleBuffer[Index],
735 &DriverBindingHandle
736 );
737 if (DriverBindingInterface == NULL) {
738 FakeNvData->DriSelection[Index] = 0x00;
739 continue;
740 }
741
742 //
743 // Get the EFI Loaded Image Device Path Protocol
744 //
745 LoadedImageDevicePath = NULL;
746 Status = gBS->HandleProtocol (
747 mDriverImageHandleBuffer[Index],
748 &gEfiLoadedImageDevicePathProtocolGuid,
749 (VOID **) &LoadedImageDevicePath
750 );
751 if (LoadedImageDevicePath == NULL) {
752 FakeNvData->DriSelection[Index] = 0x00;
753 continue;
754 }
755
756 if (FakeNvData->PciDeviceFilter == 0x01) {
757 //
758 // only care the driver which is in a Pci device option rom,
759 // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom
760 //
761 if (!EFI_ERROR (Status)) {
762 Status = gBS->HandleProtocol(
763 LoadedImage->DeviceHandle,
764 &gEfiBusSpecificDriverOverrideProtocolGuid,
765 (VOID **) &BusSpecificDriverOverride
766 );
767 if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {
768 FakeNvData->DriSelection[Index] = 0x00;
769 continue;
770 }
771 } else {
772 FakeNvData->DriSelection[Index] = 0x00;
773 continue;
774 }
775 }
776
777 //
778 // For driver name, try to get its component name, if fail, get its image name,
779 // if also fail, give a default name.
780 //
781 FreeDriverName = FALSE;
782 DriverName = GetComponentName (DriverBindingHandle);
783 if (DriverName == NULL) {
784 //
785 // get its image name
786 //
787 DriverName = GetImageName (LoadedImage);
788 }
789 if (DriverName == NULL) {
790 //
791 // give a default name
792 //
793 HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME), &DriverName);
794 ASSERT (DriverName != NULL);
795 FreeDriverName = TRUE; // the DriverName string need to free pool
796 }
797
798
799 //
800 // Step2 Export the driver name string and create check box item in second page
801 //
802
803 //
804 // First create the driver image name
805 //
806 NewString = AllocateZeroPool (StrSize (DriverName));
807 if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) {
808 FakeNvData->DriSelection[Index] = 0x00;
809 } else {
810 FakeNvData->DriSelection[Index] = 0x01;
811 mLastSavedDriverImageNum++;
812 }
813 StrCat (NewString, DriverName);
814 NewStringToken = mDriverImageToken[Index];
815 if (NewStringToken == 0) {
816 Status = HiiLibNewString (Private->RegisteredHandle, &NewStringToken, NewString);
817 } else {
818 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);
819 }
820 mDriverImageToken[Index] = NewStringToken;
821 ASSERT_EFI_ERROR (Status);
822 gBS->FreePool (NewString);
823 if (FreeDriverName) {
824 gBS->FreePool (DriverName);
825 }
826
827 //
828 // Second create the driver image device path as item help string
829 //
830 DriverName = DevicePathToStr (LoadedImageDevicePath);
831
832 NewString = AllocateZeroPool (StrSize (DriverName));
833 StrCat (NewString, DriverName);
834 NewStringHelpToken = mDriverImageFilePathToken[Index];
835 if (NewStringHelpToken == 0) {
836 Status = HiiLibNewString (Private->RegisteredHandle, &NewStringHelpToken, NewString);
837 } else {
838 Status = HiiLibSetString (Private->RegisteredHandle, NewStringHelpToken, NewString);
839 }
840 mDriverImageFilePathToken[Index] = NewStringHelpToken;
841 ASSERT_EFI_ERROR (Status);
842 gBS->FreePool (NewString);
843 gBS->FreePool (DriverName);
844
845 CreateCheckBoxOpCode (
846 (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index),
847 VARSTORE_ID_PLAT_OVER_MNGR,
848 (UINT16) (DRIVER_SELECTION_VAR_OFFSET + Index),
849 NewStringToken,
850 NewStringHelpToken,
851 0,
852 0,
853 &UpdateData
854 );
855 }
856
857 //
858 // Update second page form
859 //
860 IfrLibUpdateForm (
861 Private->RegisteredHandle,
862 &mPlatformOverridesManagerGuid,
863 FORM_ID_DRIVER,
864 FORM_ID_DRIVER,
865 FALSE,
866 &UpdateData
867 );
868
869 gBS->FreePool (UpdateData.Data);
870 return EFI_SUCCESS;
871 }
872
873 /**
874 Prepare to let user select the priority order of the drivers which are
875 selected in second page.
876
877 @param Private Pointer to EFI_CALLBACK_INFO.
878 @param KeyValue The callback key value of device controller item in first page.
879 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
880
881 @retval EFI_SUCCESS Always returned.
882
883 **/
884 EFI_STATUS
885 UpdatePrioritySelectPage (
886 IN EFI_CALLBACK_INFO *Private,
887 IN UINT16 KeyValue,
888 IN PLAT_OVER_MNGR_DATA *FakeNvData
889 )
890 {
891 EFI_HII_UPDATE_DATA UpdateData;
892 UINTN Index;
893
894 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
895
896 IFR_OPTION *IfrOptionList;
897 UINTN SelectedDriverImageNum;
898 UINT32 DriverImageNO;
899 UINTN MinNO;
900 UINTN Index1;
901 UINTN TempNO[100];
902
903 //
904 // Following code will be run if user select 'order ... priority' item in second page
905 // Prepare third page. In third page, user will order the drivers priority which are selected in second page
906 //
907 mCurrentPage = FORM_ID_ORDER;
908
909 UpdateData.BufferSize = UPDATE_DATA_SIZE;
910 UpdateData.Offset = 0;
911 UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);
912 ASSERT (UpdateData.Data != NULL);
913 //
914 // Clear third page form
915 //
916 IfrLibUpdateForm (
917 Private->RegisteredHandle,
918 &mPlatformOverridesManagerGuid,
919 FORM_ID_ORDER,
920 FORM_ID_ORDER,
921 FALSE,
922 &UpdateData
923 );
924
925 //
926 // Check how many drivers have been selected
927 //
928 SelectedDriverImageNum = 0;
929 for (Index = 0; Index < mDriverImageHandleCount; Index++) {
930 if (FakeNvData->DriSelection[Index] != 0) {
931 SelectedDriverImageNum ++;
932 }
933 }
934
935 mSelectedDriverImageNum = SelectedDriverImageNum;
936 if (SelectedDriverImageNum == 0) {
937 return EFI_SUCCESS;
938 }
939
940 IfrOptionList = AllocateZeroPool (0x200);
941 ASSERT_EFI_ERROR (IfrOptionList != NULL);
942 //
943 // Create order list for those selected drivers
944 //
945 SelectedDriverImageNum = 0;
946 for (Index = 0; Index < mDriverImageHandleCount; Index++) {
947 if (FakeNvData->DriSelection[Index] != 0) {
948 IfrOptionList[SelectedDriverImageNum].StringToken = mDriverImageToken[Index];
949 //
950 // Use the NO. in driver binding buffer as value, will use it later
951 //
952 IfrOptionList[SelectedDriverImageNum].Value.u8 = (UINT8) (Index + 1);
953 IfrOptionList[SelectedDriverImageNum].Flags = 0;
954
955 //
956 // Get the EFI Loaded Image Device Path Protocol
957 //
958 LoadedImageDevicePath = NULL;
959 gBS->HandleProtocol (
960 mDriverImageHandleBuffer[Index],
961 &gEfiLoadedImageDevicePathProtocolGuid,
962 (VOID **) &LoadedImageDevicePath
963 );
964 ASSERT (LoadedImageDevicePath != NULL);
965
966 //
967 // Check the driver DriverImage's order number in mapping database
968 //
969 DriverImageNO = 0;
970 CheckMapping (
971 mControllerDevicePathProtocol[mSelectedCtrIndex],
972 LoadedImageDevicePath,
973 &mMappingDataBase,
974 NULL,
975 &DriverImageNO
976 );
977 if (DriverImageNO == 0) {
978 DriverImageNO = (UINT32) mLastSavedDriverImageNum + 1;
979 mLastSavedDriverImageNum++;
980 }
981 TempNO[SelectedDriverImageNum] = DriverImageNO;
982 SelectedDriverImageNum ++;
983 }
984 }
985
986 ASSERT (SelectedDriverImageNum == mSelectedDriverImageNum);
987 //
988 // NvRamMap Must be clear firstly
989 //
990 ZeroMem (FakeNvData->DriOrder, 100);
991
992 //
993 // Order the selected drivers according to the info already in mapping database
994 // the less order number in mapping database the less order number in NvRamMap
995 //
996 for (Index=0; Index < SelectedDriverImageNum; Index++) {
997 //
998 // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array
999 //
1000 MinNO = 0;
1001 for (Index1=0; Index1 < SelectedDriverImageNum; Index1++) {
1002 if (TempNO[Index1] < TempNO[MinNO]) {
1003 MinNO = Index1;
1004 }
1005 }
1006 //
1007 // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer
1008 //
1009 FakeNvData->DriOrder[Index] =IfrOptionList[MinNO].Value.u8;
1010 TempNO[MinNO] = 101;
1011 }
1012
1013 CreateOrderedListOpCode (
1014 (UINT16) DRIVER_ORDER_QUESTION_ID,
1015 VARSTORE_ID_PLAT_OVER_MNGR,
1016 (UINT16) DRIVER_ORDER_VAR_OFFSET,
1017 mControllerToken[mSelectedCtrIndex],
1018 mControllerToken[mSelectedCtrIndex],
1019 EFI_IFR_FLAG_RESET_REQUIRED,
1020 0,
1021 EFI_IFR_NUMERIC_SIZE_1,
1022 100,
1023 IfrOptionList,
1024 SelectedDriverImageNum,
1025 &UpdateData
1026 );
1027
1028 //
1029 // Update third page form
1030 //
1031 IfrLibUpdateForm (
1032 Private->RegisteredHandle,
1033 &mPlatformOverridesManagerGuid,
1034 FORM_ID_ORDER,
1035 FORM_ID_ORDER,
1036 FALSE,
1037 &UpdateData
1038 );
1039
1040 gBS->FreePool (IfrOptionList);
1041 gBS->FreePool (UpdateData.Data);
1042 return EFI_SUCCESS;
1043 }
1044
1045 /**
1046 Save the save the mapping database to NV variable.
1047
1048 @param Private Pointer to EFI_CALLBACK_INFO.
1049 @param KeyValue The callback key value of device controller item in first page.
1050 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
1051
1052 @retval EFI_SUCCESS Always returned.
1053
1054 **/
1055 EFI_STATUS
1056 CommintChanges (
1057 IN EFI_CALLBACK_INFO *Private,
1058 IN UINT16 KeyValue,
1059 IN PLAT_OVER_MNGR_DATA *FakeNvData
1060 )
1061 {
1062 EFI_STATUS Status;
1063 UINTN Index;
1064 UINTN SelectedDriverImageNum;
1065 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
1066 //
1067 // Following code will be run if user select 'commint changes' in third page
1068 // user enter 'Commit Changes' to save the mapping database
1069 //
1070 DeleteDriverImage (mControllerDevicePathProtocol[mSelectedCtrIndex], NULL, &mMappingDataBase);
1071 for (SelectedDriverImageNum = 0; SelectedDriverImageNum < mSelectedDriverImageNum; SelectedDriverImageNum++) {
1072 //
1073 // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer
1074 //
1075 Index = FakeNvData->DriOrder[SelectedDriverImageNum] - 1;
1076
1077 //
1078 // Get the EFI Loaded Image Device Path Protocol
1079 //
1080 LoadedImageDevicePath = NULL;
1081 Status = gBS->HandleProtocol (
1082 mDriverImageHandleBuffer[Index],
1083 &gEfiLoadedImageDevicePathProtocolGuid,
1084 (VOID **) &LoadedImageDevicePath
1085 );
1086 ASSERT (LoadedImageDevicePath != NULL);
1087
1088 InsertDriverImage (
1089 mControllerDevicePathProtocol[mSelectedCtrIndex],
1090 LoadedImageDevicePath,
1091 &mMappingDataBase,
1092 (UINT32)SelectedDriverImageNum + 1
1093 );
1094 }
1095 Status = SaveOverridesMapping (&mMappingDataBase);
1096
1097 return Status;
1098 }
1099
1100 /**
1101 This function allows a caller to extract the current configuration for one
1102 or more named elements from the target driver.
1103
1104 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1105 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1106 @param Progress On return, points to a character in the Request string.
1107 Points to the string's null terminator if request was successful.
1108 Points to the most recent '&' before the first failing name/value
1109 pair (or the beginning of the string if the failure is in the
1110 first name/value pair) if the request was not successful.
1111 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
1112 has all values filled in for the names in the Request string.
1113 String to be allocated by the called function.
1114
1115 @retval EFI_SUCCESS The Results is filled with the requested values.
1116 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
1117 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
1118 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1119
1120 **/
1121 EFI_STATUS
1122 EFIAPI
1123 PlatOverMngrExtractConfig (
1124 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1125 IN CONST EFI_STRING Request,
1126 OUT EFI_STRING *Progress,
1127 OUT EFI_STRING *Results
1128 )
1129 {
1130 EFI_STATUS Status;
1131 EFI_CALLBACK_INFO *Private;
1132 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1133
1134 Private = EFI_CALLBACK_INFO_FROM_THIS (This);
1135 HiiConfigRouting = Private->HiiConfigRouting;
1136
1137 //
1138 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1139 //
1140 Status = HiiConfigRouting->BlockToConfig (
1141 HiiConfigRouting,
1142 Request,
1143 (UINT8 *) &Private->FakeNvData,
1144 sizeof (PLAT_OVER_MNGR_DATA),
1145 Results,
1146 Progress
1147 );
1148 return Status;
1149 }
1150
1151 /**
1152 This function processes the results of changes in configuration.
1153
1154 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1155 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1156 @param Progress A pointer to a string filled in with the offset of the most
1157 recent '&' before the first failing name/value pair (or the
1158 beginning of the string if the failure is in the first
1159 name/value pair) or the terminating NULL if all was successful.
1160
1161 @retval EFI_SUCCESS The Results is processed successfully.
1162 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1163 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1164
1165 **/
1166 EFI_STATUS
1167 EFIAPI
1168 PlatOverMngrRouteConfig (
1169 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1170 IN CONST EFI_STRING Configuration,
1171 OUT EFI_STRING *Progress
1172 )
1173 {
1174 EFI_CALLBACK_INFO *Private;
1175 EFI_STATUS Status;
1176 UINT16 KeyValue;
1177 UINTN BufferSize;
1178 PLAT_OVER_MNGR_DATA *FakeNvData;
1179
1180 Private = EFI_CALLBACK_INFO_FROM_THIS (This);
1181
1182 FakeNvData = &Private->FakeNvData;
1183 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);
1184 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);
1185 if (EFI_ERROR (Status)) {
1186 return Status;
1187 }
1188
1189 if (mCurrentPage == FORM_ID_DRIVER) {
1190 KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER;
1191 UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);
1192 KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;
1193 CommintChanges (Private, KeyValue, FakeNvData);
1194 //
1195 // Since UpdatePrioritySelectPage will change mCurrentPage,
1196 // should ensure the mCurrentPage still indicate the second page here
1197 //
1198 mCurrentPage = FORM_ID_DRIVER;
1199 }
1200
1201 if (mCurrentPage == FORM_ID_ORDER) {
1202 KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;
1203 CommintChanges (Private, KeyValue, FakeNvData);
1204 }
1205 return EFI_SUCCESS;
1206 }
1207
1208 /**
1209 This is the function that is called to provide results data to the driver. This data
1210 consists of a unique key which is used to identify what data is either being passed back
1211 or being asked for.
1212
1213 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1214 @param Action A null-terminated Unicode string in <ConfigRequest> format.
1215 @param KeyValue A unique Goto OpCode callback value which record user's selection.
1216 0x100 <= KeyValue <0x500 : user select a controller item in the first page;
1217 KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page
1218 KeyValue == 0x1235 : user select 'Pci device filter' in first page
1219 KeyValue == 0x1500 : user select 'order ... priority' item in second page
1220 KeyValue == 0x1800 : user select 'commint changes' in third page
1221 KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page
1222 @param Type The type of value for the question.
1223 @param Value A pointer to the data being sent to the original exporting driver.
1224 @param ActionRequest On return, points to the action requested by the callback function.
1225
1226 @retval EFI_SUCCESS Always returned.
1227
1228 **/
1229 EFI_STATUS
1230 EFIAPI
1231 PlatOverMngrCallback (
1232 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1233 IN EFI_BROWSER_ACTION Action,
1234 IN EFI_QUESTION_ID KeyValue,
1235 IN UINT8 Type,
1236 IN EFI_IFR_TYPE_VALUE *Value,
1237 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1238 )
1239 {
1240 EFI_CALLBACK_INFO *Private;
1241 EFI_STATUS Status;
1242 EFI_STRING_ID NewStringToken;
1243 UINTN BufferSize;
1244 PLAT_OVER_MNGR_DATA *FakeNvData;
1245 EFI_INPUT_KEY Key;
1246
1247 Private = EFI_CALLBACK_INFO_FROM_THIS (This);
1248
1249 FakeNvData = &Private->FakeNvData;
1250 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);
1251 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);
1252 if (EFI_ERROR (Status)) {
1253 return Status;
1254 }
1255
1256 if (KeyValue == KEY_VALUE_DEVICE_REFRESH ||
1257 KeyValue == KEY_VALUE_DEVICE_FILTER ||
1258 KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS
1259 ) {
1260 UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);
1261 //
1262 // Update page title string
1263 //
1264 NewStringToken = STRING_TOKEN (STR_TITLE);
1265 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path");
1266 ASSERT_EFI_ERROR (Status);
1267 }
1268
1269 if (((KEY_VALUE_DEVICE_OFFSET <= KeyValue) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) {
1270 if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) {
1271 KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + 0x100);
1272 }
1273 UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData);
1274 //
1275 // Update page title string
1276 //
1277 NewStringToken = STRING_TOKEN (STR_TITLE);
1278 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller");
1279 ASSERT_EFI_ERROR (Status);
1280 }
1281
1282 if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) {
1283 UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);
1284 //
1285 // Update page title string
1286 //
1287 NewStringToken = STRING_TOKEN (STR_TITLE);
1288 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them");
1289 ASSERT_EFI_ERROR (Status);
1290 }
1291
1292 if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) {
1293 Status = CommintChanges (Private, KeyValue, FakeNvData);
1294 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1295 if (EFI_ERROR (Status)) {
1296 IfrLibCreatePopUp (1, &Key, L"Single Override Info too large, Saving Error!");
1297 return EFI_DEVICE_ERROR;
1298 }
1299 }
1300
1301 if (KeyValue == KEY_VALUE_DEVICE_CLEAR) {
1302 //
1303 // Deletes all environment variable(s) that contain the override mappings info
1304 //
1305 FreeMappingDatabase (&mMappingDataBase);
1306 Status = SaveOverridesMapping (&mMappingDataBase);
1307 UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);
1308 }
1309 //
1310 // Pass changed uncommitted data back to Form Browser
1311 //
1312 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);
1313 Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) FakeNvData, NULL);
1314
1315 return EFI_SUCCESS;
1316 }
1317
1318 /**
1319 Function unpacks a device path data structure so that all the nodes
1320 of a device path are naturally aligned.
1321
1322 @param DevPath A pointer to a device path data structure
1323
1324 @return If the memory for the device path is successfully allocated, then a
1325 @return pointer to the new device path is returned. Otherwise, NULL is returned.
1326
1327 **/
1328 EFI_DEVICE_PATH_PROTOCOL *
1329 UnpackDevicePath (
1330 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
1331 )
1332 {
1333 EFI_DEVICE_PATH_PROTOCOL *Src;
1334 EFI_DEVICE_PATH_PROTOCOL *Dest;
1335 EFI_DEVICE_PATH_PROTOCOL *NewPath;
1336 UINTN Size;
1337
1338 //
1339 // Walk device path and round sizes to valid boundries
1340 //
1341 Src = DevPath;
1342 Size = 0;
1343 for (;;) {
1344 Size += DevicePathNodeLength (Src);
1345 Size += ALIGN_SIZE (Size);
1346
1347 if (IsDevicePathEnd (Src)) {
1348 break;
1349 }
1350
1351 Src = NextDevicePathNode (Src);
1352 }
1353 //
1354 // Allocate space for the unpacked path
1355 //
1356 NewPath = AllocateZeroPool (Size);
1357 if (NewPath) {
1358
1359 ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);
1360
1361 //
1362 // Copy each node
1363 //
1364 Src = DevPath;
1365 Dest = NewPath;
1366 for (;;) {
1367 Size = DevicePathNodeLength (Src);
1368 CopyMem (Dest, Src, Size);
1369 Size += ALIGN_SIZE (Size);
1370 SetDevicePathNodeLength (Dest, Size);
1371 Dest->Type |= EFI_DP_TYPE_UNPACKED;
1372 Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);
1373
1374 if (IsDevicePathEnd (Src)) {
1375 break;
1376 }
1377
1378 Src = NextDevicePathNode (Src);
1379 }
1380 }
1381
1382 return NewPath;
1383 }
1384
1385
1386 /**
1387 Get the description string by device path.
1388
1389 @param DevPath The input device path.
1390
1391 @retval !NULL The description string retured.
1392 @retval NULL The description string cannot be found.
1393
1394 **/
1395 CHAR16 *
1396 DevicePathToStr (
1397 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
1398 )
1399 {
1400 EFI_STATUS Status;
1401 CHAR16 *ToText;
1402 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
1403
1404 if (DevPath == NULL) {
1405 return NULL;
1406 }
1407
1408 Status = gBS->LocateProtocol (
1409 &gEfiDevicePathToTextProtocolGuid,
1410 NULL,
1411 (VOID **) &DevPathToText
1412 );
1413 if (!EFI_ERROR (Status)) {
1414 ToText = DevPathToText->ConvertDevicePathToText (
1415 DevPath,
1416 FALSE,
1417 TRUE
1418 );
1419 ASSERT (ToText != NULL);
1420 return ToText;
1421 }
1422
1423 return NULL;
1424 }