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