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