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