Update HiiConfigAccess.ExtractConfig interface to support NULL request string and...
[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 - 2010, 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   EFI_STRING                       ConfigRequestHdr;\r
1165   EFI_STRING                       ConfigRequest;\r
1166   BOOLEAN                          AllocatedRequest;\r
1167   UINTN                            Size;\r
1168   UINTN                            BufferSize;\r
1169 \r
1170   if (Progress == NULL || Results == NULL) {\r
1171     return EFI_INVALID_PARAMETER;\r
1172   }\r
1173 \r
1174   *Progress = Request;\r
1175   if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mPlatformOverridesManagerGuid, mVariableName)) {\r
1176     return EFI_NOT_FOUND;\r
1177   }\r
1178 \r
1179   ConfigRequestHdr = NULL;\r
1180   ConfigRequest    = NULL;\r
1181   Size             = 0;\r
1182   AllocatedRequest = FALSE;\r
1183 \r
1184   Private          = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1185   HiiConfigRouting = Private->HiiConfigRouting;\r
1186   ConfigRequest = Request;\r
1187   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
1188     //\r
1189     // Request has no request element, construct full request string.\r
1190     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
1191     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
1192     //\r
1193     ConfigRequestHdr = HiiConstructConfigHdr (&mPlatformOverridesManagerGuid, mVariableName, Private->DriverHandle);\r
1194     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
1195     ConfigRequest = AllocateZeroPool (Size);\r
1196     ASSERT (ConfigRequest != NULL);\r
1197     AllocatedRequest = TRUE;\r
1198     BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
1199     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
1200     FreePool (ConfigRequestHdr);\r
1201   }\r
1202 \r
1203   //\r
1204   // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
1205   //\r
1206   Status = HiiConfigRouting->BlockToConfig (\r
1207                                 HiiConfigRouting,\r
1208                                 ConfigRequest,\r
1209                                 (UINT8 *) &Private->FakeNvData,\r
1210                                 sizeof (PLAT_OVER_MNGR_DATA),\r
1211                                 Results,\r
1212                                 Progress\r
1213                                 );\r
1214 \r
1215   //\r
1216   // Free the allocated config request string.\r
1217   //\r
1218   if (AllocatedRequest) {\r
1219     FreePool (ConfigRequest);\r
1220     ConfigRequest = NULL;\r
1221   }\r
1222   //\r
1223   // Set Progress string to the original request string.\r
1224   //\r
1225   if (Request == NULL) {\r
1226     *Progress = NULL;\r
1227   } else if (StrStr (Request, L"OFFSET") == NULL) {\r
1228     *Progress = Request + StrLen (Request);\r
1229   }\r
1230 \r
1231   return Status;\r
1232 }\r
1233 \r
1234 /**\r
1235   This function processes the results of changes in configuration.\r
1236 \r
1237   @param  This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1238   @param  Configuration   A null-terminated Unicode string in <ConfigRequest> format.\r
1239   @param  Progress        A pointer to a string filled in with the offset of the most\r
1240                           recent '&' before the first failing name/value pair (or the\r
1241                           beginning of the string if the failure is in the first\r
1242                           name/value pair) or the terminating NULL if all was successful.\r
1243 \r
1244   @retval EFI_SUCCESS            The Results is processed successfully.\r
1245   @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
1246   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.\r
1247 \r
1248 **/\r
1249 EFI_STATUS\r
1250 EFIAPI\r
1251 PlatOverMngrRouteConfig (\r
1252   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
1253   IN  CONST EFI_STRING                       Configuration,\r
1254   OUT EFI_STRING                             *Progress\r
1255   )\r
1256 {\r
1257   EFI_CALLBACK_INFO                         *Private;\r
1258   UINT16                                    KeyValue;\r
1259   PLAT_OVER_MNGR_DATA                       *FakeNvData;\r
1260 \r
1261   if (Configuration == NULL || Progress == NULL) {\r
1262     return EFI_INVALID_PARAMETER;\r
1263   }\r
1264   *Progress = Configuration;\r
1265 \r
1266   if (!HiiIsConfigHdrMatch (Configuration, &mPlatformOverridesManagerGuid, mVariableName)) {\r
1267     return EFI_NOT_FOUND;\r
1268   }\r
1269   \r
1270   *Progress = Configuration + StrLen (Configuration);\r
1271   Private    = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1272   FakeNvData = &Private->FakeNvData;\r
1273   if (!HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData)) {\r
1274     //\r
1275     // FakeNvData can't be got from SetupBrowser, which doesn't need to be set.\r
1276     //\r
1277     return EFI_SUCCESS;\r
1278   }\r
1279 \r
1280   if (mCurrentPage == FORM_ID_DRIVER) {\r
1281     KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER;\r
1282     UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
1283     KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
1284     CommintChanges (Private, KeyValue, FakeNvData);\r
1285     //\r
1286     // Since UpdatePrioritySelectPage will change mCurrentPage,\r
1287     // should ensure the mCurrentPage still indicate the second page here\r
1288     //\r
1289     mCurrentPage = FORM_ID_DRIVER;\r
1290   }\r
1291 \r
1292   if (mCurrentPage == FORM_ID_ORDER) {\r
1293     KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
1294     CommintChanges (Private, KeyValue, FakeNvData);\r
1295   }\r
1296 \r
1297   return EFI_SUCCESS;\r
1298 }\r
1299 \r
1300 /**\r
1301   This is the function that is called to provide results data to the driver.  This data\r
1302   consists of a unique key which is used to identify what data is either being passed back\r
1303   or being asked for.\r
1304 \r
1305   @param  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1306   @param  Action         A null-terminated Unicode string in <ConfigRequest> format.\r
1307   @param  KeyValue       A unique Goto OpCode callback value which record user's selection.\r
1308                          0x100 <= KeyValue <0x500 : user select a controller item in the first page;\r
1309                          KeyValue == 0x1234       : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page\r
1310                          KeyValue == 0x1235       : user select 'Pci device filter' in first page\r
1311                          KeyValue == 0x1500       : user select 'order ... priority' item in second page\r
1312                          KeyValue == 0x1800       : user select 'commint changes' in third page\r
1313                          KeyValue == 0x2000       : user select 'Go to Previous Menu' in third page\r
1314   @param  Type           The type of value for the question.\r
1315   @param  Value          A pointer to the data being sent to the original exporting driver.\r
1316   @param  ActionRequest  On return, points to the action requested by the callback function.\r
1317 \r
1318   @retval EFI_SUCCESS    Always returned.\r
1319 \r
1320 **/\r
1321 EFI_STATUS\r
1322 EFIAPI\r
1323 PlatOverMngrCallback (\r
1324   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
1325   IN  EFI_BROWSER_ACTION                     Action,\r
1326   IN  EFI_QUESTION_ID                        KeyValue,\r
1327   IN  UINT8                                  Type,\r
1328   IN  EFI_IFR_TYPE_VALUE                     *Value,\r
1329   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
1330   )\r
1331 {\r
1332   EFI_CALLBACK_INFO                         *Private;\r
1333   EFI_STATUS                                Status;\r
1334   EFI_STRING_ID                             NewStringToken;\r
1335   EFI_INPUT_KEY                             Key;\r
1336   PLAT_OVER_MNGR_DATA                       *FakeNvData;\r
1337   \r
1338   Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1339   FakeNvData = &Private->FakeNvData;\r
1340   if (!HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData)) {\r
1341     return EFI_NOT_FOUND;\r
1342   }\r
1343 \r
1344   if (KeyValue == KEY_VALUE_DEVICE_REFRESH ||\r
1345       KeyValue == KEY_VALUE_DEVICE_FILTER ||\r
1346       KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS\r
1347       ) {\r
1348     UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
1349     //\r
1350     // Update page title string\r
1351     //\r
1352     NewStringToken = STRING_TOKEN (STR_TITLE);\r
1353     if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path", NULL) == 0) {\r
1354       ASSERT (FALSE);\r
1355     }\r
1356   }\r
1357 \r
1358   if (((KeyValue >= KEY_VALUE_DEVICE_OFFSET) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) {\r
1359     if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) {\r
1360       KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + KEY_VALUE_DEVICE_OFFSET);\r
1361     }\r
1362     UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData);\r
1363     //\r
1364     // Update page title string\r
1365     //\r
1366     NewStringToken = STRING_TOKEN (STR_TITLE);\r
1367     if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller", NULL) == 0) {\r
1368       ASSERT (FALSE);\r
1369     }\r
1370   }\r
1371 \r
1372   if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) {\r
1373     UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
1374     //\r
1375     // Update page title string\r
1376     //\r
1377     NewStringToken = STRING_TOKEN (STR_TITLE);\r
1378     if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them", NULL) == 0) {\r
1379       ASSERT (FALSE);\r
1380     }\r
1381   }\r
1382 \r
1383   if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) {\r
1384     Status = CommintChanges (Private, KeyValue, FakeNvData);\r
1385     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1386     if (EFI_ERROR (Status)) {\r
1387       CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Single Override Info too large, Saving Error!", NULL);\r
1388       return EFI_DEVICE_ERROR;\r
1389     }\r
1390   }\r
1391 \r
1392   if (KeyValue == KEY_VALUE_DEVICE_CLEAR) {\r
1393     //\r
1394     // Deletes all environment variable(s) that contain the override mappings info\r
1395     //\r
1396     FreeMappingDatabase (&mMappingDataBase);\r
1397     Status = SaveOverridesMapping (&mMappingDataBase);\r
1398     UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
1399   }\r
1400   //\r
1401   // Pass changed uncommitted data back to Form Browser\r
1402   //\r
1403   HiiSetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData, NULL);\r
1404 \r
1405   return EFI_SUCCESS;\r
1406 }\r
1407 \r
1408 /**\r
1409   Retrieves the image handle of the platform override driver for a controller in the system.\r
1410 \r
1411   @param  This                   A pointer to the\r
1412                                  EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL instance.\r
1413   @param  ControllerHandle       The device handle of the controller to check if a\r
1414                                  driver override exists.\r
1415   @param  DriverImageHandle      On input, a pointer to the previous driver image\r
1416                                  handle returned by GetDriver().  On output, a\r
1417                                  pointer to the next driver image handle. Passing\r
1418                                  in a NULL,  will return the first driver image\r
1419                                  handle for ControllerHandle.\r
1420 \r
1421   @retval EFI_SUCCESS            The driver override for ControllerHandle was\r
1422                                  returned in DriverImageHandle.\r
1423   @retval EFI_NOT_FOUND          A driver override for ControllerHandle was not\r
1424                                  found.\r
1425   @retval EFI_INVALID_PARAMETER  The handle specified by ControllerHandle is not a\r
1426                                  valid handle. DriverImageHandle is not a handle\r
1427                                  that was returned on a previous  call to\r
1428                                  GetDriver().\r
1429 \r
1430 **/\r
1431 EFI_STATUS\r
1432 EFIAPI\r
1433 GetDriver (\r
1434   IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL              *This,\r
1435   IN     EFI_HANDLE                                     ControllerHandle,\r
1436   IN OUT EFI_HANDLE                                     *DriverImageHandle\r
1437   )\r
1438 {\r
1439   EFI_STATUS  Status;\r
1440 \r
1441   //\r
1442   // Check that ControllerHandle is a valid handle\r
1443   //\r
1444   if (ControllerHandle == NULL) {\r
1445     return EFI_INVALID_PARAMETER;\r
1446   }\r
1447 \r
1448   //\r
1449   // Read the environment variable(s) that contain the override mappings from Controller Device Path to\r
1450   // a set of Driver Device Paths, and  initialize in memory database of the overrides that map Controller\r
1451   // Device Paths to an ordered set of Driver Device Paths and Driver Handles. This action is only performed\r
1452   // once and finished in first call.\r
1453   //\r
1454   if (!mEnvironmentVariableRead) {\r
1455     mEnvironmentVariableRead = TRUE;\r
1456 \r
1457     Status = InitOverridesMapping (&mMappingDataBase);\r
1458     if (EFI_ERROR (Status)){\r
1459       DEBUG ((DEBUG_ERROR, "The status to Get Platform Driver Override Variable is %r\n", Status));\r
1460       InitializeListHead (&mMappingDataBase);\r
1461       return EFI_NOT_FOUND;\r
1462     }\r
1463   }\r
1464 \r
1465   //\r
1466   // if the environment variable does not exist, just return not found\r
1467   //\r
1468   if (IsListEmpty (&mMappingDataBase)) {\r
1469     return EFI_NOT_FOUND;\r
1470   }\r
1471 \r
1472   return GetDriverFromMapping (\r
1473             ControllerHandle,\r
1474             DriverImageHandle,\r
1475             &mMappingDataBase,\r
1476             mCallerImageHandle\r
1477             );\r
1478 }\r
1479 \r
1480 /**\r
1481   Retrieves the device path of the platform override driver for a controller in the system.\r
1482   This driver doesn't support this API.\r
1483 \r
1484   @param  This                  A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_\r
1485                                 PROTOCOL instance.                            \r
1486   @param  ControllerHandle      The device handle of the controller to check if a driver override\r
1487                                 exists.                                                          \r
1488   @param  DriverImagePath       On input, a pointer to the previous driver device path returned by\r
1489                                 GetDriverPath(). On output, a pointer to the next driver\r
1490                                 device path. Passing in a pointer to NULL, will return the first\r
1491                                 driver device path for ControllerHandle.\r
1492   \r
1493   @retval EFI_UNSUPPORTED\r
1494 **/\r
1495 EFI_STATUS\r
1496 EFIAPI\r
1497 GetDriverPath (\r
1498   IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL              *This,\r
1499   IN     EFI_HANDLE                                     ControllerHandle,\r
1500   IN OUT EFI_DEVICE_PATH_PROTOCOL                       **DriverImagePath\r
1501   )\r
1502 {\r
1503   return EFI_UNSUPPORTED;\r
1504 }\r
1505 \r
1506 \r
1507 /**\r
1508   Used to associate a driver image handle with a device path that was returned on a prior call to the\r
1509   GetDriverPath() service. This driver image handle will then be available through the               \r
1510   GetDriver() service. This driver doesn't support this API.\r
1511 \r
1512   @param  This                  A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_\r
1513                                 PROTOCOL instance.                            \r
1514   @param  ControllerHandle      The device handle of the controller.                                                             \r
1515   @param  DriverImagePath       A pointer to the driver device path that was returned in a prior\r
1516                                 call to GetDriverPath().                                                                        \r
1517   @param  DriverImageHandle     The driver image handle that was returned by LoadImage()\r
1518                                 when the driver specified by DriverImagePath was loaded \r
1519                                 into memory. \r
1520   \r
1521   @retval EFI_UNSUPPORTED\r
1522 **/\r
1523 EFI_STATUS\r
1524 EFIAPI\r
1525 DriverLoaded (\r
1526   IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL          *This,\r
1527   IN EFI_HANDLE                                     ControllerHandle,\r
1528   IN EFI_DEVICE_PATH_PROTOCOL                       *DriverImagePath,\r
1529   IN EFI_HANDLE                                     DriverImageHandle\r
1530   )\r
1531 {\r
1532   return EFI_UNSUPPORTED;\r
1533 }\r
1534 \r
1535 /**\r
1536   The driver Entry Point. The funciton will export a disk device class formset and\r
1537   its callback function to hii database.\r
1538 \r
1539   @param  ImageHandle    The firmware allocated handle for the EFI image.\r
1540   @param  SystemTable    A pointer to the EFI System Table.\r
1541 \r
1542   @retval EFI_SUCCESS    The entry point is executed successfully.\r
1543   @retval other          Some error occurs when executing this entry point.\r
1544 \r
1545 **/\r
1546 EFI_STATUS\r
1547 EFIAPI\r
1548 PlatDriOverrideDxeInit (\r
1549   IN EFI_HANDLE                   ImageHandle,\r
1550   IN EFI_SYSTEM_TABLE             *SystemTable\r
1551   )\r
1552 {\r
1553   EFI_STATUS                  Status;\r
1554   EFI_FORM_BROWSER2_PROTOCOL  *FormBrowser2;\r
1555   VOID                        *Instance;\r
1556   \r
1557   //\r
1558   // There should only be one Form Configuration protocol\r
1559   //\r
1560   Status = gBS->LocateProtocol (\r
1561                  &gEfiFormBrowser2ProtocolGuid,\r
1562                  NULL,\r
1563                  (VOID **) &FormBrowser2\r
1564                  );\r
1565   if (EFI_ERROR (Status)) {\r
1566     return Status;\r
1567   }\r
1568 \r
1569   //\r
1570   // According to UEFI spec, there can be at most a single instance\r
1571   // in the system of the EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL.\r
1572   // So here we check the existence.\r
1573   //\r
1574   Status = gBS->LocateProtocol (\r
1575                   &gEfiPlatformDriverOverrideProtocolGuid,\r
1576                   NULL,\r
1577                   &Instance\r
1578                   );\r
1579   //\r
1580   // If there was no error, assume there is an installation and return error\r
1581   //\r
1582   if (!EFI_ERROR (Status)) {\r
1583     return EFI_ALREADY_STARTED;\r
1584   }\r
1585   \r
1586   mCallerImageHandle = ImageHandle;\r
1587   mCallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO));\r
1588   if (mCallbackInfo == NULL) {\r
1589     return EFI_BAD_BUFFER_SIZE;\r
1590   }\r
1591 \r
1592   mCallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;\r
1593   mCallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig;\r
1594   mCallbackInfo->ConfigAccess.RouteConfig   = PlatOverMngrRouteConfig;\r
1595   mCallbackInfo->ConfigAccess.Callback      = PlatOverMngrCallback;\r
1596   mCallbackInfo->PlatformDriverOverride.GetDriver      = GetDriver;\r
1597   mCallbackInfo->PlatformDriverOverride.GetDriverPath  = GetDriverPath;\r
1598   mCallbackInfo->PlatformDriverOverride.DriverLoaded   = DriverLoaded;\r
1599   //\r
1600   // Install Device Path Protocol and Config Access protocol to driver handle\r
1601   // Install Platform Driver Override Protocol to driver handle\r
1602   //\r
1603   Status = gBS->InstallMultipleProtocolInterfaces (\r
1604                   &mCallbackInfo->DriverHandle,\r
1605                   &gEfiDevicePathProtocolGuid,\r
1606                   &mHiiVendorDevicePath,\r
1607                   &gEfiHiiConfigAccessProtocolGuid,\r
1608                   &mCallbackInfo->ConfigAccess,\r
1609                   &gEfiPlatformDriverOverrideProtocolGuid,\r
1610                   &mCallbackInfo->PlatformDriverOverride,\r
1611                   NULL\r
1612                   );\r
1613   if (EFI_ERROR (Status)) {\r
1614     goto Finish;\r
1615   }\r
1616 \r
1617   //\r
1618   // Publish our HII data\r
1619   //\r
1620   mCallbackInfo->RegisteredHandle = HiiAddPackages (\r
1621                                      &mPlatformOverridesManagerGuid,\r
1622                                      mCallbackInfo->DriverHandle,\r
1623                                      VfrBin,\r
1624                                      PlatDriOverrideDxeStrings,\r
1625                                      NULL\r
1626                                      );\r
1627   if (mCallbackInfo->RegisteredHandle == NULL) {\r
1628     Status = EFI_OUT_OF_RESOURCES;\r
1629     goto Finish;\r
1630   }\r
1631 \r
1632   //\r
1633   // Locate ConfigRouting protocol\r
1634   //\r
1635   Status = gBS->LocateProtocol (\r
1636                   &gEfiHiiConfigRoutingProtocolGuid,\r
1637                   NULL,\r
1638                   (VOID **) &mCallbackInfo->HiiConfigRouting\r
1639                   );\r
1640   if (EFI_ERROR (Status)) {\r
1641     goto Finish;\r
1642   }\r
1643 \r
1644   //\r
1645   // Clear all the globle variable\r
1646   //\r
1647   mDriverImageHandleCount = 0;\r
1648   mCurrentPage = 0;\r
1649   ZeroMem (mDriverImageToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
1650   ZeroMem (mDriverImageFilePathToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
1651   ZeroMem (mControllerToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
1652   ZeroMem (mDriverImageProtocol, MAX_CHOICE_NUM * sizeof (EFI_LOADED_IMAGE_PROTOCOL *));\r
1653   \r
1654   return EFI_SUCCESS;\r
1655 \r
1656 Finish:\r
1657   if (mCallbackInfo->DriverHandle != NULL) {\r
1658     gBS->UninstallMultipleProtocolInterfaces (\r
1659            mCallbackInfo->DriverHandle,\r
1660            &gEfiDevicePathProtocolGuid,\r
1661            &mHiiVendorDevicePath,\r
1662            &gEfiHiiConfigAccessProtocolGuid,\r
1663            &mCallbackInfo->ConfigAccess,\r
1664            &gEfiPlatformDriverOverrideProtocolGuid,\r
1665            &mCallbackInfo->PlatformDriverOverride,\r
1666            NULL\r
1667            );\r
1668   }\r
1669   \r
1670   if (mCallbackInfo->RegisteredHandle != NULL) {\r
1671     HiiRemovePackages (mCallbackInfo->RegisteredHandle);\r
1672   }\r
1673 \r
1674   if (mCallbackInfo != NULL) {\r
1675     FreePool (mCallbackInfo);\r
1676   }\r
1677 \r
1678   return Status;\r
1679 }\r
1680 \r
1681 /**\r
1682   Unload its installed protocol.\r
1683 \r
1684   @param[in]  ImageHandle       Handle that identifies the image to be unloaded.\r
1685 \r
1686   @retval EFI_SUCCESS           The image has been unloaded.\r
1687 **/\r
1688 EFI_STATUS\r
1689 EFIAPI\r
1690 PlatDriOverrideDxeUnload (\r
1691   IN EFI_HANDLE  ImageHandle\r
1692   )\r
1693 {\r
1694   if (mCallbackInfo->DriverHandle != NULL) {\r
1695     gBS->UninstallMultipleProtocolInterfaces (\r
1696            mCallbackInfo->DriverHandle,\r
1697            &gEfiDevicePathProtocolGuid,\r
1698            &mHiiVendorDevicePath,\r
1699            &gEfiHiiConfigAccessProtocolGuid,\r
1700            &mCallbackInfo->ConfigAccess,\r
1701            &gEfiPlatformDriverOverrideProtocolGuid,\r
1702            &mCallbackInfo->PlatformDriverOverride,\r
1703            NULL\r
1704            );\r
1705   }\r
1706 \r
1707   if (mCallbackInfo->RegisteredHandle != NULL) {\r
1708     HiiRemovePackages (mCallbackInfo->RegisteredHandle);\r
1709   }\r
1710 \r
1711   if (mCallbackInfo != NULL) {\r
1712     FreePool (mCallbackInfo);\r
1713   }\r
1714 \r
1715   return EFI_SUCCESS;\r
1716 }\r