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