1 /** @file 2 Main file for BCFG command. 3 4 (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR> 5 Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 17 #include <Uefi.h> 18 #include <ShellBase.h> 19 20 #include <Guid/GlobalVariable.h> 21 #include <Guid/ShellLibHiiGuid.h> 22 23 #include <Protocol/EfiShell.h> 24 #include <Protocol/EfiShellParameters.h> 25 #include <Protocol/DevicePath.h> 26 #include <Protocol/LoadedImage.h> 27 #include <Protocol/UnicodeCollation.h> 28 29 #include <Library/BaseLib.h> 30 #include <Library/BaseMemoryLib.h> 31 #include <Library/DebugLib.h> 32 #include <Library/MemoryAllocationLib.h> 33 #include <Library/PcdLib.h> 34 #include <Library/ShellCommandLib.h> 35 #include <Library/ShellLib.h> 36 #include <Library/SortLib.h> 37 #include <Library/UefiLib.h> 38 #include <Library/UefiRuntimeServicesTableLib.h> 39 #include <Library/UefiBootServicesTableLib.h> 40 #include <Library/HiiLib.h> 41 #include <Library/FileHandleLib.h> 42 #include <Library/PrintLib.h> 43 #include <Library/HandleParsingLib.h> 44 #include <Library/DevicePathLib.h> 45 46 STATIC CONST CHAR16 mFileName[] = L"ShellCommands"; 47 STATIC EFI_HANDLE gShellBcfgHiiHandle = NULL; 48 49 typedef enum { 50 BcfgTargetBootOrder = 0, 51 BcfgTargetDriverOrder = 1, 52 BcfgTargetMax = 2 53 } BCFG_OPERATION_TARGET; 54 55 typedef enum { 56 BcfgTypeDump = 0, 57 BcfgTypeAdd = 1, 58 BcfgTypeAddp = 2, 59 BcfgTypeAddh = 3, 60 BcfgTypeRm = 4, 61 BcfgTypeMv = 5, 62 BcfgTypeOpt = 6, 63 BcfgTypeMax = 7 64 } BCFG_OPERATION_TYPE; 65 66 typedef struct { 67 BCFG_OPERATION_TARGET Target; 68 BCFG_OPERATION_TYPE Type; 69 UINT16 Number1; 70 UINT16 Number2; 71 UINTN HandleIndex; 72 CHAR16 *FileName; 73 CHAR16 *Description; 74 UINT16 *Order; 75 CONST CHAR16 *OptData; 76 } BGFG_OPERATION; 77 78 /** 79 Update the optional data for a boot or driver option. 80 81 If optional data exists it will be changed. 82 83 @param[in] Index The boot or driver option index update. 84 @param[in] DataSize The size in bytes of Data. 85 @param[in] Data The buffer for the optioanl data. 86 @param[in] Target The target of the operation. 87 88 @retval EFI_SUCCESS The data was sucessfully updated. 89 @retval other A error occured. 90 **/ 91 EFI_STATUS 92 EFIAPI 93 UpdateOptionalData( 94 UINT16 Index, 95 UINTN DataSize, 96 UINT8 *Data, 97 IN CONST BCFG_OPERATION_TARGET Target 98 ) 99 { 100 EFI_STATUS Status; 101 CHAR16 VariableName[12]; 102 UINTN OriginalSize; 103 UINT8 *OriginalData; 104 UINTN NewSize; 105 UINT8 *NewData; 106 UINTN OriginalOptionDataSize; 107 108 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", Index); 109 110 OriginalSize = 0; 111 OriginalData = NULL; 112 NewData = NULL; 113 NewSize = 0; 114 115 Status = gRT->GetVariable( 116 VariableName, 117 (EFI_GUID*)&gEfiGlobalVariableGuid, 118 NULL, 119 &OriginalSize, 120 OriginalData); 121 if (Status == EFI_BUFFER_TOO_SMALL) { 122 OriginalData = AllocateZeroPool(OriginalSize); 123 if (OriginalData == NULL) { 124 return (EFI_OUT_OF_RESOURCES); 125 } 126 Status = gRT->GetVariable( 127 VariableName, 128 (EFI_GUID*)&gEfiGlobalVariableGuid, 129 NULL, 130 &OriginalSize, 131 OriginalData); 132 } 133 134 if (!EFI_ERROR(Status)) { 135 // 136 // Allocate new struct and discard old optional data. 137 // 138 ASSERT (OriginalData != NULL); 139 OriginalOptionDataSize = sizeof(UINT32) + sizeof(UINT16) + StrSize(((CHAR16*)(OriginalData + sizeof(UINT32) + sizeof(UINT16)))); 140 OriginalOptionDataSize += (*(UINT16*)(OriginalData + sizeof(UINT32))); 141 OriginalOptionDataSize -= OriginalSize; 142 NewSize = OriginalSize - OriginalOptionDataSize + DataSize; 143 NewData = AllocateCopyPool(NewSize, OriginalData); 144 if (NewData == NULL) { 145 Status = EFI_OUT_OF_RESOURCES; 146 } else { 147 CopyMem(NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize); 148 } 149 } 150 151 if (!EFI_ERROR(Status)) { 152 // 153 // put the data back under the variable 154 // 155 Status = gRT->SetVariable( 156 VariableName, 157 (EFI_GUID*)&gEfiGlobalVariableGuid, 158 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, 159 NewSize, 160 NewData); 161 } 162 163 SHELL_FREE_NON_NULL(OriginalData); 164 SHELL_FREE_NON_NULL(NewData); 165 return (Status); 166 } 167 168 /** 169 This function will get a CRC for a boot option. 170 171 @param[in, out] Crc The CRC value to return. 172 @param[in] BootIndex The boot option index to CRC. 173 174 @retval EFI_SUCCESS The CRC was sucessfully returned. 175 @retval other A error occured. 176 **/ 177 EFI_STATUS 178 EFIAPI 179 GetBootOptionCrc( 180 UINT32 *Crc, 181 UINT16 BootIndex 182 ) 183 { 184 CHAR16 VariableName[12]; 185 EFI_STATUS Status; 186 UINT8 *Buffer; 187 UINTN BufferSize; 188 189 Buffer = NULL; 190 BufferSize = 0; 191 192 // 193 // Get the data Buffer 194 // 195 UnicodeSPrint(VariableName, sizeof(VariableName), L"%Boot%04x", BootIndex); 196 Status = gRT->GetVariable( 197 VariableName, 198 (EFI_GUID*)&gEfiGlobalVariableGuid, 199 NULL, 200 &BufferSize, 201 NULL); 202 if (Status == EFI_BUFFER_TOO_SMALL) { 203 Buffer = AllocateZeroPool(BufferSize); 204 Status = gRT->GetVariable( 205 VariableName, 206 (EFI_GUID*)&gEfiGlobalVariableGuid, 207 NULL, 208 &BufferSize, 209 Buffer); 210 } 211 212 // 213 // Get the CRC computed 214 // 215 if (!EFI_ERROR(Status)) { 216 Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc); 217 } 218 219 SHELL_FREE_NON_NULL(Buffer); 220 return EFI_SUCCESS; 221 } 222 223 /** 224 This function will populate the device path protocol parameter based on TheHandle. 225 226 @param[in] TheHandle Driver handle. 227 @param[in, out] FilePath On a sucessful return the device path to the handle. 228 229 @retval EFI_SUCCESS The device path was sucessfully returned. 230 @retval other A error from gBS->HandleProtocol. 231 232 @sa HandleProtocol 233 **/ 234 EFI_STATUS 235 EFIAPI 236 GetDevicePathForDriverHandle ( 237 IN EFI_HANDLE TheHandle, 238 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath 239 ) 240 { 241 EFI_STATUS Status; 242 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 243 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; 244 245 Status = gBS->OpenProtocol ( 246 TheHandle, 247 &gEfiLoadedImageProtocolGuid, 248 (VOID**)&LoadedImage, 249 gImageHandle, 250 NULL, 251 EFI_OPEN_PROTOCOL_GET_PROTOCOL 252 ); 253 if (!EFI_ERROR (Status)) { 254 Status = gBS->OpenProtocol ( 255 LoadedImage->DeviceHandle, 256 &gEfiDevicePathProtocolGuid, 257 (VOID**)&ImageDevicePath, 258 gImageHandle, 259 NULL, 260 EFI_OPEN_PROTOCOL_GET_PROTOCOL 261 ); 262 if (!EFI_ERROR (Status)) { 263 // *DevPath = DuplicateDevicePath (ImageDevicePath); 264 // *FilePath = DuplicateDevicePath (LoadedImage->FilePath); 265 *FilePath = AppendDevicePath(ImageDevicePath,LoadedImage->FilePath); 266 gBS->CloseProtocol( 267 LoadedImage->DeviceHandle, 268 &gEfiDevicePathProtocolGuid, 269 gImageHandle, 270 NULL); 271 } 272 gBS->CloseProtocol( 273 TheHandle, 274 &gEfiLoadedImageProtocolGuid, 275 gImageHandle, 276 NULL); 277 } 278 return (Status); 279 } 280 281 /** 282 Function to add a option. 283 284 @param[in] Position The position to add Target at. 285 @param[in] File The file to make the target. 286 @param[in] Desc The description text. 287 @param[in] CurrentOrder The pointer to the current order of items. 288 @param[in] OrderCount The number if items in CurrentOrder. 289 @param[in] Target The info on the option to add. 290 @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc. 291 @param[in] UsePath TRUE to convert to devicepath. 292 @param[in] HandleNumber The handle number to add. 293 294 @retval SHELL_SUCCESS The operation was successful. 295 @retval SHELL_INVALID_PARAMETER A parameter was invalid. 296 **/ 297 SHELL_STATUS 298 EFIAPI 299 BcfgAdd( 300 IN UINTN Position, 301 IN CONST CHAR16 *File, 302 IN CONST CHAR16 *Desc, 303 IN CONST UINT16 *CurrentOrder, 304 IN CONST UINTN OrderCount, 305 IN CONST BCFG_OPERATION_TARGET Target, 306 IN CONST BOOLEAN UseHandle, 307 IN CONST BOOLEAN UsePath, 308 IN CONST UINTN HandleNumber 309 ) 310 { 311 EFI_STATUS Status; 312 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 313 EFI_DEVICE_PATH_PROTOCOL *FilePath; 314 CHAR16 *Str; 315 UINT8 *TempByteBuffer; 316 UINT8 *TempByteStart; 317 EFI_SHELL_FILE_INFO *Arg; 318 EFI_SHELL_FILE_INFO *FileList; 319 CHAR16 OptionStr[40]; 320 UINTN DescSize, FilePathSize; 321 BOOLEAN Found; 322 UINTN TargetLocation; 323 UINTN Index; 324 EFI_HANDLE *Handles; 325 EFI_HANDLE CurHandle; 326 UINTN DriverBindingHandleCount; 327 UINTN ParentControllerHandleCount; 328 UINTN ChildControllerHandleCount; 329 SHELL_STATUS ShellStatus; 330 UINT16 *NewOrder; 331 332 if (!UseHandle) { 333 if (File == NULL || Desc == NULL) { 334 return (SHELL_INVALID_PARAMETER); 335 } 336 } else { 337 if (HandleNumber == 0) { 338 return (SHELL_INVALID_PARAMETER); 339 } 340 } 341 342 if (Position > OrderCount) { 343 Position = OrderCount; 344 } 345 346 Str = NULL; 347 FilePath = NULL; 348 FileList = NULL; 349 Handles = NULL; 350 ShellStatus = SHELL_SUCCESS; 351 TargetLocation = 0xFFFF; 352 353 if (UseHandle) { 354 CurHandle = ConvertHandleIndexToHandle(HandleNumber); 355 if (CurHandle == NULL) { 356 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number"); 357 ShellStatus = SHELL_INVALID_PARAMETER; 358 } else { 359 if (Target == BcfgTargetBootOrder) { 360 // 361 //Make sure that the handle should point to a real controller 362 // 363 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( 364 CurHandle, 365 &DriverBindingHandleCount, 366 NULL); 367 368 Status = PARSE_HANDLE_DATABASE_PARENTS ( 369 CurHandle, 370 &ParentControllerHandleCount, 371 NULL); 372 373 Status = ParseHandleDatabaseForChildControllers ( 374 CurHandle, 375 &ChildControllerHandleCount, 376 NULL); 377 378 if (DriverBindingHandleCount > 0 379 || ParentControllerHandleCount > 0 380 || ChildControllerHandleCount > 0) { 381 FilePath = NULL; 382 Status = gBS->HandleProtocol ( 383 CurHandle, 384 &gEfiDevicePathProtocolGuid, 385 (VOID**)&FilePath); 386 } 387 if (EFI_ERROR (Status)) { 388 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, L"bcfg", HandleNumber); 389 ShellStatus = SHELL_INVALID_PARAMETER; 390 } 391 } else { 392 // 393 //Make sure that the handle should point to driver, not a controller. 394 // 395 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( 396 CurHandle, 397 &DriverBindingHandleCount, 398 NULL); 399 400 Status = PARSE_HANDLE_DATABASE_PARENTS ( 401 CurHandle, 402 &ParentControllerHandleCount, 403 NULL); 404 405 Status = ParseHandleDatabaseForChildControllers ( 406 CurHandle, 407 &ChildControllerHandleCount, 408 NULL); 409 410 Status = gBS->HandleProtocol ( 411 CurHandle, 412 &gEfiDevicePathProtocolGuid, 413 (VOID**)&FilePath); 414 415 if (DriverBindingHandleCount > 0 416 || ParentControllerHandleCount > 0 417 || ChildControllerHandleCount > 0 418 || !EFI_ERROR(Status) ) { 419 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number"); 420 ShellStatus = SHELL_INVALID_PARAMETER; 421 } else { 422 // 423 // Get the DevicePath from the loaded image information. 424 // 425 Status = GetDevicePathForDriverHandle(CurHandle, &FilePath); 426 } 427 } 428 } 429 } else { 430 // 431 // Get file info 432 // 433 ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList); 434 435 if (FileList == NULL) { 436 // 437 // If filename matched nothing fail 438 // 439 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", File); 440 ShellStatus = SHELL_INVALID_PARAMETER; 441 } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) { 442 // 443 // If filename expanded to multiple names, fail 444 // 445 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", File); 446 ShellStatus = SHELL_INVALID_PARAMETER; 447 } else { 448 Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link); 449 if (EFI_ERROR(Arg->Status)) { 450 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", File); 451 ShellStatus = SHELL_INVALID_PARAMETER; 452 } else { 453 // 454 // Build FilePath to the filename 455 // 456 457 // 458 // get the device path 459 // 460 DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName); 461 if (DevicePath == NULL) { 462 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName); 463 ShellStatus = SHELL_UNSUPPORTED; 464 } else { 465 /* 466 if (UsePath) { 467 DevPath = DevicePath; 468 while (!IsDevicePathEnd(DevPath)) { 469 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) && 470 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) { 471 472 // 473 // If we find it use it instead 474 // 475 DevicePath = DevPath; 476 break; 477 } 478 DevPath = NextDevicePathNode(DevPath); 479 } 480 // 481 // append the file 482 // 483 for(StringWalker=Arg->FullName; *StringWalker != CHAR_NULL && *StringWalker != ':'; StringWalker++); 484 FileNode = FileDevicePath(NULL, StringWalker+1); 485 FilePath = AppendDevicePath(DevicePath, FileNode); 486 FreePool(FileNode); 487 } else { 488 */ 489 FilePath = DuplicateDevicePath(DevicePath); 490 /* 491 } 492 */ 493 FreePool(DevicePath); 494 } 495 } 496 } 497 } 498 499 500 if (ShellStatus == SHELL_SUCCESS) { 501 // 502 // Find a free target ,a brute force implementation 503 // 504 Found = FALSE; 505 for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) { 506 Found = TRUE; 507 for (Index=0; Index < OrderCount; Index++) { 508 if (CurrentOrder[Index] == TargetLocation) { 509 Found = FALSE; 510 break; 511 } 512 } 513 514 if (Found) { 515 break; 516 } 517 } 518 519 if (TargetLocation == 0xFFFF) { 520 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle, L"bcfg"); 521 } else { 522 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation); 523 } 524 } 525 526 if (ShellStatus == SHELL_SUCCESS) { 527 // 528 // Add the option 529 // 530 DescSize = StrSize(Desc); 531 FilePathSize = GetDevicePathSize (FilePath); 532 533 TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize); 534 if (TempByteBuffer != NULL) { 535 TempByteStart = TempByteBuffer; 536 *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes 537 TempByteBuffer += sizeof (UINT32); 538 539 *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength 540 TempByteBuffer += sizeof (UINT16); 541 542 CopyMem (TempByteBuffer, Desc, DescSize); 543 TempByteBuffer += DescSize; 544 ASSERT (FilePath != NULL); 545 CopyMem (TempByteBuffer, FilePath, FilePathSize); 546 547 UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation); 548 Status = gRT->SetVariable ( 549 OptionStr, 550 &gEfiGlobalVariableGuid, 551 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, 552 sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize, 553 TempByteStart 554 ); 555 556 FreePool(TempByteStart); 557 } else { 558 Status = EFI_OUT_OF_RESOURCES; 559 } 560 561 if (EFI_ERROR(Status)) { 562 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr); 563 } else { 564 NewOrder = AllocateZeroPool((OrderCount+1)*sizeof(NewOrder[0])); 565 ASSERT(NewOrder != NULL); 566 CopyMem(NewOrder, CurrentOrder, (OrderCount)*sizeof(NewOrder[0])); 567 568 // 569 // Insert target into order list 570 // 571 for (Index=OrderCount; Index > Position; Index--) { 572 NewOrder[Index] = NewOrder[Index-1]; 573 } 574 575 NewOrder[Position] = (UINT16) TargetLocation; 576 Status = gRT->SetVariable ( 577 Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder", 578 &gEfiGlobalVariableGuid, 579 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, 580 (OrderCount+1) * sizeof(UINT16), 581 NewOrder 582 ); 583 584 FreePool(NewOrder); 585 586 if (EFI_ERROR(Status)) { 587 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder"); 588 ShellStatus = SHELL_INVALID_PARAMETER; 589 } else { 590 Print (L"bcfg: Add %s as %x\n", OptionStr, Position); 591 } 592 } 593 } 594 595 // 596 //If always Free FilePath, will free devicepath in system when use "addh" 597 // 598 if (FilePath!=NULL && !UseHandle) { 599 FreePool (FilePath); 600 } 601 602 if (Str != NULL) { 603 FreePool(Str); 604 } 605 606 if (Handles != NULL) { 607 FreePool (Handles); 608 } 609 610 if (FileList != NULL) { 611 ShellCloseFileMetaArg (&FileList); 612 } 613 614 return (ShellStatus); 615 } 616 617 /** 618 Funciton to remove an item. 619 620 @param[in] Target The target item to move. 621 @param[in] CurrentOrder The pointer to the current order of items. 622 @param[in] OrderCount The number if items in CurrentOrder. 623 @param[in] Location The current location of the Target. 624 625 @retval SHELL_SUCCESS The operation was successful. 626 @retval SHELL_INVALID_PARAMETER A parameter was invalid. 627 **/ 628 SHELL_STATUS 629 EFIAPI 630 BcfgRemove( 631 IN CONST BCFG_OPERATION_TARGET Target, 632 IN CONST UINT16 *CurrentOrder, 633 IN CONST UINTN OrderCount, 634 IN CONST UINT16 Location 635 ) 636 { 637 CHAR16 VariableName[12]; 638 UINT16 *NewOrder; 639 EFI_STATUS Status; 640 UINTN NewCount; 641 642 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]); 643 Status = gRT->SetVariable( 644 VariableName, 645 (EFI_GUID*)&gEfiGlobalVariableGuid, 646 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, 647 0, 648 NULL); 649 if (EFI_ERROR(Status)) { 650 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); 651 return (SHELL_INVALID_PARAMETER); 652 } 653 NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0])); 654 if (NewOrder != NULL) { 655 NewCount = OrderCount; 656 CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0])); 657 CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0])); 658 NewCount--; 659 660 Status = gRT->SetVariable( 661 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", 662 (EFI_GUID*)&gEfiGlobalVariableGuid, 663 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, 664 NewCount*sizeof(NewOrder[0]), 665 NewOrder); 666 FreePool(NewOrder); 667 } else { 668 Status = EFI_OUT_OF_RESOURCES; 669 } 670 if (EFI_ERROR(Status)) { 671 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder"); 672 return (SHELL_INVALID_PARAMETER); 673 } 674 return (SHELL_SUCCESS); 675 } 676 677 /** 678 Funciton to move a item to another location. 679 680 @param[in] Target The target item to move. 681 @param[in] CurrentOrder The pointer to the current order of items. 682 @param[in] OrderCount The number if items in CurrentOrder. 683 @param[in] OldLocation The current location of the Target. 684 @param[in] NewLocation The desired location of the Target. 685 686 @retval SHELL_SUCCESS The operation was successful. 687 @retval SHELL_INVALID_PARAMETER A parameter was invalid. 688 **/ 689 SHELL_STATUS 690 EFIAPI 691 BcfgMove( 692 IN CONST BCFG_OPERATION_TARGET Target, 693 IN CONST UINT16 *CurrentOrder, 694 IN CONST UINTN OrderCount, 695 IN CONST UINT16 OldLocation, 696 IN UINT16 NewLocation 697 ) 698 { 699 UINT16 *NewOrder; 700 EFI_STATUS Status; 701 UINT16 Temp; 702 703 NewOrder = AllocateCopyPool(OrderCount*sizeof(CurrentOrder[0]), CurrentOrder); 704 if (NewOrder == NULL) { 705 return (SHELL_OUT_OF_RESOURCES); 706 } 707 708 // 709 // correct the new location 710 // 711 if (NewLocation >= OrderCount) { 712 if (OrderCount > 0) { 713 NewLocation = (UINT16)OrderCount - 1; 714 } else { 715 NewLocation = 0; 716 } 717 } 718 719 Temp = CurrentOrder[OldLocation]; 720 CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0])); 721 CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0])); 722 NewOrder[NewLocation] = Temp; 723 724 Status = gRT->SetVariable( 725 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", 726 (EFI_GUID*)&gEfiGlobalVariableGuid, 727 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, 728 OrderCount*sizeof(CurrentOrder[0]), 729 NewOrder); 730 731 FreePool(NewOrder); 732 733 if (EFI_ERROR(Status)) { 734 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder"); 735 return (SHELL_INVALID_PARAMETER); 736 } 737 return (SHELL_SUCCESS); 738 } 739 740 /** 741 Function to add optional data to an option. 742 743 @param[in] OptData The optional data to add. 744 @param[in] CurrentOrder The pointer to the current order of items. 745 @param[in] OrderCount The number if items in CurrentOrder. 746 @param[in] Target The target of the operation. 747 748 @retval SHELL_SUCCESS The operation was succesful. 749 **/ 750 SHELL_STATUS 751 EFIAPI 752 BcfgAddOpt( 753 IN CONST CHAR16 *OptData, 754 IN CONST UINT16 *CurrentOrder, 755 IN CONST UINTN OrderCount, 756 IN CONST BCFG_OPERATION_TARGET Target 757 ) 758 { 759 EFI_KEY_OPTION NewKeyOption; 760 EFI_KEY_OPTION *KeyOptionBuffer; 761 SHELL_STATUS ShellStatus; 762 EFI_STATUS Status; 763 UINT16 OptionIndex; 764 UINT16 LoopCounter; 765 UINT64 Intermediate; 766 CONST CHAR16 *Temp; 767 CONST CHAR16 *Walker; 768 CHAR16 *FileName; 769 CHAR16 *Temp2; 770 CHAR16 *Data; 771 UINT32 KeyIndex; 772 CHAR16 VariableName[12]; 773 VOID *VariableData; 774 775 SHELL_FILE_HANDLE FileHandle; 776 777 Status = EFI_SUCCESS; 778 ShellStatus = SHELL_SUCCESS; 779 Walker = OptData; 780 FileName = NULL; 781 Data = NULL; 782 KeyOptionBuffer = NULL; 783 VariableData = NULL; 784 785 ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION)); 786 ZeroMem(VariableName, sizeof(VariableName)); 787 788 while(Walker[0] == L' ') { 789 Walker++; 790 } 791 792 // 793 // Get the index of the variable we are changing. 794 // 795 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE); 796 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) { 797 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index"); 798 ShellStatus = SHELL_INVALID_PARAMETER; 799 return (ShellStatus); 800 } 801 OptionIndex = (UINT16)Intermediate; 802 803 Temp = StrStr(Walker, L" "); 804 if (Temp != NULL) { 805 Walker = Temp; 806 } 807 while(Walker[0] == L' ') { 808 Walker++; 809 } 810 811 // 812 // determine whether we have file with data, quote delimited information, or a hot-key 813 // 814 if (Walker[0] == L'\"') { 815 // 816 // quoted filename or quoted information. 817 // 818 Temp = StrStr(Walker+1, L"\""); 819 if (Temp == NULL || StrLen(Temp) != 1) { 820 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); 821 ShellStatus = SHELL_INVALID_PARAMETER; 822 } else { 823 FileName = StrnCatGrow(&FileName, NULL, Walker+1, 0); 824 if (FileName == NULL) { 825 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle, L"bcfg"); 826 ShellStatus = SHELL_OUT_OF_RESOURCES; 827 return (ShellStatus); 828 } 829 Temp2 = StrStr(FileName, L"\""); 830 ASSERT(Temp2 != NULL); 831 Temp2[0] = CHAR_NULL; 832 Temp2++; 833 if (StrLen(Temp2)>0) { 834 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); 835 ShellStatus = SHELL_INVALID_PARAMETER; 836 } 837 if (EFI_ERROR(ShellFileExists(Walker))) { 838 // 839 // Not a file. must be misc information. 840 // 841 Data = FileName; 842 FileName = NULL; 843 } else { 844 FileName = StrnCatGrow(&FileName, NULL, Walker, 0); 845 } 846 } 847 } else { 848 // 849 // filename or hot key information. 850 // 851 if (StrStr(Walker, L" ") == NULL) { 852 // 853 // filename 854 // 855 if (EFI_ERROR(ShellFileExists(Walker))) { 856 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, L"bcfg", Walker); 857 ShellStatus = SHELL_INVALID_PARAMETER; 858 } else { 859 FileName = StrnCatGrow(&FileName, NULL, Walker, 0); 860 } 861 } else { 862 if (Target != BcfgTargetBootOrder) { 863 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle, L"bcfg"); 864 ShellStatus = SHELL_INVALID_PARAMETER; 865 } 866 867 if (ShellStatus == SHELL_SUCCESS) { 868 // 869 // Get hot key information 870 // 871 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE); 872 if (EFI_ERROR(Status) || (((UINT32)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) { 873 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); 874 ShellStatus = SHELL_INVALID_PARAMETER; 875 } 876 NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate; 877 Temp = StrStr(Walker, L" "); 878 if (Temp != NULL) { 879 Walker = Temp; 880 } 881 while(Walker[0] == L' ') { 882 Walker++; 883 } 884 } 885 886 if (ShellStatus == SHELL_SUCCESS) { 887 // 888 // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct. 889 // Re-allocate with the added information. 890 // 891 KeyOptionBuffer = AllocateCopyPool(sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount), &NewKeyOption); 892 if (KeyOptionBuffer == NULL) { 893 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg"); 894 ShellStatus = SHELL_OUT_OF_RESOURCES; 895 } 896 } 897 for (LoopCounter = 0 ; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) { 898 // 899 // ScanCode 900 // 901 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE); 902 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) { 903 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); 904 ShellStatus = SHELL_INVALID_PARAMETER; 905 } 906 ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate; 907 Temp = StrStr(Walker, L" "); 908 if (Temp != NULL) { 909 Walker = Temp; 910 } 911 while(Walker[0] == L' ') { 912 Walker++; 913 } 914 915 // 916 // UnicodeChar 917 // 918 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE); 919 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate)) { 920 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); 921 ShellStatus = SHELL_INVALID_PARAMETER; 922 } 923 ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate; 924 Temp = StrStr(Walker, L" "); 925 if (Temp != NULL) { 926 Walker = Temp; 927 } 928 while(Walker[0] == L' ') { 929 Walker++; 930 } 931 } 932 933 if (ShellStatus == SHELL_SUCCESS) { 934 // 935 // Now do the BootOption / BootOptionCrc 936 // 937 ASSERT (OptionIndex <= OrderCount); 938 KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex]; 939 Status = GetBootOptionCrc(&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption); 940 if (EFI_ERROR(Status)) { 941 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index"); 942 ShellStatus = SHELL_INVALID_PARAMETER; 943 } 944 } 945 946 if (ShellStatus == SHELL_SUCCESS) { 947 for (Temp2 = NULL, KeyIndex = 0 ; KeyIndex <= 0xFFFF ; KeyIndex++) { 948 UnicodeSPrint(VariableName, sizeof(VariableName), L"Key%04x", KeyIndex); 949 Status = GetEfiGlobalVariable2 (VariableName, &VariableData, NULL); 950 if (Status == EFI_NOT_FOUND) { 951 break; 952 } 953 if (!EFI_ERROR(Status)) { 954 SHELL_FREE_NON_NULL(VariableData); 955 } 956 } 957 if (KeyIndex <= 0xFFFF) { 958 Status = gRT->SetVariable( 959 VariableName, 960 (EFI_GUID*)&gEfiGlobalVariableGuid, 961 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, 962 sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount), 963 KeyOptionBuffer); 964 if (EFI_ERROR(Status)) { 965 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); 966 ShellStatus = SHELL_INVALID_PARAMETER; 967 } 968 } else { 969 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_VAR_NO_NUM), gShellBcfgHiiHandle, L"bcfg"); 970 ShellStatus = SHELL_INVALID_PARAMETER; 971 } 972 ASSERT(FileName == NULL && Data == NULL); 973 } 974 } 975 } 976 977 // 978 // Shouldn't be possible to have have both. Neither is ok though. 979 // 980 ASSERT(FileName == NULL || Data == NULL); 981 982 if (ShellStatus == SHELL_SUCCESS && (FileName != NULL || Data != NULL)) { 983 if (FileName != NULL) { 984 // 985 // Open the file and populate the data buffer. 986 // 987 Status = ShellOpenFileByName( 988 FileName, 989 &FileHandle, 990 EFI_FILE_MODE_READ, 991 0); 992 if (!EFI_ERROR(Status)) { 993 Status = ShellGetFileSize(FileHandle, &Intermediate); 994 } 995 Data = AllocateZeroPool((UINTN)Intermediate); 996 if (Data == NULL) { 997 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg"); 998 ShellStatus = SHELL_OUT_OF_RESOURCES; 999 } 1000 if (!EFI_ERROR(Status)) { 1001 Status = ShellReadFile(FileHandle, (UINTN *)&Intermediate, Data); 1002 } 1003 } else { 1004 Intermediate = StrSize(Data); 1005 } 1006 1007 if (!EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS && Data != NULL) { 1008 Status = UpdateOptionalData(CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8*)Data, Target); 1009 if (EFI_ERROR(Status)) { 1010 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); 1011 ShellStatus = SHELL_INVALID_PARAMETER; 1012 } 1013 } 1014 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) { 1015 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); 1016 ShellStatus = SHELL_INVALID_PARAMETER; 1017 } 1018 } 1019 1020 SHELL_FREE_NON_NULL(Data); 1021 SHELL_FREE_NON_NULL(KeyOptionBuffer); 1022 SHELL_FREE_NON_NULL(FileName); 1023 return ShellStatus; 1024 } 1025 1026 /** 1027 Function to dump the Bcfg information. 1028 1029 @param[in] Op The operation. 1030 @param[in] OrderCount How many to dump. 1031 @param[in] CurrentOrder The pointer to the current order of items. 1032 @param[in] VerboseOutput TRUE for extra output. FALSE otherwise. 1033 1034 @retval SHELL_SUCCESS The dump was successful. 1035 @retval SHELL_INVALID_PARAMETER A parameter was invalid. 1036 **/ 1037 SHELL_STATUS 1038 EFIAPI 1039 BcfgDisplayDump( 1040 IN CONST CHAR16 *Op, 1041 IN CONST UINTN OrderCount, 1042 IN CONST UINT16 *CurrentOrder, 1043 IN CONST BOOLEAN VerboseOutput 1044 ) 1045 { 1046 EFI_STATUS Status; 1047 UINT8 *Buffer; 1048 UINTN BufferSize; 1049 CHAR16 VariableName[12]; 1050 UINTN LoopVar; 1051 UINTN LoopVar2; 1052 CHAR16 *DevPathString; 1053 VOID *DevPath; 1054 1055 if (OrderCount == 0) { 1056 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellBcfgHiiHandle, L"bcfg"); 1057 return (SHELL_SUCCESS); 1058 } 1059 1060 for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) { 1061 Buffer = NULL; 1062 BufferSize = 0; 1063 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]); 1064 1065 Status = gRT->GetVariable( 1066 VariableName, 1067 (EFI_GUID*)&gEfiGlobalVariableGuid, 1068 NULL, 1069 &BufferSize, 1070 Buffer); 1071 if (Status == EFI_BUFFER_TOO_SMALL) { 1072 Buffer = AllocateZeroPool(BufferSize); 1073 Status = gRT->GetVariable( 1074 VariableName, 1075 (EFI_GUID*)&gEfiGlobalVariableGuid, 1076 NULL, 1077 &BufferSize, 1078 Buffer); 1079 } 1080 1081 if (EFI_ERROR(Status) || Buffer == NULL) { 1082 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); 1083 return (SHELL_INVALID_PARAMETER); 1084 } 1085 1086 if ((*(UINT16*)(Buffer+4)) != 0) { 1087 DevPath = AllocateZeroPool(*(UINT16*)(Buffer+4)); 1088 if (DevPath == NULL) { 1089 DevPathString = NULL; 1090 } else { 1091 CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4)); 1092 DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE); 1093 } 1094 } else { 1095 DevPath = NULL; 1096 DevPathString = NULL; 1097 } 1098 ShellPrintHiiEx( 1099 -1, 1100 -1, 1101 NULL, 1102 STRING_TOKEN(STR_BCFG_LOAD_OPTIONS), 1103 gShellBcfgHiiHandle, 1104 LoopVar, 1105 VariableName, 1106 (CHAR16*)(Buffer+6), 1107 DevPathString, 1108 (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y'); 1109 if (VerboseOutput) { 1110 for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2<BufferSize;LoopVar2++){ 1111 ShellPrintEx( 1112 -1, 1113 -1, 1114 NULL, 1115 L"%02x", 1116 Buffer[LoopVar2]); 1117 } 1118 ShellPrintEx( 1119 -1, 1120 -1, 1121 NULL, 1122 L"\r\n"); 1123 } 1124 1125 if (Buffer != NULL) { 1126 FreePool(Buffer); 1127 } 1128 if (DevPath != NULL) { 1129 FreePool(DevPath); 1130 } 1131 if (DevPathString != NULL) { 1132 FreePool(DevPathString); 1133 } 1134 } 1135 return (SHELL_SUCCESS); 1136 } 1137 1138 /** 1139 Function to initialize the BCFG operation structure. 1140 1141 @param[in] Struct The stuct to initialize. 1142 **/ 1143 VOID 1144 EFIAPI 1145 InitBcfgStruct( 1146 IN BGFG_OPERATION *Struct 1147 ) 1148 { 1149 ASSERT(Struct != NULL); 1150 Struct->Target = BcfgTargetMax; 1151 Struct->Type = BcfgTypeMax; 1152 Struct->Number1 = 0; 1153 Struct->Number2 = 0; 1154 Struct->HandleIndex = 0; 1155 Struct->FileName = NULL; 1156 Struct->Description = NULL; 1157 Struct->Order = NULL; 1158 Struct->OptData = NULL; 1159 } 1160 1161 1162 STATIC CONST SHELL_PARAM_ITEM ParamList[] = { 1163 {L"-v", TypeFlag}, 1164 {L"-opt", TypeMaxValue}, 1165 {NULL, TypeMax} 1166 }; 1167 1168 /** 1169 Function for 'bcfg' command. 1170 1171 @param[in] ImageHandle Handle to the Image (NULL if Internal). 1172 @param[in] SystemTable Pointer to the System Table (NULL if Internal). 1173 **/ 1174 SHELL_STATUS 1175 EFIAPI 1176 ShellCommandRunBcfg ( 1177 IN EFI_HANDLE ImageHandle, 1178 IN EFI_SYSTEM_TABLE *SystemTable 1179 ) 1180 { 1181 EFI_STATUS Status; 1182 LIST_ENTRY *Package; 1183 CHAR16 *ProblemParam; 1184 SHELL_STATUS ShellStatus; 1185 UINTN ParamNumber; 1186 CONST CHAR16 *CurrentParam; 1187 BGFG_OPERATION CurrentOperation; 1188 UINTN Length; 1189 UINT64 Intermediate; 1190 UINT16 Count; 1191 1192 Length = 0; 1193 ProblemParam = NULL; 1194 Package = NULL; 1195 ShellStatus = SHELL_SUCCESS; 1196 1197 InitBcfgStruct(&CurrentOperation); 1198 1199 // 1200 // initialize the shell lib (we must be in non-auto-init...) 1201 // 1202 Status = ShellInitialize(); 1203 ASSERT_EFI_ERROR(Status); 1204 1205 Status = CommandInit(); 1206 ASSERT_EFI_ERROR(Status); 1207 1208 // 1209 // parse the command line 1210 // 1211 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); 1212 if (EFI_ERROR(Status)) { 1213 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { 1214 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"bcfg", ProblemParam); 1215 FreePool(ProblemParam); 1216 ShellStatus = SHELL_INVALID_PARAMETER; 1217 } else { 1218 ASSERT(FALSE); 1219 } 1220 } else { 1221 // 1222 // Read in if we are doing -OPT 1223 // 1224 if (ShellCommandLineGetFlag(Package, L"-opt")) { 1225 CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt"); 1226 if (CurrentOperation.OptData == NULL) { 1227 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellBcfgHiiHandle, L"bcfg", L"-opt"); 1228 ShellStatus = SHELL_INVALID_PARAMETER; 1229 } 1230 CurrentOperation.Type = BcfgTypeOpt; 1231 } 1232 1233 // 1234 // small block to read the target of the operation 1235 // 1236 if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) || 1237 (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt) 1238 ){ 1239 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); 1240 ShellStatus = SHELL_INVALID_PARAMETER; 1241 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) { 1242 CurrentOperation.Target = BcfgTargetDriverOrder; 1243 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) { 1244 CurrentOperation.Target = BcfgTargetBootOrder; 1245 } else { 1246 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle, L"bcfg"); 1247 ShellStatus = SHELL_INVALID_PARAMETER; 1248 } 1249 1250 1251 // 1252 // Read in the boot or driver order environment variable (not needed for opt) 1253 // 1254 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) { 1255 Length = 0; 1256 Status = gRT->GetVariable( 1257 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", 1258 (EFI_GUID*)&gEfiGlobalVariableGuid, 1259 NULL, 1260 &Length, 1261 CurrentOperation.Order); 1262 if (Status == EFI_BUFFER_TOO_SMALL) { 1263 CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0]))); 1264 if (CurrentOperation.Order == NULL) { 1265 ShellStatus = SHELL_OUT_OF_RESOURCES; 1266 } else { 1267 Status = gRT->GetVariable( 1268 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", 1269 (EFI_GUID*)&gEfiGlobalVariableGuid, 1270 NULL, 1271 &Length, 1272 CurrentOperation.Order); 1273 } 1274 } 1275 } 1276 1277 Count = (UINT16) (Length / sizeof(CurrentOperation.Order[0])); 1278 1279 // 1280 // large block to read the type of operation and verify parameter types for the info. 1281 // 1282 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) { 1283 for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) { 1284 CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber); 1285 if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) { 1286 CurrentOperation.Type = BcfgTypeDump; 1287 } else if (ShellCommandLineGetFlag(Package, L"-v")) { 1288 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"-v (without dump)"); 1289 ShellStatus = SHELL_INVALID_PARAMETER; 1290 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) { 1291 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { 1292 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); 1293 ShellStatus = SHELL_INVALID_PARAMETER; 1294 } 1295 CurrentOperation.Type = BcfgTypeAdd; 1296 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); 1297 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { 1298 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); 1299 ShellStatus = SHELL_INVALID_PARAMETER; 1300 } else { 1301 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); 1302 CurrentOperation.Number1 = (UINT16)Intermediate; 1303 ASSERT(CurrentOperation.FileName == NULL); 1304 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); 1305 ASSERT(CurrentOperation.Description == NULL); 1306 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); 1307 } 1308 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) { 1309 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { 1310 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); 1311 ShellStatus = SHELL_INVALID_PARAMETER; 1312 } 1313 CurrentOperation.Type = BcfgTypeAddp; 1314 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); 1315 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { 1316 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); 1317 ShellStatus = SHELL_INVALID_PARAMETER; 1318 } else { 1319 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); 1320 CurrentOperation.Number1 = (UINT16)Intermediate; 1321 ASSERT(CurrentOperation.FileName == NULL); 1322 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); 1323 ASSERT(CurrentOperation.Description == NULL); 1324 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); 1325 } 1326 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) { 1327 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { 1328 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); 1329 ShellStatus = SHELL_INVALID_PARAMETER; 1330 } 1331 CurrentOperation.Type = BcfgTypeAddh; 1332 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); 1333 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { 1334 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); 1335 ShellStatus = SHELL_INVALID_PARAMETER; 1336 } else { 1337 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); 1338 CurrentOperation.Number1 = (UINT16)Intermediate; 1339 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); 1340 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { 1341 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); 1342 ShellStatus = SHELL_INVALID_PARAMETER; 1343 } else { 1344 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); 1345 CurrentOperation.HandleIndex = (UINT16)Intermediate; 1346 ASSERT(CurrentOperation.Description == NULL); 1347 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); 1348 } 1349 } 1350 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) { 1351 if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) { 1352 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); 1353 ShellStatus = SHELL_INVALID_PARAMETER; 1354 } 1355 CurrentOperation.Type = BcfgTypeRm; 1356 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); 1357 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { 1358 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); 1359 ShellStatus = SHELL_INVALID_PARAMETER; 1360 } else { 1361 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); 1362 CurrentOperation.Number1 = (UINT16)Intermediate; 1363 if (CurrentOperation.Number1 >= Count){ 1364 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); 1365 ShellStatus = SHELL_INVALID_PARAMETER; 1366 } 1367 } 1368 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) { 1369 if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) { 1370 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); 1371 ShellStatus = SHELL_INVALID_PARAMETER; 1372 } 1373 CurrentOperation.Type = BcfgTypeMv; 1374 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); 1375 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { 1376 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); 1377 ShellStatus = SHELL_INVALID_PARAMETER; 1378 } else { 1379 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); 1380 CurrentOperation.Number1 = (UINT16)Intermediate; 1381 if (CurrentOperation.Number1 >= Count){ 1382 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); 1383 ShellStatus = SHELL_INVALID_PARAMETER; 1384 } else { 1385 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); 1386 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { 1387 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); 1388 ShellStatus = SHELL_INVALID_PARAMETER; 1389 } else { 1390 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); 1391 CurrentOperation.Number2 = (UINT16)Intermediate; 1392 } 1393 if (CurrentOperation.Number2 == CurrentOperation.Number1 1394 ||CurrentOperation.Number2 >= Count 1395 ){ 1396 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); 1397 ShellStatus = SHELL_INVALID_PARAMETER; 1398 } 1399 } 1400 } 1401 } else { 1402 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); 1403 ShellStatus = SHELL_INVALID_PARAMETER; 1404 } 1405 } 1406 } 1407 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) { 1408 // 1409 // we have all the info. Do the work 1410 // 1411 switch (CurrentOperation.Type) { 1412 case BcfgTypeDump: 1413 ShellStatus = BcfgDisplayDump( 1414 CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver", 1415 Count, 1416 CurrentOperation.Order, 1417 ShellCommandLineGetFlag(Package, L"-v")); 1418 break; 1419 case BcfgTypeMv: 1420 ShellStatus = BcfgMove( 1421 CurrentOperation.Target, 1422 CurrentOperation.Order, 1423 Count, 1424 CurrentOperation.Number1, 1425 CurrentOperation.Number2); 1426 break; 1427 case BcfgTypeRm: 1428 ShellStatus = BcfgRemove( 1429 CurrentOperation.Target, 1430 CurrentOperation.Order, 1431 Count, 1432 CurrentOperation.Number1); 1433 break; 1434 case BcfgTypeAdd: 1435 case BcfgTypeAddp: 1436 case BcfgTypeAddh: 1437 ShellStatus = BcfgAdd( 1438 CurrentOperation.Number1, 1439 CurrentOperation.FileName, 1440 CurrentOperation.Description==NULL?L"":CurrentOperation.Description, 1441 CurrentOperation.Order, 1442 Count, 1443 CurrentOperation.Target, 1444 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh), 1445 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp), 1446 CurrentOperation.HandleIndex); 1447 break; 1448 case BcfgTypeOpt: 1449 ShellStatus = BcfgAddOpt( 1450 CurrentOperation.OptData, 1451 CurrentOperation.Order, 1452 Count, 1453 CurrentOperation.Target); 1454 break; 1455 default: 1456 ASSERT(FALSE); 1457 } 1458 } 1459 } 1460 1461 if (Package != NULL) { 1462 ShellCommandLineFreeVarList (Package); 1463 } 1464 if (CurrentOperation.FileName != NULL) { 1465 FreePool(CurrentOperation.FileName); 1466 } 1467 if (CurrentOperation.Description != NULL) { 1468 FreePool(CurrentOperation.Description); 1469 } 1470 if (CurrentOperation.Order != NULL) { 1471 FreePool(CurrentOperation.Order); 1472 } 1473 1474 return (ShellStatus); 1475 } 1476 1477 1478 /** 1479 Function to get the filename with help context if HII will not be used. 1480 1481 @return The filename with help text in it. 1482 **/ 1483 CONST CHAR16* 1484 EFIAPI 1485 ShellCommandGetManFileNameBcfg ( 1486 VOID 1487 ) 1488 { 1489 return (mFileName); 1490 } 1491 1492 /** 1493 "Constructor" for the library. 1494 1495 This will register the handler for the bcfg command. 1496 1497 @param[in] ImageHandle the image handle of the process 1498 @param[in] SystemTable the EFI System Table pointer 1499 @param[in] Name the profile name to use 1500 1501 @retval EFI_SUCCESS the shell command handlers were installed sucessfully 1502 @retval EFI_UNSUPPORTED the shell level required was not found. 1503 **/ 1504 EFI_STATUS 1505 EFIAPI 1506 BcfgLibraryRegisterBcfgCommand ( 1507 IN EFI_HANDLE ImageHandle, 1508 IN EFI_SYSTEM_TABLE *SystemTable, 1509 IN CONST CHAR16 *Name 1510 ) 1511 { 1512 if (gShellBcfgHiiHandle != NULL) { 1513 return (EFI_SUCCESS); 1514 } 1515 1516 gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL); 1517 if (gShellBcfgHiiHandle == NULL) { 1518 return (EFI_DEVICE_ERROR); 1519 } 1520 1521 // 1522 // install our shell command handler 1523 // 1524 ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfg , ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG)); 1525 1526 return (EFI_SUCCESS); 1527 } 1528 1529 /** 1530 Destructor for the library. free any resources. 1531 1532 @param ImageHandle The image handle of the process. 1533 @param SystemTable The EFI System Table pointer. 1534 **/ 1535 EFI_STATUS 1536 EFIAPI 1537 BcfgLibraryUnregisterBcfgCommand ( 1538 IN EFI_HANDLE ImageHandle, 1539 IN EFI_SYSTEM_TABLE *SystemTable 1540 ) 1541 { 1542 if (gShellBcfgHiiHandle != NULL) { 1543 HiiRemovePackages(gShellBcfgHiiHandle); 1544 } 1545 gShellBcfgHiiHandle = NULL; 1546 return (EFI_SUCCESS); 1547 } 1548 1549