1 /** @file 2 The functions for Boot Maintainence Main menu. 3 4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "BootMaintenanceManager.h" 16 17 #define FRONT_PAGE_KEY_OFFSET 0x4000 18 // 19 // Boot video resolution and text mode. 20 // 21 UINT32 mBmmBootHorizontalResolution = 0; 22 UINT32 mBmmBootVerticalResolution = 0; 23 UINT32 mBmmBootTextModeColumn = 0; 24 UINT32 mBmmBootTextModeRow = 0; 25 // 26 // BIOS setup video resolution and text mode. 27 // 28 UINT32 mBmmSetupTextModeColumn = 0; 29 UINT32 mBmmSetupTextModeRow = 0; 30 UINT32 mBmmSetupHorizontalResolution = 0; 31 UINT32 mBmmSetupVerticalResolution = 0; 32 33 BOOLEAN mBmmModeInitialized = FALSE; 34 35 EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = { 36 { 37 END_DEVICE_PATH_TYPE, 38 END_ENTIRE_DEVICE_PATH_SUBTYPE, 39 { 40 END_DEVICE_PATH_LENGTH, 41 0 42 } 43 } 44 }; 45 46 HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = { 47 { 48 { 49 HARDWARE_DEVICE_PATH, 50 HW_VENDOR_DP, 51 { 52 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), 53 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) 54 } 55 }, 56 // 57 // {165A028F-0BB2-4b5f-8747-77592E3F6499} 58 // 59 { 0x165a028f, 0xbb2, 0x4b5f, { 0x87, 0x47, 0x77, 0x59, 0x2e, 0x3f, 0x64, 0x99 } } 60 }, 61 { 62 END_DEVICE_PATH_TYPE, 63 END_ENTIRE_DEVICE_PATH_SUBTYPE, 64 { 65 (UINT8) (END_DEVICE_PATH_LENGTH), 66 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) 67 } 68 } 69 }; 70 71 EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID; 72 73 CHAR16 mBootMaintStorageName[] = L"BmmData"; 74 BMM_CALLBACK_DATA gBootMaintenancePrivate = { 75 BMM_CALLBACK_DATA_SIGNATURE, 76 NULL, 77 NULL, 78 { 79 BootMaintExtractConfig, 80 BootMaintRouteConfig, 81 BootMaintCallback 82 } 83 }; 84 85 BMM_CALLBACK_DATA *mBmmCallbackInfo = &gBootMaintenancePrivate; 86 BOOLEAN mAllMenuInit = FALSE; 87 BOOLEAN mFirstEnterBMMForm = FALSE; 88 89 /** 90 Init all memu. 91 92 @param CallbackData The BMM context data. 93 94 **/ 95 VOID 96 InitAllMenu ( 97 IN BMM_CALLBACK_DATA *CallbackData 98 ); 99 100 /** 101 Free up all Menu Option list. 102 103 **/ 104 VOID 105 FreeAllMenu ( 106 VOID 107 ); 108 109 /** 110 111 Update the menus in the BMM page. 112 113 **/ 114 VOID 115 CustomizeMenus ( 116 VOID 117 ); 118 119 /** 120 This function will change video resolution and text mode 121 according to defined setup mode or defined boot mode 122 123 @param IsSetupMode Indicate mode is changed to setup mode or boot mode. 124 125 @retval EFI_SUCCESS Mode is changed successfully. 126 @retval Others Mode failed to be changed. 127 128 **/ 129 EFI_STATUS 130 BmmSetConsoleMode ( 131 BOOLEAN IsSetupMode 132 ) 133 { 134 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; 135 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; 136 UINTN SizeOfInfo; 137 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; 138 UINT32 MaxGopMode; 139 UINT32 MaxTextMode; 140 UINT32 ModeNumber; 141 UINT32 NewHorizontalResolution; 142 UINT32 NewVerticalResolution; 143 UINT32 NewColumns; 144 UINT32 NewRows; 145 UINTN HandleCount; 146 EFI_HANDLE *HandleBuffer; 147 EFI_STATUS Status; 148 UINTN Index; 149 UINTN CurrentColumn; 150 UINTN CurrentRow; 151 152 MaxGopMode = 0; 153 MaxTextMode = 0; 154 155 // 156 // Get current video resolution and text mode 157 // 158 Status = gBS->HandleProtocol ( 159 gST->ConsoleOutHandle, 160 &gEfiGraphicsOutputProtocolGuid, 161 (VOID**)&GraphicsOutput 162 ); 163 if (EFI_ERROR (Status)) { 164 GraphicsOutput = NULL; 165 } 166 167 Status = gBS->HandleProtocol ( 168 gST->ConsoleOutHandle, 169 &gEfiSimpleTextOutProtocolGuid, 170 (VOID**)&SimpleTextOut 171 ); 172 if (EFI_ERROR (Status)) { 173 SimpleTextOut = NULL; 174 } 175 176 if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) { 177 return EFI_UNSUPPORTED; 178 } 179 180 if (IsSetupMode) { 181 // 182 // The required resolution and text mode is setup mode. 183 // 184 NewHorizontalResolution = mBmmSetupHorizontalResolution; 185 NewVerticalResolution = mBmmSetupVerticalResolution; 186 NewColumns = mBmmSetupTextModeColumn; 187 NewRows = mBmmSetupTextModeRow; 188 } else { 189 // 190 // The required resolution and text mode is boot mode. 191 // 192 NewHorizontalResolution = mBmmBootHorizontalResolution; 193 NewVerticalResolution = mBmmBootVerticalResolution; 194 NewColumns = mBmmBootTextModeColumn; 195 NewRows = mBmmBootTextModeRow; 196 } 197 198 if (GraphicsOutput != NULL) { 199 MaxGopMode = GraphicsOutput->Mode->MaxMode; 200 } 201 202 if (SimpleTextOut != NULL) { 203 MaxTextMode = SimpleTextOut->Mode->MaxMode; 204 } 205 206 // 207 // 1. If current video resolution is same with required video resolution, 208 // video resolution need not be changed. 209 // 1.1. If current text mode is same with required text mode, text mode need not be changed. 210 // 1.2. If current text mode is different from required text mode, text mode need be changed. 211 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers. 212 // 213 for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) { 214 Status = GraphicsOutput->QueryMode ( 215 GraphicsOutput, 216 ModeNumber, 217 &SizeOfInfo, 218 &Info 219 ); 220 if (!EFI_ERROR (Status)) { 221 if ((Info->HorizontalResolution == NewHorizontalResolution) && 222 (Info->VerticalResolution == NewVerticalResolution)) { 223 if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) && 224 (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) { 225 // 226 // Current resolution is same with required resolution, check if text mode need be set 227 // 228 Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow); 229 ASSERT_EFI_ERROR (Status); 230 if (CurrentColumn == NewColumns && CurrentRow == NewRows) { 231 // 232 // If current text mode is same with required text mode. Do nothing 233 // 234 FreePool (Info); 235 return EFI_SUCCESS; 236 } else { 237 // 238 // If current text mode is different from required text mode. Set new video mode 239 // 240 for (Index = 0; Index < MaxTextMode; Index++) { 241 Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow); 242 if (!EFI_ERROR(Status)) { 243 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) { 244 // 245 // Required text mode is supported, set it. 246 // 247 Status = SimpleTextOut->SetMode (SimpleTextOut, Index); 248 ASSERT_EFI_ERROR (Status); 249 // 250 // Update text mode PCD. 251 // 252 Status = PcdSet32S (PcdConOutColumn, mBmmSetupTextModeColumn); 253 ASSERT_EFI_ERROR (Status); 254 Status = PcdSet32S (PcdConOutRow, mBmmSetupTextModeRow); 255 ASSERT_EFI_ERROR (Status); 256 FreePool (Info); 257 return EFI_SUCCESS; 258 } 259 } 260 } 261 if (Index == MaxTextMode) { 262 // 263 // If required text mode is not supported, return error. 264 // 265 FreePool (Info); 266 return EFI_UNSUPPORTED; 267 } 268 } 269 } else { 270 // 271 // If current video resolution is not same with the new one, set new video resolution. 272 // In this case, the driver which produces simple text out need be restarted. 273 // 274 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber); 275 if (!EFI_ERROR (Status)) { 276 FreePool (Info); 277 break; 278 } 279 } 280 } 281 FreePool (Info); 282 } 283 } 284 285 if (ModeNumber == MaxGopMode) { 286 // 287 // If the resolution is not supported, return error. 288 // 289 return EFI_UNSUPPORTED; 290 } 291 292 // 293 // Set PCD to Inform GraphicsConsole to change video resolution. 294 // Set PCD to Inform Consplitter to change text mode. 295 // 296 Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution); 297 ASSERT_EFI_ERROR (Status); 298 Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution); 299 ASSERT_EFI_ERROR (Status); 300 Status = PcdSet32S (PcdConOutColumn, NewColumns); 301 ASSERT_EFI_ERROR (Status); 302 Status = PcdSet32S (PcdConOutRow, NewRows); 303 ASSERT_EFI_ERROR (Status); 304 305 // 306 // Video mode is changed, so restart graphics console driver and higher level driver. 307 // Reconnect graphics console driver and higher level driver. 308 // Locate all the handles with GOP protocol and reconnect it. 309 // 310 Status = gBS->LocateHandleBuffer ( 311 ByProtocol, 312 &gEfiSimpleTextOutProtocolGuid, 313 NULL, 314 &HandleCount, 315 &HandleBuffer 316 ); 317 if (!EFI_ERROR (Status)) { 318 for (Index = 0; Index < HandleCount; Index++) { 319 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); 320 } 321 for (Index = 0; Index < HandleCount; Index++) { 322 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); 323 } 324 if (HandleBuffer != NULL) { 325 FreePool (HandleBuffer); 326 } 327 } 328 329 return EFI_SUCCESS; 330 } 331 332 /** 333 This function converts an input device structure to a Unicode string. 334 335 @param DevPath A pointer to the device path structure. 336 337 @return A new allocated Unicode string that represents the device path. 338 339 **/ 340 CHAR16 * 341 UiDevicePathToStr ( 342 IN EFI_DEVICE_PATH_PROTOCOL *DevPath 343 ) 344 { 345 EFI_STATUS Status; 346 CHAR16 *ToText; 347 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; 348 349 if (DevPath == NULL) { 350 return NULL; 351 } 352 353 Status = gBS->LocateProtocol ( 354 &gEfiDevicePathToTextProtocolGuid, 355 NULL, 356 (VOID **) &DevPathToText 357 ); 358 ASSERT_EFI_ERROR (Status); 359 ToText = DevPathToText->ConvertDevicePathToText ( 360 DevPath, 361 FALSE, 362 TRUE 363 ); 364 ASSERT (ToText != NULL); 365 return ToText; 366 } 367 368 /** 369 Extract filename from device path. The returned buffer is allocated using AllocateCopyPool. 370 The caller is responsible for freeing the allocated buffer using FreePool(). 371 372 @param DevicePath Device path. 373 374 @return A new allocated string that represents the file name. 375 376 **/ 377 CHAR16 * 378 ExtractFileNameFromDevicePath ( 379 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath 380 ) 381 { 382 CHAR16 *String; 383 CHAR16 *MatchString; 384 CHAR16 *LastMatch; 385 CHAR16 *FileName; 386 UINTN Length; 387 388 ASSERT(DevicePath != NULL); 389 390 String = UiDevicePathToStr(DevicePath); 391 MatchString = String; 392 LastMatch = String; 393 FileName = NULL; 394 395 while(MatchString != NULL){ 396 LastMatch = MatchString + 1; 397 MatchString = StrStr(LastMatch,L"\\"); 398 } 399 400 Length = StrLen(LastMatch); 401 FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch); 402 if (FileName != NULL) { 403 *(FileName + Length) = 0; 404 } 405 406 FreePool(String); 407 408 return FileName; 409 } 410 411 /** 412 Extract device path for given HII handle and class guid. 413 414 @param Handle The HII handle. 415 416 @retval NULL Fail to get the device path string. 417 @return PathString Get the device path string. 418 419 **/ 420 CHAR16 * 421 BmmExtractDevicePathFromHiiHandle ( 422 IN EFI_HII_HANDLE Handle 423 ) 424 { 425 EFI_STATUS Status; 426 EFI_HANDLE DriverHandle; 427 428 ASSERT (Handle != NULL); 429 430 if (Handle == NULL) { 431 return NULL; 432 } 433 434 Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle); 435 if (EFI_ERROR (Status)) { 436 return NULL; 437 } 438 439 // 440 // Get device path string. 441 // 442 return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle), FALSE, FALSE); 443 444 } 445 446 /** 447 Converts the unicode character of the string from uppercase to lowercase. 448 This is a internal function. 449 450 @param ConfigString String to be converted 451 452 **/ 453 VOID 454 HiiToLower ( 455 IN EFI_STRING ConfigString 456 ) 457 { 458 EFI_STRING String; 459 BOOLEAN Lower; 460 461 ASSERT (ConfigString != NULL); 462 463 // 464 // Convert all hex digits in range [A-F] in the configuration header to [a-f] 465 // 466 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) { 467 if (*String == L'=') { 468 Lower = TRUE; 469 } else if (*String == L'&') { 470 Lower = FALSE; 471 } else if (Lower && *String >= L'A' && *String <= L'F') { 472 *String = (CHAR16) (*String - L'A' + L'a'); 473 } 474 } 475 } 476 477 /** 478 Update the progress string through the offset value. 479 480 @param Offset The offset value 481 @param Configuration Point to the configuration string. 482 483 **/ 484 EFI_STRING 485 UpdateProgress( 486 IN UINTN Offset, 487 IN EFI_STRING Configuration 488 ) 489 { 490 UINTN Length; 491 EFI_STRING StringPtr; 492 EFI_STRING ReturnString; 493 494 StringPtr = NULL; 495 ReturnString = NULL; 496 497 // 498 // &OFFSET=XXXX followed by a Null-terminator. 499 // Length = StrLen (L"&OFFSET=") + 4 + 1 500 // 501 Length = StrLen (L"&OFFSET=") + 4 + 1; 502 503 StringPtr = AllocateZeroPool (Length * sizeof (CHAR16)); 504 505 if (StringPtr == NULL) { 506 return NULL; 507 } 508 509 UnicodeSPrint ( 510 StringPtr, 511 (8 + 4 + 1) * sizeof (CHAR16), 512 L"&OFFSET=%04x", 513 Offset 514 ); 515 516 ReturnString = StrStr (Configuration, StringPtr); 517 518 if (ReturnString == NULL) { 519 // 520 // If doesn't find the string in Configuration, convert the string to lower case then search again. 521 // 522 HiiToLower (StringPtr); 523 ReturnString = StrStr (Configuration, StringPtr); 524 } 525 526 FreePool (StringPtr); 527 528 return ReturnString; 529 } 530 531 /** 532 Update the terminal content in TerminalMenu. 533 534 @param BmmData The BMM fake NV data. 535 536 **/ 537 VOID 538 UpdateTerminalContent ( 539 IN BMM_FAKE_NV_DATA *BmmData 540 ) 541 { 542 UINT16 Index; 543 BM_TERMINAL_CONTEXT *NewTerminalContext; 544 BM_MENU_ENTRY *NewMenuEntry; 545 546 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { 547 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); 548 ASSERT (NewMenuEntry != NULL); 549 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; 550 NewTerminalContext->BaudRateIndex = BmmData->COMBaudRate[Index]; 551 ASSERT (BmmData->COMBaudRate[Index] < (ARRAY_SIZE (BaudRateList))); 552 NewTerminalContext->BaudRate = BaudRateList[BmmData->COMBaudRate[Index]].Value; 553 NewTerminalContext->DataBitsIndex = BmmData->COMDataRate[Index]; 554 ASSERT (BmmData->COMDataRate[Index] < (ARRAY_SIZE (DataBitsList))); 555 NewTerminalContext->DataBits = (UINT8) DataBitsList[BmmData->COMDataRate[Index]].Value; 556 NewTerminalContext->StopBitsIndex = BmmData->COMStopBits[Index]; 557 ASSERT (BmmData->COMStopBits[Index] < (ARRAY_SIZE (StopBitsList))); 558 NewTerminalContext->StopBits = (UINT8) StopBitsList[BmmData->COMStopBits[Index]].Value; 559 NewTerminalContext->ParityIndex = BmmData->COMParity[Index]; 560 ASSERT (BmmData->COMParity[Index] < (ARRAY_SIZE (ParityList))); 561 NewTerminalContext->Parity = (UINT8) ParityList[BmmData->COMParity[Index]].Value; 562 NewTerminalContext->TerminalType = BmmData->COMTerminalType[Index]; 563 NewTerminalContext->FlowControl = BmmData->COMFlowControl[Index]; 564 ChangeTerminalDevicePath ( 565 NewTerminalContext->DevicePath, 566 FALSE 567 ); 568 } 569 } 570 571 /** 572 Update the console content in ConsoleMenu. 573 574 @param ConsoleName The name for the console device type. 575 @param BmmData The BMM fake NV data. 576 577 **/ 578 VOID 579 UpdateConsoleContent( 580 IN CHAR16 *ConsoleName, 581 IN BMM_FAKE_NV_DATA *BmmData 582 ) 583 { 584 UINT16 Index; 585 BM_CONSOLE_CONTEXT *NewConsoleContext; 586 BM_TERMINAL_CONTEXT *NewTerminalContext; 587 BM_MENU_ENTRY *NewMenuEntry; 588 589 if (StrCmp (ConsoleName, L"ConIn") == 0) { 590 for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++){ 591 NewMenuEntry = BOpt_GetMenuEntry(&ConsoleInpMenu, Index); 592 NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext; 593 ASSERT (Index < MAX_MENU_NUMBER); 594 NewConsoleContext->IsActive = BmmData->ConsoleInCheck[Index]; 595 } 596 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { 597 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); 598 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; 599 ASSERT (Index + ConsoleInpMenu.MenuNumber < MAX_MENU_NUMBER); 600 NewTerminalContext->IsConIn = BmmData->ConsoleInCheck[Index + ConsoleInpMenu.MenuNumber]; 601 } 602 } 603 604 if (StrCmp (ConsoleName, L"ConOut") == 0) { 605 for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++){ 606 NewMenuEntry = BOpt_GetMenuEntry(&ConsoleOutMenu, Index); 607 NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext; 608 ASSERT (Index < MAX_MENU_NUMBER); 609 NewConsoleContext->IsActive = BmmData->ConsoleOutCheck[Index]; 610 } 611 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { 612 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); 613 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; 614 ASSERT (Index + ConsoleOutMenu.MenuNumber < MAX_MENU_NUMBER); 615 NewTerminalContext->IsConOut = BmmData->ConsoleOutCheck[Index + ConsoleOutMenu.MenuNumber]; 616 } 617 } 618 if (StrCmp (ConsoleName, L"ErrOut") == 0) { 619 for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++){ 620 NewMenuEntry = BOpt_GetMenuEntry(&ConsoleErrMenu, Index); 621 NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext; 622 ASSERT (Index < MAX_MENU_NUMBER); 623 NewConsoleContext->IsActive = BmmData->ConsoleErrCheck[Index]; 624 } 625 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { 626 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); 627 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; 628 ASSERT (Index + ConsoleErrMenu.MenuNumber < MAX_MENU_NUMBER); 629 NewTerminalContext->IsStdErr = BmmData->ConsoleErrCheck[Index + ConsoleErrMenu.MenuNumber]; 630 } 631 } 632 } 633 634 /** 635 This function allows a caller to extract the current configuration for one 636 or more named elements from the target driver. 637 638 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 639 @param Request A null-terminated Unicode string in <ConfigRequest> format. 640 @param Progress On return, points to a character in the Request string. 641 Points to the string's null terminator if request was successful. 642 Points to the most recent '&' before the first failing name/value 643 pair (or the beginning of the string if the failure is in the 644 first name/value pair) if the request was not successful. 645 @param Results A null-terminated Unicode string in <ConfigAltResp> format which 646 has all values filled in for the names in the Request string. 647 String to be allocated by the called function. 648 649 @retval EFI_SUCCESS The Results is filled with the requested values. 650 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. 651 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. 652 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. 653 654 **/ 655 EFI_STATUS 656 EFIAPI 657 BootMaintExtractConfig ( 658 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 659 IN CONST EFI_STRING Request, 660 OUT EFI_STRING *Progress, 661 OUT EFI_STRING *Results 662 ) 663 { 664 EFI_STATUS Status; 665 UINTN BufferSize; 666 BMM_CALLBACK_DATA *Private; 667 EFI_STRING ConfigRequestHdr; 668 EFI_STRING ConfigRequest; 669 BOOLEAN AllocatedRequest; 670 UINTN Size; 671 672 if (Progress == NULL || Results == NULL) { 673 return EFI_INVALID_PARAMETER; 674 } 675 676 *Progress = Request; 677 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mBootMaintGuid, mBootMaintStorageName)) { 678 return EFI_NOT_FOUND; 679 } 680 681 ConfigRequestHdr = NULL; 682 ConfigRequest = NULL; 683 AllocatedRequest = FALSE; 684 Size = 0; 685 686 Private = BMM_CALLBACK_DATA_FROM_THIS (This); 687 // 688 // Convert buffer data to <ConfigResp> by helper function BlockToConfig() 689 // 690 BufferSize = sizeof (BMM_FAKE_NV_DATA); 691 ConfigRequest = Request; 692 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { 693 // 694 // Request has no request element, construct full request string. 695 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template 696 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator 697 // 698 ConfigRequestHdr = HiiConstructConfigHdr (&mBootMaintGuid, mBootMaintStorageName, Private->BmmDriverHandle); 699 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); 700 ConfigRequest = AllocateZeroPool (Size); 701 ASSERT (ConfigRequest != NULL); 702 AllocatedRequest = TRUE; 703 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); 704 FreePool (ConfigRequestHdr); 705 } 706 707 Status = gHiiConfigRouting->BlockToConfig ( 708 gHiiConfigRouting, 709 ConfigRequest, 710 (UINT8 *) &Private->BmmFakeNvData, 711 BufferSize, 712 Results, 713 Progress 714 ); 715 // 716 // Free the allocated config request string. 717 // 718 if (AllocatedRequest) { 719 FreePool (ConfigRequest); 720 ConfigRequest = NULL; 721 } 722 // 723 // Set Progress string to the original request string. 724 // 725 if (Request == NULL) { 726 *Progress = NULL; 727 } else if (StrStr (Request, L"OFFSET") == NULL) { 728 *Progress = Request + StrLen (Request); 729 } 730 731 return Status; 732 } 733 734 /** 735 This function applies changes in a driver's configuration. 736 Input is a Configuration, which has the routing data for this 737 driver followed by name / value configuration pairs. The driver 738 must apply those pairs to its configurable storage. If the 739 driver's configuration is stored in a linear block of data 740 and the driver's name / value pairs are in <BlockConfig> 741 format, it may use the ConfigToBlock helper function (above) to 742 simplify the job. Currently not implemented. 743 744 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 745 @param[in] Configuration A null-terminated Unicode string in 746 <ConfigString> format. 747 @param[out] Progress A pointer to a string filled in with the 748 offset of the most recent '&' before the 749 first failing name / value pair (or the 750 beginn ing of the string if the failure 751 is in the first name / value pair) or 752 the terminating NULL if all was 753 successful. 754 755 @retval EFI_SUCCESS The results have been distributed or are 756 awaiting distribution. 757 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the 758 parts of the results that must be 759 stored awaiting possible future 760 protocols. 761 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the 762 Results parameter would result 763 in this type of error. 764 @retval EFI_NOT_FOUND Target for the specified routing data 765 was not found. 766 **/ 767 EFI_STATUS 768 EFIAPI 769 BootMaintRouteConfig ( 770 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 771 IN CONST EFI_STRING Configuration, 772 OUT EFI_STRING *Progress 773 ) 774 { 775 EFI_STATUS Status; 776 UINTN BufferSize; 777 EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; 778 BMM_FAKE_NV_DATA *NewBmmData; 779 BMM_FAKE_NV_DATA *OldBmmData; 780 BM_MENU_ENTRY *NewMenuEntry; 781 BM_LOAD_CONTEXT *NewLoadContext; 782 UINT16 Index; 783 BOOLEAN TerminalAttChange; 784 BMM_CALLBACK_DATA *Private; 785 UINTN Offset; 786 787 if (Progress == NULL) { 788 return EFI_INVALID_PARAMETER; 789 } 790 *Progress = Configuration; 791 792 if (Configuration == NULL) { 793 return EFI_INVALID_PARAMETER; 794 } 795 796 // 797 // Check routing data in <ConfigHdr>. 798 // Note: there is no name for Name/Value storage, only GUID will be checked 799 // 800 if (!HiiIsConfigHdrMatch (Configuration, &mBootMaintGuid, mBootMaintStorageName)) { 801 return EFI_NOT_FOUND; 802 } 803 804 Status = gBS->LocateProtocol ( 805 &gEfiHiiConfigRoutingProtocolGuid, 806 NULL, 807 (VOID **)&ConfigRouting 808 ); 809 if (EFI_ERROR (Status)) { 810 return Status; 811 } 812 813 Private = BMM_CALLBACK_DATA_FROM_THIS (This); 814 // 815 // Get Buffer Storage data from EFI variable 816 // 817 BufferSize = sizeof (BMM_FAKE_NV_DATA); 818 OldBmmData = &Private->BmmOldFakeNVData; 819 NewBmmData = &Private->BmmFakeNvData; 820 Offset = 0; 821 // 822 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock() 823 // 824 Status = ConfigRouting->ConfigToBlock ( 825 ConfigRouting, 826 Configuration, 827 (UINT8 *) NewBmmData, 828 &BufferSize, 829 Progress 830 ); 831 ASSERT_EFI_ERROR (Status); 832 // 833 // Compare new and old BMM configuration data and only do action for modified item to 834 // avoid setting unnecessary non-volatile variable 835 // 836 837 // 838 // Check data which located in BMM main page and save the settings if need 839 // 840 if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) { 841 Status = Var_UpdateBootNext (Private); 842 if (EFI_ERROR (Status)) { 843 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootNext); 844 goto Exit; 845 } 846 } 847 848 // 849 // Check data which located in Boot Options Menu and save the settings if need 850 // 851 if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) { 852 for (Index = 0; 853 ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); 854 Index ++) { 855 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); 856 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 857 NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index]; 858 NewBmmData->BootOptionDel[Index] = FALSE; 859 NewBmmData->BootOptionDelMark[Index] = FALSE; 860 } 861 862 Status = Var_DelBootOption (); 863 if (EFI_ERROR (Status)) { 864 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionDel); 865 goto Exit; 866 } 867 } 868 869 if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) { 870 Status = Var_UpdateBootOrder (Private); 871 if (EFI_ERROR (Status)) { 872 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionOrder); 873 goto Exit; 874 } 875 } 876 877 if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0){ 878 Status = gRT->SetVariable( 879 L"Timeout", 880 &gEfiGlobalVariableGuid, 881 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 882 sizeof(UINT16), 883 &(NewBmmData->BootTimeOut) 884 ); 885 if (EFI_ERROR (Status)) { 886 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootTimeOut); 887 goto Exit; 888 } 889 Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut; 890 } 891 892 // 893 // Check data which located in Driver Options Menu and save the settings if need 894 // 895 if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) { 896 for (Index = 0; 897 ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); 898 Index++) { 899 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); 900 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 901 NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index]; 902 NewBmmData->DriverOptionDel[Index] = FALSE; 903 NewBmmData->DriverOptionDelMark[Index] = FALSE; 904 } 905 Status = Var_DelDriverOption (); 906 if (EFI_ERROR (Status)) { 907 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionDel); 908 goto Exit; 909 } 910 } 911 912 if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) { 913 Status = Var_UpdateDriverOrder (Private); 914 if (EFI_ERROR (Status)) { 915 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionOrder); 916 goto Exit; 917 } 918 } 919 920 if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0){ 921 Status = Var_UpdateConMode(Private); 922 if (EFI_ERROR (Status)) { 923 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleOutMode); 924 goto Exit; 925 } 926 } 927 928 TerminalAttChange = FALSE; 929 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { 930 931 // 932 // only need update modified items 933 // 934 if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 && 935 CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 && 936 CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 && 937 CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 && 938 CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 && 939 CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) { 940 continue; 941 } 942 943 TerminalAttChange = TRUE; 944 } 945 if (TerminalAttChange) { 946 if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) != 0) { 947 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMBaudRate); 948 } else if (CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) != 0) { 949 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMDataRate); 950 } else if (CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) != 0) { 951 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMStopBits); 952 } else if (CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) != 0) { 953 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMParity); 954 } else if (CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) != 0) { 955 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMTerminalType); 956 } else if (CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) != 0) { 957 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMFlowControl); 958 } 959 Status = Var_UpdateConsoleInpOption (); 960 if (EFI_ERROR (Status)) { 961 goto Exit; 962 } 963 Status = Var_UpdateConsoleOutOption (); 964 if (EFI_ERROR (Status)) { 965 goto Exit; 966 } 967 Status = Var_UpdateErrorOutOption (); 968 if (EFI_ERROR (Status)) { 969 goto Exit; 970 } 971 } 972 // 973 // Check data which located in Console Options Menu and save the settings if need 974 // 975 if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0){ 976 Status = Var_UpdateConsoleInpOption(); 977 if (EFI_ERROR (Status)) { 978 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleInCheck); 979 goto Exit; 980 } 981 } 982 983 if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0){ 984 Status = Var_UpdateConsoleOutOption(); 985 if (EFI_ERROR (Status)) { 986 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleOutCheck); 987 goto Exit; 988 } 989 } 990 991 if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0){ 992 Status = Var_UpdateErrorOutOption(); 993 if (EFI_ERROR (Status)) { 994 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleErrCheck); 995 goto Exit; 996 } 997 } 998 999 if (CompareMem (NewBmmData->BootDescriptionData, OldBmmData->BootDescriptionData, sizeof (NewBmmData->BootDescriptionData)) != 0 || 1000 CompareMem (NewBmmData->BootOptionalData, OldBmmData->BootOptionalData, sizeof (NewBmmData->BootOptionalData)) != 0) { 1001 Status = Var_UpdateBootOption (Private); 1002 NewBmmData->BootOptionChanged = FALSE; 1003 if (EFI_ERROR (Status)) { 1004 if (CompareMem (NewBmmData->BootDescriptionData, OldBmmData->BootDescriptionData, sizeof (NewBmmData->BootDescriptionData)) != 0) { 1005 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootDescriptionData); 1006 } else { 1007 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionalData); 1008 } 1009 goto Exit; 1010 } 1011 BOpt_GetBootOptions (Private); 1012 } 1013 1014 if (CompareMem (NewBmmData->DriverDescriptionData, OldBmmData->DriverDescriptionData, sizeof (NewBmmData->DriverDescriptionData)) != 0 || 1015 CompareMem (NewBmmData->DriverOptionalData, OldBmmData->DriverOptionalData, sizeof (NewBmmData->DriverOptionalData)) != 0) { 1016 Status = Var_UpdateDriverOption ( 1017 Private, 1018 Private->BmmHiiHandle, 1019 NewBmmData->DriverDescriptionData, 1020 NewBmmData->DriverOptionalData, 1021 NewBmmData->ForceReconnect 1022 ); 1023 NewBmmData->DriverOptionChanged = FALSE; 1024 NewBmmData->ForceReconnect = TRUE; 1025 if (EFI_ERROR (Status)) { 1026 if (CompareMem (NewBmmData->DriverDescriptionData, OldBmmData->DriverDescriptionData, sizeof (NewBmmData->DriverDescriptionData)) != 0) { 1027 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverDescriptionData); 1028 } else { 1029 Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionalData); 1030 } 1031 goto Exit; 1032 } 1033 1034 BOpt_GetDriverOptions (Private); 1035 } 1036 1037 // 1038 // After user do the save action, need to update OldBmmData. 1039 // 1040 CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA)); 1041 1042 return EFI_SUCCESS; 1043 1044 Exit: 1045 // 1046 // Fail to save the data, update the progress string. 1047 // 1048 *Progress = UpdateProgress (Offset, Configuration); 1049 if (Status == EFI_OUT_OF_RESOURCES) { 1050 return Status; 1051 } else { 1052 return EFI_NOT_FOUND; 1053 } 1054 } 1055 1056 /** 1057 This function processes the results of changes in configuration. 1058 1059 1060 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 1061 @param Action Specifies the type of action taken by the browser. 1062 @param QuestionId A unique value which is sent to the original exporting driver 1063 so that it can identify the type of data to expect. 1064 @param Type The type of value for the question. 1065 @param Value A pointer to the data being sent to the original exporting driver. 1066 @param ActionRequest On return, points to the action requested by the callback function. 1067 1068 @retval EFI_SUCCESS The callback successfully handled the action. 1069 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. 1070 @retval EFI_DEVICE_ERROR The variable could not be saved. 1071 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. 1072 @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. 1073 **/ 1074 EFI_STATUS 1075 EFIAPI 1076 BootMaintCallback ( 1077 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 1078 IN EFI_BROWSER_ACTION Action, 1079 IN EFI_QUESTION_ID QuestionId, 1080 IN UINT8 Type, 1081 IN EFI_IFR_TYPE_VALUE *Value, 1082 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest 1083 ) 1084 { 1085 BMM_CALLBACK_DATA *Private; 1086 BM_MENU_ENTRY *NewMenuEntry; 1087 BMM_FAKE_NV_DATA *CurrentFakeNVMap; 1088 BMM_FAKE_NV_DATA *OldFakeNVMap; 1089 UINTN Index; 1090 EFI_DEVICE_PATH_PROTOCOL * File; 1091 1092 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_FORM_OPEN) { 1093 // 1094 // Do nothing for other UEFI Action. Only do call back when data is changed or the form is open. 1095 // 1096 return EFI_UNSUPPORTED; 1097 } 1098 1099 Private = BMM_CALLBACK_DATA_FROM_THIS (This); 1100 1101 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { 1102 if (QuestionId == KEY_VALUE_TRIGGER_FORM_OPEN_ACTION) { 1103 if (!mFirstEnterBMMForm) { 1104 // 1105 // BMMUiLib depends on LegacyUi library to show legacy menus. 1106 // If we want to show Legacy menus correctly in BMM page, 1107 // we must do it after the LegacyUi library has already been initialized. 1108 // Opening the BMM form is the appropriate time that the LegacyUi library has already been initialized. 1109 // So we do the tasks which are related to legacy menus here. 1110 // 1. Update the menus (including legacy munu) show in BootMiantenanceManager page. 1111 // 2. Re-scan the BootOption menus (including the legacy boot option). 1112 // 1113 CustomizeMenus (); 1114 BOpt_GetBootOptions (Private); 1115 mFirstEnterBMMForm = TRUE; 1116 } 1117 } 1118 } 1119 // 1120 // Retrieve uncommitted data from Form Browser 1121 // 1122 CurrentFakeNVMap = &Private->BmmFakeNvData; 1123 OldFakeNVMap = &Private->BmmOldFakeNVData; 1124 HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); 1125 1126 if (Action == EFI_BROWSER_ACTION_CHANGING) { 1127 if (Value == NULL) { 1128 return EFI_INVALID_PARAMETER; 1129 } 1130 1131 UpdatePageId (Private, QuestionId); 1132 1133 if (QuestionId < FILE_OPTION_OFFSET) { 1134 if (QuestionId < CONFIG_OPTION_OFFSET) { 1135 switch (QuestionId) { 1136 case FORM_BOOT_ADD_ID: 1137 // Leave BMM and enter FileExplorer. 1138 ChooseFile (NULL, L".efi", CreateBootOptionFromFile, &File); 1139 break; 1140 1141 case FORM_DRV_ADD_FILE_ID: 1142 // Leave BMM and enter FileExplorer. 1143 ChooseFile (NULL, L".efi", CreateDriverOptionFromFile, &File); 1144 break; 1145 1146 case FORM_DRV_ADD_HANDLE_ID: 1147 CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); 1148 UpdateDrvAddHandlePage (Private); 1149 break; 1150 1151 case FORM_BOOT_DEL_ID: 1152 CleanUpPage (FORM_BOOT_DEL_ID, Private); 1153 UpdateBootDelPage (Private); 1154 break; 1155 1156 case FORM_BOOT_CHG_ID: 1157 case FORM_DRV_CHG_ID: 1158 UpdatePageBody (QuestionId, Private); 1159 break; 1160 1161 case FORM_DRV_DEL_ID: 1162 CleanUpPage (FORM_DRV_DEL_ID, Private); 1163 UpdateDrvDelPage (Private); 1164 break; 1165 1166 case FORM_CON_IN_ID: 1167 case FORM_CON_OUT_ID: 1168 case FORM_CON_ERR_ID: 1169 UpdatePageBody (QuestionId, Private); 1170 break; 1171 1172 case FORM_CON_MODE_ID: 1173 CleanUpPage (FORM_CON_MODE_ID, Private); 1174 UpdateConModePage (Private); 1175 break; 1176 1177 case FORM_CON_COM_ID: 1178 CleanUpPage (FORM_CON_COM_ID, Private); 1179 UpdateConCOMPage (Private); 1180 break; 1181 1182 default: 1183 break; 1184 } 1185 } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { 1186 Index = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); 1187 Private->CurrentTerminal = Index; 1188 1189 CleanUpPage (FORM_CON_COM_SETUP_ID, Private); 1190 UpdateTerminalPage (Private); 1191 1192 } else if (QuestionId >= HANDLE_OPTION_OFFSET) { 1193 Index = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); 1194 1195 NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); 1196 ASSERT (NewMenuEntry != NULL); 1197 Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; 1198 1199 CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); 1200 1201 Private->MenuEntry = NewMenuEntry; 1202 Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; 1203 1204 UpdateDriverAddHandleDescPage (Private); 1205 } 1206 } 1207 if (QuestionId == KEY_VALUE_BOOT_FROM_FILE){ 1208 // Leave BMM and enter FileExplorer. 1209 ChooseFile (NULL, L".efi", BootFromFile, &File); 1210 } 1211 } else if (Action == EFI_BROWSER_ACTION_CHANGED) { 1212 if ((Value == NULL) || (ActionRequest == NULL)) { 1213 return EFI_INVALID_PARAMETER; 1214 } 1215 1216 if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) { 1217 CurrentFakeNVMap->BootOptionChanged = FALSE; 1218 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; 1219 } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { 1220 CurrentFakeNVMap->DriverOptionChanged = FALSE; 1221 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; 1222 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { 1223 // 1224 // Discard changes and exit formset 1225 // 1226 ZeroMem (CurrentFakeNVMap->DriverOptionalData, sizeof (CurrentFakeNVMap->DriverOptionalData)); 1227 ZeroMem (CurrentFakeNVMap->BootDescriptionData, sizeof (CurrentFakeNVMap->BootDescriptionData)); 1228 ZeroMem (OldFakeNVMap->DriverOptionalData, sizeof (OldFakeNVMap->DriverOptionalData)); 1229 ZeroMem (OldFakeNVMap->DriverDescriptionData, sizeof (OldFakeNVMap->DriverDescriptionData)); 1230 CurrentFakeNVMap->DriverOptionChanged = FALSE; 1231 CurrentFakeNVMap->ForceReconnect = TRUE; 1232 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; 1233 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) { 1234 // 1235 // Discard changes and exit formset 1236 // 1237 ZeroMem (CurrentFakeNVMap->BootOptionalData, sizeof (CurrentFakeNVMap->BootOptionalData)); 1238 ZeroMem (CurrentFakeNVMap->BootDescriptionData, sizeof (CurrentFakeNVMap->BootDescriptionData)); 1239 ZeroMem (OldFakeNVMap->BootOptionalData, sizeof (OldFakeNVMap->BootOptionalData)); 1240 ZeroMem (OldFakeNVMap->BootDescriptionData, sizeof (OldFakeNVMap->BootDescriptionData)); 1241 CurrentFakeNVMap->BootOptionChanged = FALSE; 1242 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; 1243 } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) { 1244 CurrentFakeNVMap->BootOptionChanged = TRUE; 1245 } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) { 1246 CurrentFakeNVMap->DriverOptionChanged = TRUE; 1247 } 1248 1249 if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { 1250 if (Value->b){ 1251 // 1252 // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu. 1253 // 1254 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE; 1255 } else { 1256 // 1257 // Means user remove the old check status. 1258 // 1259 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE; 1260 } 1261 } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { 1262 if (Value->b){ 1263 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE; 1264 } else { 1265 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE; 1266 } 1267 } else { 1268 switch (QuestionId) { 1269 case KEY_VALUE_SAVE_AND_EXIT: 1270 case KEY_VALUE_NO_SAVE_AND_EXIT: 1271 if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) { 1272 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; 1273 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) { 1274 DiscardChangeHandler (Private, CurrentFakeNVMap); 1275 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; 1276 } 1277 1278 break; 1279 1280 case FORM_RESET: 1281 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); 1282 return EFI_UNSUPPORTED; 1283 1284 default: 1285 break; 1286 } 1287 } 1288 // 1289 // Update the content in Terminal menu and Console menu here. 1290 // 1291 if (QuestionId == COM_BAUD_RATE_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_DATA_RATE_QUESTION_ID + Private->CurrentTerminal || 1292 QuestionId == COM_PARITY_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_STOP_BITS_QUESTION_ID + Private->CurrentTerminal || 1293 QuestionId == COM_TERMINAL_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_FLOWCONTROL_QUESTION_ID + Private->CurrentTerminal 1294 ) { 1295 UpdateTerminalContent(CurrentFakeNVMap); 1296 } 1297 if ((QuestionId >= CON_IN_DEVICE_QUESTION_ID) && (QuestionId < CON_IN_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) { 1298 UpdateConsoleContent (L"ConIn",CurrentFakeNVMap); 1299 } else if ((QuestionId >= CON_OUT_DEVICE_QUESTION_ID) && (QuestionId < CON_OUT_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) { 1300 UpdateConsoleContent (L"ConOut", CurrentFakeNVMap); 1301 } else if ((QuestionId >= CON_ERR_DEVICE_QUESTION_ID) && (QuestionId < CON_ERR_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) { 1302 UpdateConsoleContent (L"ConErr", CurrentFakeNVMap); 1303 } 1304 } 1305 1306 // 1307 // Pass changed uncommitted data back to Form Browser 1308 // 1309 HiiSetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); 1310 1311 return EFI_SUCCESS; 1312 } 1313 1314 /** 1315 Discard all changes done to the BMM pages such as Boot Order change, 1316 Driver order change. 1317 1318 @param Private The BMM context data. 1319 @param CurrentFakeNVMap The current Fack NV Map. 1320 1321 **/ 1322 VOID 1323 DiscardChangeHandler ( 1324 IN BMM_CALLBACK_DATA *Private, 1325 IN BMM_FAKE_NV_DATA *CurrentFakeNVMap 1326 ) 1327 { 1328 UINT16 Index; 1329 1330 switch (Private->BmmPreviousPageId) { 1331 case FORM_BOOT_CHG_ID: 1332 CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder)); 1333 break; 1334 1335 case FORM_DRV_CHG_ID: 1336 CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder)); 1337 break; 1338 1339 case FORM_BOOT_DEL_ID: 1340 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0]))); 1341 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { 1342 CurrentFakeNVMap->BootOptionDel[Index] = FALSE; 1343 } 1344 break; 1345 1346 case FORM_DRV_DEL_ID: 1347 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0]))); 1348 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { 1349 CurrentFakeNVMap->DriverOptionDel[Index] = FALSE; 1350 } 1351 break; 1352 1353 case FORM_BOOT_NEXT_ID: 1354 CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext; 1355 break; 1356 1357 case FORM_TIME_OUT_ID: 1358 CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut; 1359 break; 1360 1361 case FORM_DRV_ADD_HANDLE_DESC_ID: 1362 case FORM_DRV_ADD_FILE_ID: 1363 case FORM_DRV_ADD_HANDLE_ID: 1364 CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000; 1365 CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000; 1366 break; 1367 1368 default: 1369 break; 1370 } 1371 } 1372 1373 /** 1374 1375 Update the menus in the BMM page. 1376 1377 **/ 1378 VOID 1379 CustomizeMenus ( 1380 VOID 1381 ) 1382 { 1383 VOID *StartOpCodeHandle; 1384 VOID *EndOpCodeHandle; 1385 EFI_IFR_GUID_LABEL *StartGuidLabel; 1386 EFI_IFR_GUID_LABEL *EndGuidLabel; 1387 1388 // 1389 // Allocate space for creation of UpdateData Buffer 1390 // 1391 StartOpCodeHandle = HiiAllocateOpCodeHandle (); 1392 ASSERT (StartOpCodeHandle != NULL); 1393 1394 EndOpCodeHandle = HiiAllocateOpCodeHandle (); 1395 ASSERT (EndOpCodeHandle != NULL); 1396 // 1397 // Create Hii Extend Label OpCode as the start opcode 1398 // 1399 StartGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 1400 StartGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 1401 StartGuidLabel->Number = LABEL_FORM_MAIN_START; 1402 // 1403 // Create Hii Extend Label OpCode as the end opcode 1404 // 1405 EndGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 1406 EndGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 1407 EndGuidLabel->Number = LABEL_FORM_MAIN_END; 1408 1409 // 1410 //Updata Front Page form 1411 // 1412 UiCustomizeBMMPage ( 1413 mBmmCallbackInfo->BmmHiiHandle, 1414 StartOpCodeHandle 1415 ); 1416 1417 HiiUpdateForm ( 1418 mBmmCallbackInfo->BmmHiiHandle, 1419 &mBootMaintGuid, 1420 FORM_MAIN_ID, 1421 StartOpCodeHandle, 1422 EndOpCodeHandle 1423 ); 1424 1425 HiiFreeOpCodeHandle (StartOpCodeHandle); 1426 HiiFreeOpCodeHandle (EndOpCodeHandle); 1427 } 1428 1429 /** 1430 Create dynamic code for BMM and initialize all of BMM configuration data in BmmFakeNvData and 1431 BmmOldFakeNVData member in BMM context data. 1432 1433 @param CallbackData The BMM context data. 1434 1435 **/ 1436 VOID 1437 InitializeBmmConfig ( 1438 IN BMM_CALLBACK_DATA *CallbackData 1439 ) 1440 { 1441 BM_MENU_ENTRY *NewMenuEntry; 1442 BM_LOAD_CONTEXT *NewLoadContext; 1443 UINT16 Index; 1444 1445 ASSERT (CallbackData != NULL); 1446 1447 // 1448 // Initialize data which located in BMM main page 1449 // 1450 CallbackData->BmmFakeNvData.BootNext = NONE_BOOTNEXT_VALUE; 1451 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { 1452 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); 1453 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 1454 1455 if (NewLoadContext->IsBootNext) { 1456 CallbackData->BmmFakeNvData.BootNext = Index; 1457 break; 1458 } 1459 } 1460 1461 CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); 1462 1463 // 1464 // Initialize data which located in Boot Options Menu 1465 // 1466 GetBootOrder (CallbackData); 1467 1468 // 1469 // Initialize data which located in Driver Options Menu 1470 // 1471 GetDriverOrder (CallbackData); 1472 1473 // 1474 // Initialize data which located in Console Options Menu 1475 // 1476 GetConsoleOutMode (CallbackData); 1477 GetConsoleInCheck (CallbackData); 1478 GetConsoleOutCheck (CallbackData); 1479 GetConsoleErrCheck (CallbackData); 1480 GetTerminalAttribute (CallbackData); 1481 1482 CallbackData->BmmFakeNvData.ForceReconnect = TRUE; 1483 1484 // 1485 // Backup Initialize BMM configuartion data to BmmOldFakeNVData 1486 // 1487 CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA)); 1488 } 1489 1490 /** 1491 Initialized all Menu Option List. 1492 1493 @param CallbackData The BMM context data. 1494 1495 **/ 1496 VOID 1497 InitAllMenu ( 1498 IN BMM_CALLBACK_DATA *CallbackData 1499 ) 1500 { 1501 InitializeListHead (&BootOptionMenu.Head); 1502 InitializeListHead (&DriverOptionMenu.Head); 1503 BOpt_GetBootOptions (CallbackData); 1504 BOpt_GetDriverOptions (CallbackData); 1505 BOpt_FindDrivers (); 1506 InitializeListHead (&ConsoleInpMenu.Head); 1507 InitializeListHead (&ConsoleOutMenu.Head); 1508 InitializeListHead (&ConsoleErrMenu.Head); 1509 InitializeListHead (&TerminalMenu.Head); 1510 LocateSerialIo (); 1511 GetAllConsoles (); 1512 mAllMenuInit = TRUE; 1513 } 1514 1515 /** 1516 Free up all Menu Option list. 1517 1518 **/ 1519 VOID 1520 FreeAllMenu ( 1521 VOID 1522 ) 1523 { 1524 if (!mAllMenuInit){ 1525 return; 1526 } 1527 BOpt_FreeMenu (&BootOptionMenu); 1528 BOpt_FreeMenu (&DriverOptionMenu); 1529 BOpt_FreeMenu (&DriverMenu); 1530 FreeAllConsoles (); 1531 mAllMenuInit = FALSE; 1532 } 1533 1534 /** 1535 Initial the boot mode related parameters. 1536 1537 **/ 1538 VOID 1539 BmmInitialBootModeInfo ( 1540 VOID 1541 ) 1542 { 1543 EFI_STATUS Status; 1544 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; 1545 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; 1546 UINTN BootTextColumn; 1547 UINTN BootTextRow; 1548 1549 if (mBmmModeInitialized) { 1550 return; 1551 } 1552 1553 // 1554 // After the console is ready, get current video resolution 1555 // and text mode before launching setup at first time. 1556 // 1557 Status = gBS->HandleProtocol ( 1558 gST->ConsoleOutHandle, 1559 &gEfiGraphicsOutputProtocolGuid, 1560 (VOID**)&GraphicsOutput 1561 ); 1562 if (EFI_ERROR (Status)) { 1563 GraphicsOutput = NULL; 1564 } 1565 1566 Status = gBS->HandleProtocol ( 1567 gST->ConsoleOutHandle, 1568 &gEfiSimpleTextOutProtocolGuid, 1569 (VOID**)&SimpleTextOut 1570 ); 1571 if (EFI_ERROR (Status)) { 1572 SimpleTextOut = NULL; 1573 } 1574 1575 if (GraphicsOutput != NULL) { 1576 // 1577 // Get current video resolution and text mode. 1578 // 1579 mBmmBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution; 1580 mBmmBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution; 1581 } 1582 1583 if (SimpleTextOut != NULL) { 1584 Status = SimpleTextOut->QueryMode ( 1585 SimpleTextOut, 1586 SimpleTextOut->Mode->Mode, 1587 &BootTextColumn, 1588 &BootTextRow 1589 ); 1590 mBmmBootTextModeColumn = (UINT32)BootTextColumn; 1591 mBmmBootTextModeRow = (UINT32)BootTextRow; 1592 } 1593 1594 // 1595 // Get user defined text mode for setup. 1596 // 1597 mBmmSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution); 1598 mBmmSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); 1599 mBmmSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn); 1600 mBmmSetupTextModeRow = PcdGet32 (PcdSetupConOutRow); 1601 1602 mBmmModeInitialized = TRUE; 1603 } 1604 1605 /** 1606 1607 Install Boot Maintenance Manager Menu driver. 1608 1609 @param ImageHandle The image handle. 1610 @param SystemTable The system table. 1611 1612 @retval EFI_SUCEESS Install Boot manager menu success. 1613 @retval Other Return error status. 1614 1615 **/ 1616 EFI_STATUS 1617 EFIAPI 1618 BootMaintenanceManagerUiLibConstructor ( 1619 IN EFI_HANDLE ImageHandle, 1620 IN EFI_SYSTEM_TABLE *SystemTable 1621 ) 1622 1623 { 1624 EFI_STATUS Status; 1625 UINT8 *Ptr; 1626 1627 Status = EFI_SUCCESS; 1628 1629 // 1630 // Install Device Path Protocol and Config Access protocol to driver handle 1631 // 1632 Status = gBS->InstallMultipleProtocolInterfaces ( 1633 &mBmmCallbackInfo->BmmDriverHandle, 1634 &gEfiDevicePathProtocolGuid, 1635 &mBmmHiiVendorDevicePath, 1636 &gEfiHiiConfigAccessProtocolGuid, 1637 &mBmmCallbackInfo->BmmConfigAccess, 1638 NULL 1639 ); 1640 ASSERT_EFI_ERROR (Status); 1641 1642 // 1643 // Post our Boot Maint VFR binary to the HII database. 1644 // 1645 mBmmCallbackInfo->BmmHiiHandle = HiiAddPackages ( 1646 &mBootMaintGuid, 1647 mBmmCallbackInfo->BmmDriverHandle, 1648 BootMaintenanceManagerBin, 1649 BootMaintenanceManagerUiLibStrings, 1650 NULL 1651 ); 1652 ASSERT (mBmmCallbackInfo->BmmHiiHandle != NULL); 1653 1654 // 1655 // Locate Formbrowser2 protocol 1656 // 1657 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mBmmCallbackInfo->FormBrowser2); 1658 ASSERT_EFI_ERROR (Status); 1659 1660 EfiBootManagerRefreshAllBootOption (); 1661 1662 // 1663 // Create LoadOption in BmmCallbackInfo for Driver Callback 1664 // 1665 Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY)); 1666 ASSERT (Ptr != NULL); 1667 1668 // 1669 // Initialize Bmm callback data. 1670 // 1671 mBmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr; 1672 Ptr += sizeof (BM_LOAD_CONTEXT); 1673 1674 mBmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr; 1675 Ptr += sizeof (BM_FILE_CONTEXT); 1676 1677 mBmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr; 1678 Ptr += sizeof (BM_HANDLE_CONTEXT); 1679 1680 mBmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr; 1681 1682 mBmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; 1683 mBmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; 1684 1685 InitAllMenu (mBmmCallbackInfo); 1686 1687 CreateUpdateData(); 1688 // 1689 // Update boot maintenance manager page 1690 // 1691 InitializeBmmConfig(mBmmCallbackInfo); 1692 1693 BmmInitialBootModeInfo(); 1694 1695 return EFI_SUCCESS; 1696 } 1697 1698 /** 1699 Unloads the application and its installed protocol. 1700 1701 @param ImageHandle Handle that identifies the image to be unloaded. 1702 @param SystemTable The system table. 1703 1704 @retval EFI_SUCCESS The image has been unloaded. 1705 1706 **/ 1707 EFI_STATUS 1708 EFIAPI 1709 BootMaintenanceManagerUiLibDestructor ( 1710 IN EFI_HANDLE ImageHandle, 1711 IN EFI_SYSTEM_TABLE *SystemTable 1712 ) 1713 1714 { 1715 if (mStartOpCodeHandle != NULL) { 1716 HiiFreeOpCodeHandle (mStartOpCodeHandle); 1717 } 1718 1719 if (mEndOpCodeHandle != NULL) { 1720 HiiFreeOpCodeHandle (mEndOpCodeHandle); 1721 } 1722 1723 FreeAllMenu (); 1724 1725 // 1726 // Remove our IFR data from HII database 1727 // 1728 HiiRemovePackages (mBmmCallbackInfo->BmmHiiHandle); 1729 1730 gBS->UninstallMultipleProtocolInterfaces ( 1731 mBmmCallbackInfo->BmmDriverHandle, 1732 &gEfiDevicePathProtocolGuid, 1733 &mBmmHiiVendorDevicePath, 1734 &gEfiHiiConfigAccessProtocolGuid, 1735 &mBmmCallbackInfo->BmmConfigAccess, 1736 NULL 1737 ); 1738 1739 FreePool (mBmmCallbackInfo->LoadContext); 1740 1741 return EFI_SUCCESS; 1742 } 1743 1744