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