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