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