Correct HiiGetBrowserData API usage.
[efi/edk2/.git] / edk2 / MdeModulePkg / Universal / PlatformDriOverrideDxe / PlatDriOverrideDxe.c
1 /** @file\r
2   This file also installs UEFI PLATFORM_DRIVER_OVERRIDE_PROTOCOL.\r
3   \r
4   The main code offers a UI interface in device manager to let user configure\r
5   platform override protocol to override the default algorithm for matching\r
6   drivers to controllers.\r
7 \r
8   The main flow:\r
9   1. It dynamicly locate all controller device path.\r
10   2. It dynamicly locate all drivers which support binding protocol.\r
11   3. It export and dynamicly update two menu to let user select the\r
12      mapping between drivers to controllers.\r
13   4. It save all the mapping info in NV variables which will be consumed\r
14      by platform override protocol driver to publish the platform override protocol.\r
15 \r
16 Copyright (c) 2007 - 2009, Intel Corporation\r
17 All rights reserved. This program and the accompanying materials\r
18 are licensed and made available under the terms and conditions of the BSD License\r
19 which accompanies this distribution.  The full text of the license may be found at\r
20 http://opensource.org/licenses/bsd-license.php\r
21 \r
22 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
23 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
24 \r
25 **/\r
26 \r
27 #include "InternalPlatDriOverrideDxe.h"\r
28 #include "PlatOverMngr.h"\r
29 \r
30 #define EFI_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('C', 'l', 'b', 'k')\r
31 #define EFI_CALLBACK_INFO_FROM_THIS(a)  CR (a, EFI_CALLBACK_INFO, ConfigAccess, EFI_CALLBACK_INFO_SIGNATURE)\r
32 \r
33 typedef struct {\r
34   UINTN                           Signature;\r
35   EFI_HANDLE                      DriverHandle;\r
36   EFI_HII_HANDLE                  RegisteredHandle;\r
37   PLAT_OVER_MNGR_DATA             FakeNvData;\r
38   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
39   EFI_HII_CONFIG_ACCESS_PROTOCOL  ConfigAccess;\r
40   EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL PlatformDriverOverride;\r
41 } EFI_CALLBACK_INFO;\r
42 \r
43 #pragma pack(1)\r
44 \r
45 ///\r
46 /// HII specific Vendor Device Path definition.\r
47 ///\r
48 typedef struct {\r
49   VENDOR_DEVICE_PATH             VendorDevicePath;\r
50   EFI_DEVICE_PATH_PROTOCOL       End;\r
51 } HII_VENDOR_DEVICE_PATH;\r
52 \r
53 #pragma pack()\r
54 \r
55 //\r
56 // uni string and Vfr Binary data.\r
57 //\r
58 extern UINT8  VfrBin[];\r
59 extern UINT8  PlatDriOverrideDxeStrings[];\r
60 \r
61 //\r
62 // module global data\r
63 //\r
64 EFI_GUID                     mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID;\r
65 CHAR16                       mVariableName[] = L"Data";\r
66 LIST_ENTRY                   mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);\r
67 BOOLEAN                      mEnvironmentVariableRead = FALSE;\r
68 EFI_HANDLE                   mCallerImageHandle = NULL;\r
69 \r
70 EFI_HANDLE                   *mDevicePathHandleBuffer;\r
71 EFI_HANDLE                   *mDriverImageHandleBuffer;\r
72 \r
73 INTN                         mSelectedCtrIndex;\r
74 EFI_STRING_ID                mControllerToken[MAX_CHOICE_NUM];\r
75 UINTN                        mDriverImageHandleCount;\r
76 EFI_STRING_ID                mDriverImageToken[MAX_CHOICE_NUM];\r
77 EFI_STRING_ID                mDriverImageFilePathToken[MAX_CHOICE_NUM];\r
78 EFI_LOADED_IMAGE_PROTOCOL    *mDriverImageProtocol[MAX_CHOICE_NUM];\r
79 EFI_DEVICE_PATH_PROTOCOL     *mControllerDevicePathProtocol[MAX_CHOICE_NUM];\r
80 UINTN                        mSelectedDriverImageNum;\r
81 UINTN                        mLastSavedDriverImageNum;\r
82 UINT16                       mCurrentPage;\r
83 EFI_CALLBACK_INFO           *mCallbackInfo;\r
84 \r
85 HII_VENDOR_DEVICE_PATH  mHiiVendorDevicePath = {\r
86   {\r
87     {\r
88       HARDWARE_DEVICE_PATH,\r
89       HW_VENDOR_DP,\r
90       {\r
91         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
92         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
93       }\r
94     },\r
95     EFI_CALLER_ID_GUID\r
96   },\r
97   {\r
98     END_DEVICE_PATH_TYPE,\r
99     END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
100     { \r
101       (UINT8) (END_DEVICE_PATH_LENGTH),\r
102       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
103     }\r
104   }\r
105 };\r
106 \r
107 /**\r
108   Converting a given device to an unicode string. \r
109   \r
110   This function will dependent on gEfiDevicePathToTextProtocolGuid, if protocol\r
111   does not installed, then return unknown device path L"?" directly.\r
112   \r
113   @param    DevPath     Given device path instance\r
114   \r
115   @return   Converted string from given device path.\r
116   @retval   L"?"  Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting.\r
117 **/\r
118 CHAR16 *\r
119 DevicePathToStr (\r
120   IN EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
121   )\r
122 {\r
123   EFI_STATUS                       Status;\r
124   EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
125   CHAR16                           *ToText;\r
126   \r
127   if (DevPath == NULL) {\r
128     return L"";\r
129   }\r
130     \r
131   Status = gBS->LocateProtocol (\r
132                   &gEfiDevicePathToTextProtocolGuid,\r
133                   NULL,\r
134                   (VOID **) &DevPathToText\r
135                   );\r
136   if (!EFI_ERROR (Status)) {\r
137     ToText = DevPathToText->ConvertDevicePathToText (\r
138                               DevPath,\r
139                               FALSE,\r
140                               TRUE\r
141                               );\r
142     ASSERT (ToText != NULL);\r
143     return ToText;\r
144   }\r
145 \r
146   return L"?";\r
147 }\r
148 \r
149 /**\r
150   Worker function to get the driver name by ComponentName or ComponentName2 protocol \r
151   according to the driver binding handle.\r
152 \r
153   @param  DriverBindingHandle  The Handle of DriverBinding.\r
154   @param  ProtocolGuid         The pointer to Component Name (2) protocol GUID.\r
155   @param  VariableName         The name of the RFC 4646 or ISO 639-2 language variable.\r
156 \r
157   @retval !NULL               Pointer into the image name if the image name is found,\r
158   @retval NULL                Pointer to NULL if the image name is not found.\r
159 \r
160 **/\r
161 CHAR16 *\r
162 GetComponentNameWorker (\r
163   IN EFI_HANDLE                      DriverBindingHandle,\r
164   IN EFI_GUID                        *ProtocolGuid,\r
165   IN CONST CHAR16                    *VariableName\r
166   )\r
167 {\r
168   EFI_STATUS                         Status;\r
169   EFI_COMPONENT_NAME_PROTOCOL        *ComponentName;\r
170   CHAR16                             *DriverName;\r
171   CHAR8                              *Language;\r
172   CHAR8                              *BestLanguage;\r
173 \r
174   Status = gBS->OpenProtocol (\r
175                   DriverBindingHandle,\r
176                   ProtocolGuid,\r
177                   (VOID *) &ComponentName,\r
178                   NULL,\r
179                   NULL,\r
180                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
181                   );\r
182   if (EFI_ERROR (Status)) {\r
183     return NULL;\r
184   }\r
185 \r
186   //\r
187   // Find the best matching language.\r
188   //\r
189   Language = GetEfiGlobalVariable (VariableName);\r
190   BestLanguage = GetBestLanguage (\r
191                    ComponentName->SupportedLanguages,\r
192                    (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid),\r
193                    Language,\r
194                    NULL\r
195                    );\r
196 \r
197   DriverName = NULL;\r
198   if (BestLanguage != NULL) {\r
199     ComponentName->GetDriverName (\r
200                      ComponentName,\r
201                      BestLanguage,\r
202                      &DriverName\r
203                      );\r
204     FreePool (BestLanguage);\r
205   }\r
206 \r
207   if (Language != NULL) {\r
208     FreePool (Language);\r
209   }\r
210 \r
211   return DriverName;\r
212 }\r
213 \r
214 \r
215 /**\r
216   Get the driver name by ComponentName or ComponentName2 protocol \r
217   according to the driver binding handle\r
218 \r
219   @param DriverBindingHandle  The Handle of DriverBinding.\r
220 \r
221   @retval !NULL               Pointer into the image name if the image name is found,\r
222   @retval NULL                Pointer to NULL if the image name is not found.\r
223 \r
224 **/\r
225 CHAR16 *\r
226 GetComponentName (\r
227   IN EFI_HANDLE                      DriverBindingHandle\r
228   )\r
229 {\r
230   CHAR16                    *DriverName;\r
231 \r
232   //\r
233   // Try RFC 4646 Component Name 2 protocol first.\r
234   //\r
235   DriverName = GetComponentNameWorker (DriverBindingHandle, &gEfiComponentName2ProtocolGuid, L"PlatformLang");\r
236   if (DriverName == NULL) {\r
237     //\r
238     // If we can not get driver name from Component Name 2 protocol, we can try ISO 639-2 Component Name protocol. \r
239     //\r
240     DriverName = GetComponentNameWorker (DriverBindingHandle, &gEfiComponentNameProtocolGuid, L"Lang");\r
241   }\r
242 \r
243   return DriverName;\r
244 }\r
245 \r
246 /**\r
247   Get the image name from EFI UI section.\r
248   Get FV protocol by its loaded image protocol to abstract EFI UI section.\r
249 \r
250   @param Image            Pointer to the loaded image protocol\r
251 \r
252   @retval !NULL           Pointer to the image name if the image name is found,\r
253   @retval NULL            NULL if the image name is not found.\r
254 \r
255 **/\r
256 CHAR16 *\r
257 GetImageName (\r
258   IN EFI_LOADED_IMAGE_PROTOCOL *Image\r
259   )\r
260 {\r
261   EFI_STATUS                        Status;\r
262   EFI_DEVICE_PATH_PROTOCOL          *DevPathNode;\r
263   EFI_DEVICE_PATH_PROTOCOL          *AlignedDevPathNode;\r
264   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
265   VOID                              *Buffer;\r
266   UINTN                             BufferSize;\r
267   UINT32                            AuthenticationStatus;\r
268   EFI_GUID                          *NameGuid;\r
269   EFI_FIRMWARE_VOLUME2_PROTOCOL     *Fv2;\r
270 \r
271   Fv2         = NULL;\r
272   Buffer      = NULL;\r
273   BufferSize  = 0;\r
274 \r
275   if (Image->FilePath == NULL) {\r
276     return NULL;\r
277   }\r
278   DevPathNode  = Image->FilePath;\r
279 \r
280   while (!IsDevicePathEnd (DevPathNode)) {\r
281     //\r
282     // Make sure device path node is aligned when accessing it's FV Name Guid field.\r
283     //\r
284     AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength(DevPathNode), DevPathNode);\r
285     \r
286     //\r
287     // Find the Fv File path\r
288     //\r
289     NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)AlignedDevPathNode);\r
290     if (NameGuid != NULL) {\r
291       FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) AlignedDevPathNode;\r
292       Status = gBS->HandleProtocol (\r
293                     Image->DeviceHandle,\r
294                     &gEfiFirmwareVolume2ProtocolGuid,\r
295                     (VOID **) &Fv2\r
296                     );\r
297       //\r
298       // Locate Image EFI UI section to get the image name.\r
299       //\r
300       if (!EFI_ERROR (Status)) {\r
301         Status = Fv2->ReadSection (\r
302                         Fv2,\r
303                         &FvFilePath->FvFileName,\r
304                         EFI_SECTION_USER_INTERFACE,\r
305                         0,\r
306                         &Buffer,\r
307                         &BufferSize,\r
308                         &AuthenticationStatus\r
309                         );\r
310         if (!EFI_ERROR (Status)) {\r
311           FreePool (AlignedDevPathNode);\r
312           break;\r
313         }\r
314         Buffer = NULL;\r
315       }\r
316     }\r
317     \r
318     FreePool (AlignedDevPathNode);\r
319     \r
320     //\r
321     // Next device path node\r
322     //\r
323     DevPathNode = NextDevicePathNode (DevPathNode);\r
324   }\r
325 \r
326   return Buffer;\r
327 }\r
328 \r
329 /**\r
330   Prepare the first page to let user select the device controller which need to\r
331   add mapping drivers if user select 'Refresh' in first page.\r
332   During first page, user will see all currnet controller device path in system,\r
333   select any device path will go to second page to select its overrides drivers.\r
334 \r
335   @param  Private        Pointer to EFI_CALLBACK_INFO.\r
336   @param  KeyValue       The callback key value of device controller item in first page.\r
337   @param  FakeNvData     Pointer to PLAT_OVER_MNGR_DATA.\r
338 \r
339   @retval EFI_SUCCESS    Always returned.\r
340 \r
341 **/\r
342 EFI_STATUS\r
343 UpdateDeviceSelectPage (\r
344   IN EFI_CALLBACK_INFO                *Private,\r
345   IN UINT16                           KeyValue,\r
346   IN PLAT_OVER_MNGR_DATA              *FakeNvData\r
347   )\r
348 {\r
349   EFI_STATUS                                Status;\r
350   UINTN                                     Index;\r
351   UINTN                                     DevicePathHandleCount;\r
352   CHAR16                                    *NewString;\r
353   EFI_STRING_ID                             NewStringToken;\r
354   CHAR16                                    *ControllerName;\r
355   EFI_DEVICE_PATH_PROTOCOL                  *ControllerDevicePath;\r
356   EFI_PCI_IO_PROTOCOL                       *PciIo;\r
357   EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;\r
358   UINTN                                     Len;\r
359   VOID                                      *StartOpCodeHandle;\r
360   VOID                                      *EndOpCodeHandle;\r
361   EFI_IFR_GUID_LABEL                        *StartLabel;\r
362   EFI_IFR_GUID_LABEL                        *EndLabel;  \r
363 \r
364   //\r
365   // Set current page form ID.\r
366   //\r
367   mCurrentPage = FORM_ID_DEVICE;  \r
368   \r
369   //\r
370   // Initial the mapping database in memory\r
371   //\r
372   FreeMappingDatabase (&mMappingDataBase);\r
373   InitOverridesMapping (&mMappingDataBase);\r
374 \r
375   //\r
376   // Init OpCode Handle\r
377   //\r
378   StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
379   ASSERT (StartOpCodeHandle != NULL);\r
380 \r
381   EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
382   ASSERT (EndOpCodeHandle != NULL);\r
383 \r
384   //\r
385   // Create Hii Extend Label OpCode as the start opcode\r
386   //\r
387   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
388   StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
389   StartLabel->Number = FORM_ID_DEVICE;\r
390 \r
391   //\r
392   // Create Hii Extend Label OpCode as the end opcode\r
393   //\r
394   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
395   EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
396   EndLabel->Number       = LABEL_END;\r
397 \r
398   //\r
399   // Clear first page form\r
400   //\r
401   HiiUpdateForm (\r
402     Private->RegisteredHandle,\r
403     &mPlatformOverridesManagerGuid,\r
404     FORM_ID_DEVICE,\r
405     StartOpCodeHandle, // Label FORM_ID_DEVICE\r
406     EndOpCodeHandle    // LABEL_END\r
407     );\r
408 \r
409   //\r
410   // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,\r
411   // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement\r
412   //\r
413   NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH);\r
414   NewString = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH), NULL);\r
415   ASSERT (NewString != NULL);\r
416   if (HiiSetString (Private->RegisteredHandle, NewStringToken, NewString, NULL) == 0) {\r
417     ASSERT (FALSE);\r
418   }\r
419   FreePool (NewString);\r
420 \r
421   NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH_HELP);\r
422   NewString = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH_HELP), NULL);\r
423   ASSERT (NewString != NULL);\r
424   if (HiiSetString (Private->RegisteredHandle, NewStringToken, NewString, NULL) == 0) {\r
425     ASSERT (FALSE);\r
426   }\r
427   FreePool (NewString);\r
428 \r
429   //\r
430   // created needed controller device item in first page\r
431   //\r
432   DevicePathHandleCount  = 0;\r
433   Status = gBS->LocateHandleBuffer (\r
434                   ByProtocol,\r
435                   &gEfiDevicePathProtocolGuid,\r
436                   NULL,\r
437                   &DevicePathHandleCount,\r
438                   &mDevicePathHandleBuffer\r
439                   );\r
440   if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) {\r
441     return EFI_SUCCESS;\r
442   }\r
443 \r
444   for (Index = 0; Index < DevicePathHandleCount; Index++) {\r
445     if (FakeNvData->PciDeviceFilter == 0x01) {\r
446       //\r
447       // Only care PCI device which contain efi driver in its option rom.\r
448       //\r
449 \r
450       //\r
451       // Check whether it is a pci device\r
452       //\r
453       ControllerDevicePath = NULL;\r
454       Status = gBS->OpenProtocol (\r
455                       mDevicePathHandleBuffer[Index],\r
456                       &gEfiPciIoProtocolGuid,\r
457                       (VOID **) &PciIo,\r
458                       NULL,\r
459                       NULL,\r
460                       EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
461                       );\r
462       if (EFI_ERROR (Status)) {\r
463         continue;\r
464       }\r
465       //\r
466       // Check whether it contain efi driver in its option rom\r
467       //\r
468       Status = gBS->HandleProtocol(\r
469                        mDevicePathHandleBuffer[Index],\r
470                        &gEfiBusSpecificDriverOverrideProtocolGuid,\r
471                        (VOID **) &BusSpecificDriverOverride\r
472                        );\r
473       if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {\r
474         continue;\r
475       }\r
476     }\r
477 \r
478     ControllerDevicePath = NULL;\r
479     Status = gBS->OpenProtocol (\r
480                     mDevicePathHandleBuffer[Index],\r
481                     &gEfiDevicePathProtocolGuid,\r
482                     (VOID **) &ControllerDevicePath,\r
483                     NULL,\r
484                     NULL,\r
485                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
486                     );\r
487     ASSERT_EFI_ERROR (Status);\r
488     //\r
489     // Save the device path protocol interface\r
490     //\r
491     mControllerDevicePathProtocol[Index] = ControllerDevicePath;\r
492 \r
493     //\r
494     // Get the driver name\r
495     //\r
496     ControllerName = DevicePathToStr (ControllerDevicePath);\r
497 \r
498     //\r
499     // Export the driver name string and create item in set options page\r
500     //\r
501     Len = StrSize (ControllerName);\r
502     NewString = AllocateZeroPool (Len + StrSize (L"--"));\r
503     ASSERT (NewString != NULL);\r
504     if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) {\r
505       StrCat (NewString, L"--");\r
506     } else {\r
507       StrCat (NewString, L"**");\r
508     }\r
509     StrCat (NewString, ControllerName);\r
510 \r
511     NewStringToken = HiiSetString (Private->RegisteredHandle, mControllerToken[Index], NewString, NULL);\r
512     ASSERT (NewStringToken != 0);\r
513     FreePool (NewString);\r
514     //\r
515     // Save the device path string toke for next access use\r
516     //\r
517     mControllerToken[Index] = NewStringToken;\r
518       \r
519     HiiCreateGotoOpCode (\r
520       StartOpCodeHandle,\r
521       FORM_ID_DRIVER,\r
522       NewStringToken,\r
523       STRING_TOKEN (STR_GOTO_HELP_DRIVER),\r
524       EFI_IFR_FLAG_CALLBACK,\r
525       (UINT16) (Index + KEY_VALUE_DEVICE_OFFSET)\r
526       );\r
527   }\r
528 \r
529   //\r
530   // Update first page form\r
531   //\r
532   HiiUpdateForm (\r
533     Private->RegisteredHandle,\r
534     &mPlatformOverridesManagerGuid,\r
535     FORM_ID_DEVICE,\r
536     StartOpCodeHandle, // Label FORM_ID_DEVICE\r
537     EndOpCodeHandle    // LABEL_END\r
538     );\r
539 \r
540   HiiFreeOpCodeHandle (StartOpCodeHandle);\r
541   HiiFreeOpCodeHandle (EndOpCodeHandle);\r
542 \r
543   return EFI_SUCCESS;\r
544 }\r
545 \r
546 /**\r
547   Get the first Driver Binding handle which has the specific image handle.\r
548 \r
549   @param  ImageHandle          The Image handle\r
550 \r
551   @return                      Handle to Driver binding\r
552   @retval NULL                 The paramter is not valid or the driver binding handle is not found.\r
553 \r
554 **/\r
555 EFI_HANDLE\r
556 GetDriverBindingHandleFromImageHandle (\r
557   IN  EFI_HANDLE   ImageHandle\r
558   )\r
559 {\r
560   EFI_STATUS                        Status;\r
561   UINTN                             Index;\r
562   UINTN                             DriverBindingHandleCount;\r
563   EFI_HANDLE                        *DriverBindingHandleBuffer;\r
564   EFI_DRIVER_BINDING_PROTOCOL       *DriverBindingInterface;\r
565   EFI_HANDLE                        DriverBindingHandle;\r
566 \r
567   DriverBindingHandle = NULL;\r
568 \r
569   if (ImageHandle == NULL) {\r
570     return NULL;\r
571   }\r
572   //\r
573   // Get all drivers which support driver binding protocol\r
574   //\r
575   DriverBindingHandleCount  = 0;\r
576   Status = gBS->LocateHandleBuffer (\r
577                   ByProtocol,\r
578                   &gEfiDriverBindingProtocolGuid,\r
579                   NULL,\r
580                   &DriverBindingHandleCount,\r
581                   &DriverBindingHandleBuffer\r
582                   );\r
583   if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {\r
584     return NULL;\r
585   }\r
586   \r
587   //\r
588   // Get the first Driver Binding handle which has the specific image handle.\r
589   //\r
590   for (Index = 0; Index < DriverBindingHandleCount; Index++) {\r
591     DriverBindingInterface = NULL;\r
592     Status = gBS->OpenProtocol (\r
593                     DriverBindingHandleBuffer[Index],\r
594                     &gEfiDriverBindingProtocolGuid,\r
595                     (VOID **) &DriverBindingInterface,\r
596                     NULL,\r
597                     NULL,\r
598                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
599                     );\r
600     if (EFI_ERROR (Status)) {\r
601       continue;\r
602     }\r
603 \r
604     if (DriverBindingInterface->ImageHandle == ImageHandle) {\r
605       DriverBindingHandle = DriverBindingHandleBuffer[Index];\r
606       break;\r
607     }\r
608   }\r
609 \r
610   FreePool (DriverBindingHandleBuffer);\r
611   return DriverBindingHandle;\r
612 }\r
613 \r
614 /**\r
615   Prepare to let user select the drivers which need mapping with the device controller\r
616   selected in first page.\r
617 \r
618   @param  Private        Pointer to EFI_CALLBACK_INFO.\r
619   @param  KeyValue       The callback key value of device controller item in first page.\r
620                          KeyValue is larger than or equal to KEY_VALUE_DEVICE_OFFSET.\r
621   @param  FakeNvData     Pointer to PLAT_OVER_MNGR_DATA.\r
622 \r
623   @retval EFI_SUCCESS    Always returned.\r
624 \r
625 **/\r
626 EFI_STATUS\r
627 UpdateBindingDriverSelectPage (\r
628   IN EFI_CALLBACK_INFO                *Private,\r
629   IN UINT16                           KeyValue,\r
630   IN PLAT_OVER_MNGR_DATA              *FakeNvData\r
631   )\r
632 {\r
633   EFI_STATUS                                Status;\r
634   UINTN                                     Index;\r
635   CHAR16                                    *NewString;\r
636   EFI_STRING_ID                             NewStringToken;\r
637   EFI_STRING_ID                             NewStringHelpToken;\r
638   UINTN                                     DriverImageHandleCount;\r
639   EFI_LOADED_IMAGE_PROTOCOL                 *LoadedImage;\r
640   CHAR16                                    *DriverName;\r
641   BOOLEAN                                   FreeDriverName;\r
642   EFI_DEVICE_PATH_PROTOCOL                  *LoadedImageDevicePath;\r
643   EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;\r
644   EFI_HANDLE                                DriverBindingHandle;\r
645   VOID                                      *StartOpCodeHandle;\r
646   VOID                                      *EndOpCodeHandle;\r
647   EFI_IFR_GUID_LABEL                        *StartLabel;\r
648   EFI_IFR_GUID_LABEL                        *EndLabel;\r
649 \r
650   //\r
651   // If user select a controller item in the first page  the following code will be run.\r
652   // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown\r
653   //\r
654   //First acquire the list of Loaded Image Protocols, and then when  want the name of the driver, look up all the Driver Binding Protocols\r
655   // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.\r
656   // 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.\r
657   //\r
658 \r
659   mCurrentPage = FORM_ID_DRIVER;\r
660   //\r
661   // Switch the item callback key value to its NO. in mDevicePathHandleBuffer\r
662   //\r
663   mSelectedCtrIndex = KeyValue - KEY_VALUE_DEVICE_OFFSET;\r
664   ASSERT (mSelectedCtrIndex < MAX_CHOICE_NUM);\r
665 \r
666   mLastSavedDriverImageNum = 0;\r
667 \r
668   //\r
669   // Init OpCode Handle\r
670   //\r
671   StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
672   ASSERT (StartOpCodeHandle != NULL);\r
673 \r
674   EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
675   ASSERT (EndOpCodeHandle != NULL);\r
676 \r
677   //\r
678   // Create Hii Extend Label OpCode as the start opcode\r
679   //\r
680   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
681   StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
682   StartLabel->Number       = FORM_ID_DRIVER;\r
683 \r
684   //\r
685   // Create Hii Extend Label OpCode as the end opcode\r
686   //\r
687   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
688   EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
689   EndLabel->Number       = LABEL_END;\r
690 \r
691   //\r
692   // Clear second page form\r
693   //\r
694   HiiUpdateForm (\r
695     Private->RegisteredHandle,\r
696     &mPlatformOverridesManagerGuid,\r
697     FORM_ID_DRIVER,\r
698     StartOpCodeHandle,\r
699     EndOpCodeHandle\r
700     );\r
701 \r
702   //\r
703   // Show all driver which support loaded image protocol in second page\r
704   //\r
705   DriverImageHandleCount  = 0;\r
706   Status = gBS->LocateHandleBuffer (\r
707                   ByProtocol,\r
708                   &gEfiLoadedImageProtocolGuid,\r
709                   NULL,\r
710                   &DriverImageHandleCount,\r
711                   &mDriverImageHandleBuffer\r
712                   );\r
713   if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) {\r
714     return EFI_NOT_FOUND;\r
715   }\r
716 \r
717   mDriverImageHandleCount = DriverImageHandleCount;\r
718   for (Index = 0; Index < DriverImageHandleCount; Index++) {\r
719     //\r
720     // Step1: Get the driver image total file path for help string and the driver name.\r
721     //\r
722 \r
723     //\r
724     // Find driver's Loaded Image protocol\r
725     //\r
726     LoadedImage =NULL;\r
727 \r
728     Status = gBS->OpenProtocol (\r
729                     mDriverImageHandleBuffer[Index],\r
730                     &gEfiLoadedImageProtocolGuid,\r
731                     (VOID **) &LoadedImage,\r
732                     NULL,\r
733                     NULL,\r
734                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
735                     );\r
736     if (EFI_ERROR (Status)) {\r
737       FakeNvData->DriSelection[Index] = 0x00;\r
738       continue;\r
739     }\r
740     mDriverImageProtocol[Index] = LoadedImage;\r
741     //\r
742     // Find its related driver binding protocol\r
743     //\r
744     DriverBindingHandle = GetDriverBindingHandleFromImageHandle (mDriverImageHandleBuffer[Index]);\r
745     if (DriverBindingHandle == NULL) {\r
746       FakeNvData->DriSelection[Index] = 0x00;\r
747       continue;\r
748     }\r
749 \r
750     //\r
751     // Get the EFI Loaded Image Device Path Protocol\r
752     //\r
753     LoadedImageDevicePath = NULL;\r
754     Status = gBS->HandleProtocol (\r
755                         mDriverImageHandleBuffer[Index],\r
756                         &gEfiLoadedImageDevicePathProtocolGuid,\r
757                         (VOID **) &LoadedImageDevicePath\r
758                         );\r
759     if (LoadedImageDevicePath == NULL) {\r
760       FakeNvData->DriSelection[Index] = 0x00;\r
761       continue;\r
762     }\r
763 \r
764     if (FakeNvData->PciDeviceFilter == 0x01) {\r
765       //\r
766       // only care the driver which is in a Pci device option rom,\r
767       // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom\r
768       //\r
769       if (!EFI_ERROR (Status)) {\r
770         Status = gBS->HandleProtocol(\r
771                          LoadedImage->DeviceHandle,\r
772                          &gEfiBusSpecificDriverOverrideProtocolGuid,\r
773                          (VOID **) &BusSpecificDriverOverride\r
774                          );\r
775         if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {\r
776           FakeNvData->DriSelection[Index] = 0x00;\r
777           continue;\r
778         }\r
779       } else {\r
780         FakeNvData->DriSelection[Index] = 0x00;\r
781         continue;\r
782       }\r
783     }\r
784 \r
785     //\r
786     // For driver name, try to get its component name, if fail, get its image name,\r
787     // if also fail, give a default name.\r
788     //\r
789     FreeDriverName = FALSE;\r
790     DriverName = GetComponentName (DriverBindingHandle);\r
791     if (DriverName == NULL) {\r
792       //\r
793       // get its image name\r
794       //\r
795       DriverName = GetImageName (LoadedImage);\r
796     }\r
797     if (DriverName == NULL) {\r
798       //\r
799       // give a default name\r
800       //\r
801       DriverName = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME), NULL);\r
802       ASSERT (DriverName != NULL);\r
803       FreeDriverName = TRUE;  // the DriverName string need to free pool\r
804     }\r
805 \r
806 \r
807     //\r
808     // Step2 Export the driver name string and create check box item in second page\r
809     //\r
810 \r
811     //\r
812     // First create the driver image name\r
813     //\r
814     NewString = AllocateZeroPool (StrSize (DriverName));\r
815     ASSERT (NewString != NULL); \r
816     if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) {\r
817       FakeNvData->DriSelection[Index] = 0x00;\r
818     } else {\r
819       FakeNvData->DriSelection[Index] = 0x01;\r
820       mLastSavedDriverImageNum++;\r
821     }\r
822     StrCat (NewString, DriverName);\r
823     NewStringToken = HiiSetString (Private->RegisteredHandle, mDriverImageToken[Index], NewString, NULL);\r
824     ASSERT (NewStringToken != 0);\r
825     mDriverImageToken[Index] = NewStringToken;\r
826     FreePool (NewString);\r
827     if (FreeDriverName) {\r
828       FreePool (DriverName);\r
829     }\r
830 \r
831     //\r
832     // Second create the driver image device path as item help string\r
833     //\r
834     DriverName = DevicePathToStr (LoadedImageDevicePath);\r
835 \r
836     NewString = AllocateZeroPool (StrSize (DriverName));\r
837     ASSERT (NewString != NULL); \r
838     StrCat (NewString, DriverName);\r
839     NewStringHelpToken = HiiSetString (Private->RegisteredHandle, mDriverImageFilePathToken[Index], NewString, NULL);\r
840     ASSERT (NewStringHelpToken != 0);\r
841     mDriverImageFilePathToken[Index] = NewStringHelpToken;\r
842     FreePool (NewString);\r
843     FreePool (DriverName);\r
844 \r
845     HiiCreateCheckBoxOpCode (\r
846       StartOpCodeHandle,\r
847       (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index),\r
848       VARSTORE_ID_PLAT_OVER_MNGR,\r
849       (UINT16) (DRIVER_SELECTION_VAR_OFFSET + Index),\r
850       NewStringToken,\r
851       NewStringHelpToken,\r
852       0,\r
853       0,\r
854       NULL\r
855       );\r
856   }\r
857 \r
858   //\r
859   // Update second page form\r
860   //\r
861   HiiUpdateForm (\r
862     Private->RegisteredHandle,\r
863     &mPlatformOverridesManagerGuid,\r
864     FORM_ID_DRIVER,\r
865     StartOpCodeHandle, // Label FORM_ID_DRIVER\r
866     EndOpCodeHandle    // LABEL_END\r
867     );\r
868 \r
869   HiiFreeOpCodeHandle (StartOpCodeHandle);\r
870   HiiFreeOpCodeHandle (EndOpCodeHandle);\r
871   return EFI_SUCCESS;\r
872 }\r
873 \r
874 /**\r
875   Prepare to let user select the priority order of the drivers which are\r
876   selected in second page.\r
877 \r
878   @param  Private        Pointer to EFI_CALLBACK_INFO.\r
879   @param  KeyValue       The callback key value of device controller item in first page.\r
880   @param  FakeNvData     Pointer to PLAT_OVER_MNGR_DATA.\r
881 \r
882   @retval EFI_SUCCESS    Always returned.\r
883 \r
884 **/\r
885 EFI_STATUS\r
886 UpdatePrioritySelectPage (\r
887   IN EFI_CALLBACK_INFO                *Private,\r
888   IN UINT16                           KeyValue,\r
889   IN PLAT_OVER_MNGR_DATA              *FakeNvData\r
890   )\r
891 {\r
892   UINTN                                     Index;\r
893   EFI_DEVICE_PATH_PROTOCOL                  *LoadedImageDevicePath;\r
894   UINTN                                     SelectedDriverImageNum;\r
895   UINT32                                    DriverImageNO;\r
896   UINTN                                     MinNO;\r
897   UINTN                                     Index1;\r
898   UINTN                                     TempNO[100];\r
899   UINTN                                     OrderNO[100];\r
900   VOID                                      *StartOpCodeHandle;\r
901   VOID                                      *EndOpCodeHandle;\r
902   VOID                                      *OptionsOpCodeHandle;\r
903   EFI_IFR_GUID_LABEL                        *StartLabel;\r
904   EFI_IFR_GUID_LABEL                        *EndLabel;\r
905 \r
906   //\r
907   // Following code will be run if user select 'order ... priority' item in second page\r
908   // Prepare third page.  In third page, user will order the  drivers priority which are selected in second page\r
909   //\r
910   mCurrentPage = FORM_ID_ORDER;\r
911 \r
912   //\r
913   // Init OpCode Handle\r
914   //\r
915   StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
916   ASSERT (StartOpCodeHandle != NULL);\r
917 \r
918   EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
919   ASSERT (EndOpCodeHandle != NULL);\r
920 \r
921   //\r
922   // Create Hii Extend Label OpCode as the start opcode\r
923   //\r
924   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
925   StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
926   StartLabel->Number       = FORM_ID_ORDER;\r
927 \r
928   //\r
929   // Create Hii Extend Label OpCode as the end opcode\r
930   //\r
931   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
932   EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
933   EndLabel->Number       = LABEL_END;\r
934 \r
935   //\r
936   // Clear third page form\r
937   //\r
938   HiiUpdateForm (\r
939     Private->RegisteredHandle,\r
940     &mPlatformOverridesManagerGuid,\r
941     FORM_ID_ORDER,\r
942     StartOpCodeHandle,\r
943     EndOpCodeHandle\r
944     );\r
945 \r
946   //\r
947   // Check how many drivers have been selected\r
948   //\r
949   SelectedDriverImageNum = 0;\r
950   for (Index = 0; Index < mDriverImageHandleCount; Index++) {\r
951     if (FakeNvData->DriSelection[Index] != 0) {\r
952       SelectedDriverImageNum ++;\r
953     }\r
954   }\r
955 \r
956   mSelectedDriverImageNum = SelectedDriverImageNum;\r
957   if (SelectedDriverImageNum == 0) {\r
958     return EFI_SUCCESS;\r
959   }\r
960 \r
961   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();\r
962   ASSERT (OptionsOpCodeHandle != NULL);\r
963 \r
964   //\r
965   // Create order list for those selected drivers\r
966   //\r
967   SelectedDriverImageNum = 0;\r
968   for (Index = 0; Index < mDriverImageHandleCount; Index++) {\r
969     if (FakeNvData->DriSelection[Index] != 0) {\r
970       //\r
971       // Use the NO. in driver binding buffer as value, will use it later\r
972       //\r
973       HiiCreateOneOfOptionOpCode (\r
974         OptionsOpCodeHandle,\r
975         mDriverImageToken[Index],\r
976         0,\r
977         EFI_IFR_NUMERIC_SIZE_1,\r
978         Index + 1\r
979         );\r
980 \r
981       //\r
982       // Get the EFI Loaded Image Device Path Protocol\r
983       //\r
984       LoadedImageDevicePath = NULL;\r
985       gBS->HandleProtocol (\r
986                  mDriverImageHandleBuffer[Index],\r
987                  &gEfiLoadedImageDevicePathProtocolGuid,\r
988                  (VOID **) &LoadedImageDevicePath\r
989                  );\r
990       ASSERT (LoadedImageDevicePath != NULL);\r
991 \r
992       //\r
993       // Check the driver DriverImage's order number in mapping database\r
994       //\r
995       DriverImageNO = 0;\r
996       CheckMapping (\r
997               mControllerDevicePathProtocol[mSelectedCtrIndex],\r
998               LoadedImageDevicePath,\r
999               &mMappingDataBase,\r
1000               NULL,\r
1001               &DriverImageNO\r
1002               );\r
1003       if (DriverImageNO == 0) {\r
1004         DriverImageNO = (UINT32) mLastSavedDriverImageNum + 1;\r
1005         mLastSavedDriverImageNum++;\r
1006       }\r
1007       TempNO[SelectedDriverImageNum] = DriverImageNO;\r
1008       OrderNO[SelectedDriverImageNum] = Index + 1;\r
1009       SelectedDriverImageNum ++;\r
1010     }\r
1011   }\r
1012 \r
1013   ASSERT (SelectedDriverImageNum == mSelectedDriverImageNum);\r
1014   //\r
1015   // NvRamMap Must be clear firstly\r
1016   //\r
1017   ZeroMem (FakeNvData->DriOrder, sizeof (FakeNvData->DriOrder));\r
1018 \r
1019   //\r
1020   // Order the selected drivers according to the info already in mapping database\r
1021   // the less order number in mapping database the less order number in NvRamMap\r
1022   //\r
1023   for (Index=0; Index < SelectedDriverImageNum; Index++) {\r
1024     //\r
1025     // Find the minimal order number in TempNO array,  its index in TempNO is same as IfrOptionList array\r
1026     //\r
1027     MinNO = 0;\r
1028     for (Index1=0; Index1 < SelectedDriverImageNum; Index1++) {\r
1029       if (TempNO[Index1] < TempNO[MinNO]) {\r
1030         MinNO = Index1;\r
1031       }\r
1032     }\r
1033     //\r
1034     // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer\r
1035     //\r
1036     FakeNvData->DriOrder[Index] = (UINT8) OrderNO[MinNO];\r
1037     TempNO[MinNO] = MAX_CHOICE_NUM + 1;\r
1038   }\r
1039   \r
1040   //\r
1041   // Create Order List OpCode\r
1042   //\r
1043   HiiCreateOrderedListOpCode (\r
1044     StartOpCodeHandle,\r
1045     (UINT16) DRIVER_ORDER_QUESTION_ID,\r
1046     VARSTORE_ID_PLAT_OVER_MNGR,\r
1047     (UINT16) DRIVER_ORDER_VAR_OFFSET,\r
1048     mControllerToken[mSelectedCtrIndex],\r
1049     mControllerToken[mSelectedCtrIndex],\r
1050     EFI_IFR_FLAG_RESET_REQUIRED,\r
1051     0,\r
1052     EFI_IFR_NUMERIC_SIZE_1,\r
1053     (UINT8) MAX_CHOICE_NUM,\r
1054     OptionsOpCodeHandle,\r
1055     NULL\r
1056     );\r
1057 \r
1058   //\r
1059   // Update third page form\r
1060   //\r
1061   HiiUpdateForm (\r
1062     Private->RegisteredHandle,\r
1063     &mPlatformOverridesManagerGuid,\r
1064     FORM_ID_ORDER,\r
1065     StartOpCodeHandle, // Label FORM_ID_ORDER\r
1066     EndOpCodeHandle    // LABEL_END\r
1067     );\r
1068 \r
1069   HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1070   HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1071   HiiFreeOpCodeHandle (OptionsOpCodeHandle);\r
1072 \r
1073   return EFI_SUCCESS;\r
1074 }\r
1075 \r
1076 /**\r
1077   Save the save the mapping database to NV variable.\r
1078 \r
1079   @param  Private        Pointer to EFI_CALLBACK_INFO.\r
1080   @param  KeyValue       The callback key value of device controller item in first page.\r
1081   @param  FakeNvData     Pointer to PLAT_OVER_MNGR_DATA.\r
1082 \r
1083   @retval EFI_SUCCESS    Always returned.\r
1084 \r
1085 **/\r
1086 EFI_STATUS\r
1087 CommintChanges (\r
1088   IN EFI_CALLBACK_INFO                *Private,\r
1089   IN UINT16                           KeyValue,\r
1090   IN PLAT_OVER_MNGR_DATA              *FakeNvData\r
1091   )\r
1092 {\r
1093   EFI_STATUS                                Status;\r
1094   UINTN                                     Index;\r
1095   UINTN                                     SelectedDriverImageNum;\r
1096   EFI_DEVICE_PATH_PROTOCOL                  *LoadedImageDevicePath;\r
1097   //\r
1098   //  Following code will be run if user select 'commint changes' in third page\r
1099   //  user enter 'Commit Changes' to save the mapping database\r
1100   //\r
1101   DeleteDriverImage (mControllerDevicePathProtocol[mSelectedCtrIndex], NULL, &mMappingDataBase);\r
1102   for (SelectedDriverImageNum = 0; SelectedDriverImageNum < mSelectedDriverImageNum; SelectedDriverImageNum++) {\r
1103     //\r
1104     // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer\r
1105     //\r
1106     Index = FakeNvData->DriOrder[SelectedDriverImageNum] - 1;\r
1107 \r
1108     //\r
1109     // Get the EFI Loaded Image Device Path Protocol\r
1110     //\r
1111     LoadedImageDevicePath = NULL;\r
1112     Status = gBS->HandleProtocol (\r
1113                         mDriverImageHandleBuffer[Index],\r
1114                         &gEfiLoadedImageDevicePathProtocolGuid,\r
1115                         (VOID **) &LoadedImageDevicePath\r
1116                         );\r
1117     ASSERT (LoadedImageDevicePath != NULL);\r
1118 \r
1119     InsertDriverImage (\r
1120             mControllerDevicePathProtocol[mSelectedCtrIndex],\r
1121             LoadedImageDevicePath,\r
1122             &mMappingDataBase,\r
1123             (UINT32)SelectedDriverImageNum + 1\r
1124             );\r
1125   }\r
1126   Status = SaveOverridesMapping (&mMappingDataBase);\r
1127 \r
1128   return Status;\r
1129 }\r
1130 \r
1131 /**\r
1132   This function allows a caller to extract the current configuration for one\r
1133   or more named elements from the target driver.\r
1134 \r
1135   @param  This         Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1136   @param  Request      A null-terminated Unicode string in <ConfigRequest> format.\r
1137   @param  Progress     On return, points to a character in the Request string.\r
1138                        Points to the string's null terminator if request was successful.\r
1139                        Points to the most recent '&' before the first failing name/value\r
1140                        pair (or the beginning of the string if the failure is in the\r
1141                        first name/value pair) if the request was not successful.\r
1142   @param  Results      A null-terminated Unicode string in <ConfigAltResp> format which\r
1143                        has all values filled in for the names in the Request string.\r
1144                        String to be allocated by the called function.\r
1145 \r
1146   @retval EFI_SUCCESS            The Results is filled with the requested values.\r
1147   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
1148   @retval EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown name.\r
1149   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.\r
1150 \r
1151 **/\r
1152 EFI_STATUS\r
1153 EFIAPI\r
1154 PlatOverMngrExtractConfig (\r
1155   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
1156   IN  CONST EFI_STRING                       Request,\r
1157   OUT EFI_STRING                             *Progress,\r
1158   OUT EFI_STRING                             *Results\r
1159   )\r
1160 {\r
1161   EFI_STATUS                       Status;\r
1162   EFI_CALLBACK_INFO                *Private;\r
1163   EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
1164   \r
1165   if (Request == NULL) {\r
1166     return EFI_NOT_FOUND;\r
1167   }\r
1168 \r
1169   Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1170   HiiConfigRouting = Private->HiiConfigRouting;\r
1171 \r
1172   //\r
1173   // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
1174   //\r
1175   Status = HiiConfigRouting->BlockToConfig (\r
1176                                 HiiConfigRouting,\r
1177                                 Request,\r
1178                                 (UINT8 *) &Private->FakeNvData,\r
1179                                 sizeof (PLAT_OVER_MNGR_DATA),\r
1180                                 Results,\r
1181                                 Progress\r
1182                                 );\r
1183   return Status;\r
1184 }\r
1185 \r
1186 /**\r
1187   This function processes the results of changes in configuration.\r
1188 \r
1189   @param  This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1190   @param  Configuration   A null-terminated Unicode string in <ConfigRequest> format.\r
1191   @param  Progress        A pointer to a string filled in with the offset of the most\r
1192                           recent '&' before the first failing name/value pair (or the\r
1193                           beginning of the string if the failure is in the first\r
1194                           name/value pair) or the terminating NULL if all was successful.\r
1195 \r
1196   @retval EFI_SUCCESS            The Results is processed successfully.\r
1197   @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
1198   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.\r
1199 \r
1200 **/\r
1201 EFI_STATUS\r
1202 EFIAPI\r
1203 PlatOverMngrRouteConfig (\r
1204   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
1205   IN  CONST EFI_STRING                       Configuration,\r
1206   OUT EFI_STRING                             *Progress\r
1207   )\r
1208 {\r
1209   EFI_CALLBACK_INFO                         *Private;\r
1210   UINT16                                    KeyValue;\r
1211   PLAT_OVER_MNGR_DATA                       *FakeNvData;\r
1212 \r
1213   Private    = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1214   FakeNvData = &Private->FakeNvData;\r
1215   if (!HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData)) {\r
1216     return EFI_NOT_FOUND;\r
1217   }\r
1218 \r
1219   if (mCurrentPage == FORM_ID_DRIVER) {\r
1220     KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER;\r
1221     UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
1222     KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
1223     CommintChanges (Private, KeyValue, FakeNvData);\r
1224     //\r
1225     // Since UpdatePrioritySelectPage will change mCurrentPage,\r
1226     // should ensure the mCurrentPage still indicate the second page here\r
1227     //\r
1228     mCurrentPage = FORM_ID_DRIVER;\r
1229   }\r
1230 \r
1231   if (mCurrentPage == FORM_ID_ORDER) {\r
1232     KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
1233     CommintChanges (Private, KeyValue, FakeNvData);\r
1234   }\r
1235 \r
1236   return EFI_SUCCESS;\r
1237 }\r
1238 \r
1239 /**\r
1240   This is the function that is called to provide results data to the driver.  This data\r
1241   consists of a unique key which is used to identify what data is either being passed back\r
1242   or being asked for.\r
1243 \r
1244   @param  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1245   @param  Action         A null-terminated Unicode string in <ConfigRequest> format.\r
1246   @param  KeyValue       A unique Goto OpCode callback value which record user's selection.\r
1247                          0x100 <= KeyValue <0x500 : user select a controller item in the first page;\r
1248                          KeyValue == 0x1234       : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page\r
1249                          KeyValue == 0x1235       : user select 'Pci device filter' in first page\r
1250                          KeyValue == 0x1500       : user select 'order ... priority' item in second page\r
1251                          KeyValue == 0x1800       : user select 'commint changes' in third page\r
1252                          KeyValue == 0x2000       : user select 'Go to Previous Menu' in third page\r
1253   @param  Type           The type of value for the question.\r
1254   @param  Value          A pointer to the data being sent to the original exporting driver.\r
1255   @param  ActionRequest  On return, points to the action requested by the callback function.\r
1256 \r
1257   @retval EFI_SUCCESS    Always returned.\r
1258 \r
1259 **/\r
1260 EFI_STATUS\r
1261 EFIAPI\r
1262 PlatOverMngrCallback (\r
1263   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
1264   IN  EFI_BROWSER_ACTION                     Action,\r
1265   IN  EFI_QUESTION_ID                        KeyValue,\r
1266   IN  UINT8                                  Type,\r
1267   IN  EFI_IFR_TYPE_VALUE                     *Value,\r
1268   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
1269   )\r
1270 {\r
1271   EFI_CALLBACK_INFO                         *Private;\r
1272   EFI_STATUS                                Status;\r
1273   EFI_STRING_ID                             NewStringToken;\r
1274   EFI_INPUT_KEY                             Key;\r
1275   PLAT_OVER_MNGR_DATA                       *FakeNvData;\r
1276   \r
1277   Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1278   FakeNvData = &Private->FakeNvData;\r
1279   if (!HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData)) {\r
1280     return EFI_NOT_FOUND;\r
1281   }\r
1282 \r
1283   if (KeyValue == KEY_VALUE_DEVICE_REFRESH ||\r
1284       KeyValue == KEY_VALUE_DEVICE_FILTER ||\r
1285       KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS\r
1286       ) {\r
1287     UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
1288     //\r
1289     // Update page title string\r
1290     //\r
1291     NewStringToken = STRING_TOKEN (STR_TITLE);\r
1292     if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path", NULL) == 0) {\r
1293       ASSERT (FALSE);\r
1294     }\r
1295   }\r
1296 \r
1297   if (((KeyValue >= KEY_VALUE_DEVICE_OFFSET) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) {\r
1298     if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) {\r
1299       KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + KEY_VALUE_DEVICE_OFFSET);\r
1300     }\r
1301     UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData);\r
1302     //\r
1303     // Update page title string\r
1304     //\r
1305     NewStringToken = STRING_TOKEN (STR_TITLE);\r
1306     if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller", NULL) == 0) {\r
1307       ASSERT (FALSE);\r
1308     }\r
1309   }\r
1310 \r
1311   if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) {\r
1312     UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
1313     //\r
1314     // Update page title string\r
1315     //\r
1316     NewStringToken = STRING_TOKEN (STR_TITLE);\r
1317     if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them", NULL) == 0) {\r
1318       ASSERT (FALSE);\r
1319     }\r
1320   }\r
1321 \r
1322   if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) {\r
1323     Status = CommintChanges (Private, KeyValue, FakeNvData);\r
1324     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1325     if (EFI_ERROR (Status)) {\r
1326       CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Single Override Info too large, Saving Error!", NULL);\r
1327       return EFI_DEVICE_ERROR;\r
1328     }\r
1329   }\r
1330 \r
1331   if (KeyValue == KEY_VALUE_DEVICE_CLEAR) {\r
1332     //\r
1333     // Deletes all environment variable(s) that contain the override mappings info\r
1334     //\r
1335     FreeMappingDatabase (&mMappingDataBase);\r
1336     Status = SaveOverridesMapping (&mMappingDataBase);\r
1337     UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
1338   }\r
1339   //\r
1340   // Pass changed uncommitted data back to Form Browser\r
1341   //\r
1342   HiiSetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData, NULL);\r
1343 \r
1344   return EFI_SUCCESS;\r
1345 }\r
1346 \r
1347 /**\r
1348   Retrieves the image handle of the platform override driver for a controller in the system.\r
1349 \r
1350   @param  This                   A pointer to the\r
1351                                  EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL instance.\r
1352   @param  ControllerHandle       The device handle of the controller to check if a\r
1353                                  driver override exists.\r
1354   @param  DriverImageHandle      On input, a pointer to the previous driver image\r
1355                                  handle returned by GetDriver().  On output, a\r
1356                                  pointer to the next driver image handle. Passing\r
1357                                  in a NULL,  will return the first driver image\r
1358                                  handle for ControllerHandle.\r
1359 \r
1360   @retval EFI_SUCCESS            The driver override for ControllerHandle was\r
1361                                  returned in DriverImageHandle.\r
1362   @retval EFI_NOT_FOUND          A driver override for ControllerHandle was not\r
1363                                  found.\r
1364   @retval EFI_INVALID_PARAMETER  The handle specified by ControllerHandle is not a\r
1365                                  valid handle. DriverImageHandle is not a handle\r
1366                                  that was returned on a previous  call to\r
1367                                  GetDriver().\r
1368 \r
1369 **/\r
1370 EFI_STATUS\r
1371 EFIAPI\r
1372 GetDriver (\r
1373   IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL              *This,\r
1374   IN     EFI_HANDLE                                     ControllerHandle,\r
1375   IN OUT EFI_HANDLE                                     *DriverImageHandle\r
1376   )\r
1377 {\r
1378   EFI_STATUS  Status;\r
1379 \r
1380   //\r
1381   // Check that ControllerHandle is a valid handle\r
1382   //\r
1383   if (ControllerHandle == NULL) {\r
1384     return EFI_INVALID_PARAMETER;\r
1385   }\r
1386 \r
1387   //\r
1388   // Read the environment variable(s) that contain the override mappings from Controller Device Path to\r
1389   // a set of Driver Device Paths, and  initialize in memory database of the overrides that map Controller\r
1390   // Device Paths to an ordered set of Driver Device Paths and Driver Handles. This action is only performed\r
1391   // once and finished in first call.\r
1392   //\r
1393   if (!mEnvironmentVariableRead) {\r
1394     mEnvironmentVariableRead = TRUE;\r
1395 \r
1396     Status = InitOverridesMapping (&mMappingDataBase);\r
1397     if (EFI_ERROR (Status)){\r
1398       DEBUG ((DEBUG_ERROR, "The status to Get Platform Driver Override Variable is %r\n", Status));\r
1399       InitializeListHead (&mMappingDataBase);\r
1400       return EFI_NOT_FOUND;\r
1401     }\r
1402   }\r
1403 \r
1404   //\r
1405   // if the environment variable does not exist, just return not found\r
1406   //\r
1407   if (IsListEmpty (&mMappingDataBase)) {\r
1408     return EFI_NOT_FOUND;\r
1409   }\r
1410 \r
1411   return GetDriverFromMapping (\r
1412             ControllerHandle,\r
1413             DriverImageHandle,\r
1414             &mMappingDataBase,\r
1415             mCallerImageHandle\r
1416             );\r
1417 }\r
1418 \r
1419 /**\r
1420   Retrieves the device path of the platform override driver for a controller in the system.\r
1421   This driver doesn't support this API.\r
1422 \r
1423   @param  This                  A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_\r
1424                                 PROTOCOL instance.                            \r
1425   @param  ControllerHandle      The device handle of the controller to check if a driver override\r
1426                                 exists.                                                          \r
1427   @param  DriverImagePath       On input, a pointer to the previous driver device path returned by\r
1428                                 GetDriverPath(). On output, a pointer to the next driver\r
1429                                 device path. Passing in a pointer to NULL, will return the first\r
1430                                 driver device path for ControllerHandle.\r
1431   \r
1432   @retval EFI_UNSUPPORTED\r
1433 **/\r
1434 EFI_STATUS\r
1435 EFIAPI\r
1436 GetDriverPath (\r
1437   IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL              *This,\r
1438   IN     EFI_HANDLE                                     ControllerHandle,\r
1439   IN OUT EFI_DEVICE_PATH_PROTOCOL                       **DriverImagePath\r
1440   )\r
1441 {\r
1442   return EFI_UNSUPPORTED;\r
1443 }\r
1444 \r
1445 \r
1446 /**\r
1447   Used to associate a driver image handle with a device path that was returned on a prior call to the\r
1448   GetDriverPath() service. This driver image handle will then be available through the               \r
1449   GetDriver() service. This driver doesn't support this API.\r
1450 \r
1451   @param  This                  A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_\r
1452                                 PROTOCOL instance.                            \r
1453   @param  ControllerHandle      The device handle of the controller.                                                             \r
1454   @param  DriverImagePath       A pointer to the driver device path that was returned in a prior\r
1455                                 call to GetDriverPath().                                                                        \r
1456   @param  DriverImageHandle     The driver image handle that was returned by LoadImage()\r
1457                                 when the driver specified by DriverImagePath was loaded \r
1458                                 into memory. \r
1459   \r
1460   @retval EFI_UNSUPPORTED\r
1461 **/\r
1462 EFI_STATUS\r
1463 EFIAPI\r
1464 DriverLoaded (\r
1465   IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL          *This,\r
1466   IN EFI_HANDLE                                     ControllerHandle,\r
1467   IN EFI_DEVICE_PATH_PROTOCOL                       *DriverImagePath,\r
1468   IN EFI_HANDLE                                     DriverImageHandle\r
1469   )\r
1470 {\r
1471   return EFI_UNSUPPORTED;\r
1472 }\r
1473 \r
1474 /**\r
1475   The driver Entry Point. The funciton will export a disk device class formset and\r
1476   its callback function to hii database.\r
1477 \r
1478   @param  ImageHandle    The firmware allocated handle for the EFI image.\r
1479   @param  SystemTable    A pointer to the EFI System Table.\r
1480 \r
1481   @retval EFI_SUCCESS    The entry point is executed successfully.\r
1482   @retval other          Some error occurs when executing this entry point.\r
1483 \r
1484 **/\r
1485 EFI_STATUS\r
1486 EFIAPI\r
1487 PlatDriOverrideDxeInit (\r
1488   IN EFI_HANDLE                   ImageHandle,\r
1489   IN EFI_SYSTEM_TABLE             *SystemTable\r
1490   )\r
1491 {\r
1492   EFI_STATUS                  Status;\r
1493   EFI_FORM_BROWSER2_PROTOCOL  *FormBrowser2;\r
1494   VOID                        *Instance;\r
1495   \r
1496   //\r
1497   // There should only be one Form Configuration protocol\r
1498   //\r
1499   Status = gBS->LocateProtocol (\r
1500                  &gEfiFormBrowser2ProtocolGuid,\r
1501                  NULL,\r
1502                  (VOID **) &FormBrowser2\r
1503                  );\r
1504   if (EFI_ERROR (Status)) {\r
1505     return Status;\r
1506   }\r
1507 \r
1508   //\r
1509   // According to UEFI spec, there can be at most a single instance\r
1510   // in the system of the EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL.\r
1511   // So here we check the existence.\r
1512   //\r
1513   Status = gBS->LocateProtocol (\r
1514                   &gEfiPlatformDriverOverrideProtocolGuid,\r
1515                   NULL,\r
1516                   &Instance\r
1517                   );\r
1518   //\r
1519   // If there was no error, assume there is an installation and return error\r
1520   //\r
1521   if (!EFI_ERROR (Status)) {\r
1522     return EFI_ALREADY_STARTED;\r
1523   }\r
1524   \r
1525   mCallerImageHandle = ImageHandle;\r
1526   mCallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO));\r
1527   if (mCallbackInfo == NULL) {\r
1528     return EFI_BAD_BUFFER_SIZE;\r
1529   }\r
1530 \r
1531   mCallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;\r
1532   mCallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig;\r
1533   mCallbackInfo->ConfigAccess.RouteConfig   = PlatOverMngrRouteConfig;\r
1534   mCallbackInfo->ConfigAccess.Callback      = PlatOverMngrCallback;\r
1535   mCallbackInfo->PlatformDriverOverride.GetDriver      = GetDriver;\r
1536   mCallbackInfo->PlatformDriverOverride.GetDriverPath  = GetDriverPath;\r
1537   mCallbackInfo->PlatformDriverOverride.DriverLoaded   = DriverLoaded;\r
1538   //\r
1539   // Install Device Path Protocol and Config Access protocol to driver handle\r
1540   // Install Platform Driver Override Protocol to driver handle\r
1541   //\r
1542   Status = gBS->InstallMultipleProtocolInterfaces (\r
1543                   &mCallbackInfo->DriverHandle,\r
1544                   &gEfiDevicePathProtocolGuid,\r
1545                   &mHiiVendorDevicePath,\r
1546                   &gEfiHiiConfigAccessProtocolGuid,\r
1547                   &mCallbackInfo->ConfigAccess,\r
1548                   &gEfiPlatformDriverOverrideProtocolGuid,\r
1549                   &mCallbackInfo->PlatformDriverOverride,\r
1550                   NULL\r
1551                   );\r
1552   if (EFI_ERROR (Status)) {\r
1553     goto Finish;\r
1554   }\r
1555 \r
1556   //\r
1557   // Publish our HII data\r
1558   //\r
1559   mCallbackInfo->RegisteredHandle = HiiAddPackages (\r
1560                                      &mPlatformOverridesManagerGuid,\r
1561                                      mCallbackInfo->DriverHandle,\r
1562                                      VfrBin,\r
1563                                      PlatDriOverrideDxeStrings,\r
1564                                      NULL\r
1565                                      );\r
1566   if (mCallbackInfo->RegisteredHandle == NULL) {\r
1567     Status = EFI_OUT_OF_RESOURCES;\r
1568     goto Finish;\r
1569   }\r
1570 \r
1571   //\r
1572   // Locate ConfigRouting protocol\r
1573   //\r
1574   Status = gBS->LocateProtocol (\r
1575                   &gEfiHiiConfigRoutingProtocolGuid,\r
1576                   NULL,\r
1577                   (VOID **) &mCallbackInfo->HiiConfigRouting\r
1578                   );\r
1579   if (EFI_ERROR (Status)) {\r
1580     goto Finish;\r
1581   }\r
1582 \r
1583   //\r
1584   // Clear all the globle variable\r
1585   //\r
1586   mDriverImageHandleCount = 0;\r
1587   mCurrentPage = 0;\r
1588   ZeroMem (mDriverImageToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
1589   ZeroMem (mDriverImageFilePathToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
1590   ZeroMem (mControllerToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
1591   ZeroMem (mDriverImageProtocol, MAX_CHOICE_NUM * sizeof (EFI_LOADED_IMAGE_PROTOCOL *));\r
1592   \r
1593   return EFI_SUCCESS;\r
1594 \r
1595 Finish:\r
1596   if (mCallbackInfo->DriverHandle != NULL) {\r
1597     gBS->UninstallMultipleProtocolInterfaces (\r
1598            mCallbackInfo->DriverHandle,\r
1599            &gEfiDevicePathProtocolGuid,\r
1600            &mHiiVendorDevicePath,\r
1601            &gEfiHiiConfigAccessProtocolGuid,\r
1602            &mCallbackInfo->ConfigAccess,\r
1603            &gEfiPlatformDriverOverrideProtocolGuid,\r
1604            &mCallbackInfo->PlatformDriverOverride,\r
1605            NULL\r
1606            );\r
1607   }\r
1608   \r
1609   if (mCallbackInfo->RegisteredHandle != NULL) {\r
1610     HiiRemovePackages (mCallbackInfo->RegisteredHandle);\r
1611   }\r
1612 \r
1613   if (mCallbackInfo != NULL) {\r
1614     FreePool (mCallbackInfo);\r
1615   }\r
1616 \r
1617   return Status;\r
1618 }\r
1619 \r
1620 /**\r
1621   Unload its installed protocol.\r
1622 \r
1623   @param[in]  ImageHandle       Handle that identifies the image to be unloaded.\r
1624 \r
1625   @retval EFI_SUCCESS           The image has been unloaded.\r
1626 **/\r
1627 EFI_STATUS\r
1628 EFIAPI\r
1629 PlatDriOverrideDxeUnload (\r
1630   IN EFI_HANDLE  ImageHandle\r
1631   )\r
1632 {\r
1633   if (mCallbackInfo->DriverHandle != NULL) {\r
1634     gBS->UninstallMultipleProtocolInterfaces (\r
1635            mCallbackInfo->DriverHandle,\r
1636            &gEfiDevicePathProtocolGuid,\r
1637            &mHiiVendorDevicePath,\r
1638            &gEfiHiiConfigAccessProtocolGuid,\r
1639            &mCallbackInfo->ConfigAccess,\r
1640            &gEfiPlatformDriverOverrideProtocolGuid,\r
1641            &mCallbackInfo->PlatformDriverOverride,\r
1642            NULL\r
1643            );\r
1644   }\r
1645 \r
1646   if (mCallbackInfo->RegisteredHandle != NULL) {\r
1647     HiiRemovePackages (mCallbackInfo->RegisteredHandle);\r
1648   }\r
1649 \r
1650   if (mCallbackInfo != NULL) {\r
1651     FreePool (mCallbackInfo);\r
1652   }\r
1653 \r
1654   return EFI_SUCCESS;\r
1655 }\r