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