From 75aadf59c3ca398fa7f8fc0db8b45b507da5ae8e Mon Sep 17 00:00:00 2001 From: jcarsey Date: Tue, 16 Nov 2010 22:32:21 +0000 Subject: [PATCH] adding "Install1" profile. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11067 6f19259b-4bc3-4df7-8a09-765794883524 --- .../UefiShellInstall1CommandsLib/Bcfg.c | 813 ++++++++++++++++++ .../UefiShellInstall1CommandsLib.c | 85 ++ .../UefiShellInstall1CommandsLib.h | 54 ++ .../UefiShellInstall1CommandsLib.inf | 51 ++ .../UefiShellInstall1CommandsLib.uni | Bin 0 -> 14570 bytes 5 files changed, 1003 insertions(+) create mode 100644 ShellPkg/Library/UefiShellInstall1CommandsLib/Bcfg.c create mode 100644 ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c create mode 100644 ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.h create mode 100644 ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf create mode 100644 ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.uni diff --git a/ShellPkg/Library/UefiShellInstall1CommandsLib/Bcfg.c b/ShellPkg/Library/UefiShellInstall1CommandsLib/Bcfg.c new file mode 100644 index 0000000000..17c099d533 --- /dev/null +++ b/ShellPkg/Library/UefiShellInstall1CommandsLib/Bcfg.c @@ -0,0 +1,813 @@ +/** @file + Main file for bcfg shell install1 function. + + Copyright (c) 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellInstall1CommandsLib.h" +#include +#include +#include +#include + +typedef enum { + BCFG_TARGET_BOOT_ORDER = 0, + BCFG_TARGET_DRIVER_ORDER = 1, + BCFG_TARGET_MAX = 2 +} BCFG_OPERATION_TARGET; + +typedef enum { + BCFG_TYPE_DUMP = 0, + BCFG_TYPE_ADD = 1, + BCFG_TYPE_ADDP = 2, + BCFG_TYPE_ADDH = 3, + BCFG_TYPE_RM = 4, + BCFG_TYPE_MV = 5, + BCFG_TYPE_OPT = 6, + BCFG_TYPE_MAX = 7 +} BCFG_OPERATION_TYPE; + +typedef struct { + BCFG_OPERATION_TARGET Target; + BCFG_OPERATION_TYPE Type; + UINT16 Number1; + UINT16 Number2; + UINTN HandleIndex; + CHAR16 *FileName; + CHAR16 *Description; + UINT16 *Order; + CONST CHAR16 *OptData; +} BGFG_OPERATION; + +/** + Function to update the optional data associated with an option. + + @param[in] Target The type being modified. BOOT or DRIVER + @param[in] OptData The pointer to the data to modify with. + + @retval SHELL_SUCCESS The optional data was updated sucessfully. +**/ +SHELL_STATUS +EFIAPI +BcfgAddOptInstall( + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST CHAR16 *OptData + ) +{ + ShellPrintEx(-1, -1, L"use of -opt is not currently supported."); + return (SHELL_UNSUPPORTED); +} + +/** + Function to add an option. + + @param[in] Position The position to add this in at. + @param[in] File The file to add as the option. + @param[in] Desc The description. + @param[in] CurrentOrder The current order of that type. + @param[in] OrderCount The number of items in the current order. + @param[in] Target The type being modified. BOOT or DRIVER + @param[in] UseHandle Add something by a handle. Uses HandleNumber if TRUE and File if FALSE. + @param[in] UsePath Add something by local path. Only used of UseHandle is FALSE. + @param[in] HandleNumber The HandleIndex to use. + + @retval SHELL_SUCCESS The option was added sucessfully. +**/ +SHELL_STATUS +EFIAPI +BcfgAddInstall ( + IN UINTN Position, + IN CONST CHAR16 *File, + IN CONST CHAR16 *Desc, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST BOOLEAN UseHandle, + IN CONST BOOLEAN UseFullPath, + IN CONST UINTN HandleNumber + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath, *FilePath, *FileNode; + CHAR16 *Str; + CONST CHAR16 *p; + UINT8 *p8; + UINT8 *p8Copy; + EFI_SHELL_FILE_INFO *Arg; + EFI_SHELL_FILE_INFO *FileList; + CHAR16 OptionStr[40]; + UINTN DescSize, FilePathSize; + BOOLEAN Found; + UINTN TargetLocation; + UINTN Index; + EFI_HANDLE *Handles; + EFI_HANDLE CurHandle; + SHELL_STATUS ShellStatus; + UINT16 *NewOrder; + EFI_LOADED_IMAGE_PROTOCOL *Image; + + if (!UseHandle) { + ASSERT(File != NULL); + ASSERT(Desc != NULL); + } else { + ASSERT(HandleNumber != 0); + } + + Str = NULL; + FilePath = NULL; + FileNode = NULL; + FileList = NULL; + Handles = NULL; + ShellStatus = SHELL_SUCCESS; + TargetLocation = 0xFFFF; + + if (UseHandle) { + CurHandle = ConvertHandleIndexToHandle(HandleNumber); + if (CurHandle == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, L""); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + FilePath = NULL; + Status = gBS->HandleProtocol (CurHandle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID**)&FilePath); + if (EFI_ERROR (Status)) { + Status = EFI_SUCCESS; + // + // Try to construct the DevicePath + // + Status = gBS->OpenProtocol(CurHandle, &gEfiLoadedImageProtocolGuid, (VOID**)&Image, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellInstall1HiiHandle, HandleNumber); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = gBS->HandleProtocol (Image->DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID**)&DevicePath); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellInstall1HiiHandle, HandleNumber); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + FilePath = AppendDevicePath(DevicePath, Image->FilePath); + } + } + } + } + } else { + // + // Get file info + // + Status = ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellInstall1HiiHandle, File); + ShellStatus = SHELL_NOT_FOUND; + } else if (FileList == NULL || FileList->Link.ForwardLink != FileList->Link.BackLink) { + // + // If filename expanded to multiple names, fail + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellInstall1HiiHandle, File); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link); + if (EFI_ERROR(Arg->Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellInstall1HiiHandle, File, Arg->Status); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Build FilePath to the filename + // + + // + // get the device path + // + DevicePath = mEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName); + if (DevicePath == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellInstall1HiiHandle, Arg->FullName); + ShellStatus = SHELL_UNSUPPORTED; + } else { + if (UseFullPath) { + FilePath = DuplicateDevicePath(DevicePath); + } else { + for(p=Arg->FullName; *p != CHAR_NULL && *p != ':'; p++); + FilePath = FileDevicePath(NULL, p+1); + } + + FreePool(DevicePath); + } + } + } + } + + + if (ShellStatus == SHELL_SUCCESS) { + // + // Find a free target ,a brute force implementation + // + Found = FALSE; + for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) { + Found = TRUE; + for (Index=0; Index < OrderCount; Index++) { + if (CurrentOrder[Index] == TargetLocation) { + Found = FALSE; + break; + } + } + + if (Found) { + break; + } + } + + if (TargetLocation == 0xFFFF) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellInstall1HiiHandle); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellInstall1HiiHandle, TargetLocation); + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Add the option + // + DescSize = StrSize(Desc); + FilePathSize = GetDevicePathSize (FilePath); + + p8 = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize); + if (p8 != NULL) { + p8Copy = p8; + *((UINT32 *) p8) = LOAD_OPTION_ACTIVE; // Attributes + p8 += sizeof (UINT32); + + *((UINT16 *) p8) = (UINT16)FilePathSize; // FilePathListLength + p8 += sizeof (UINT16); + + CopyMem (p8, Desc, DescSize); + p8 += DescSize; + CopyMem (p8, FilePath, FilePathSize); + + UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BCFG_TARGET_BOOT_ORDER?L"Boot":L"Driver", TargetLocation); + Status = gRT->SetVariable ( + OptionStr, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize, + p8Copy + ); + + FreePool(p8Copy); + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellInstall1HiiHandle, OptionStr, Status); + } else { + NewOrder = AllocateZeroPool((OrderCount+1)*sizeof(UINT16)); + ASSERT(NewOrder != NULL); + CopyMem(NewOrder, CurrentOrder, (OrderCount)*sizeof(UINT16)); + + // + // Insert target into order list + // + for (Index=OrderCount; Index > Position; Index--) { + NewOrder[Index] = NewOrder[Index-1]; + } + + NewOrder[Index] = (UINT16)TargetLocation; + Status = gRT->SetVariable ( + Target == BCFG_TARGET_BOOT_ORDER?L"BootOrder":L"DriverOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + (OrderCount+1) * sizeof(UINT16), + NewOrder + ); + + FreePool(NewOrder); + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellInstall1HiiHandle, Target == BCFG_TARGET_BOOT_ORDER?L"BootOrder":L"DriverOrder", Status); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellPrintEx (-1, -1, L"bcfg: Add %s as %x\n", OptionStr, Index); + } + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellInstall1HiiHandle); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } + } + +// +//If always Free FilePath, will free devicepath in system when use "addh" +// + + if (FilePath!=NULL && !UseHandle) { + FreePool (FilePath); + } + + if (Str != NULL) { + FreePool(Str); + } + + if (Handles != NULL) { + FreePool (Handles); + } + + if (FileList != NULL) { + ShellCloseFileMetaArg (&FileList); + } + + return (ShellStatus); +} + +SHELL_STATUS +EFIAPI +BcfgRemoveInstall( + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST UINT16 Location + ) +{ + CHAR16 VariableName[12]; + UINT16 *NewOrder; + EFI_STATUS Status; + + NewOrder = AllocatePool(OrderCount*sizeof(CurrentOrder[0])); + if (NewOrder == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0])); + CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0])); + + Status = gRT->SetVariable( + Target == BCFG_TARGET_BOOT_ORDER?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", + (EFI_GUID*)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + (OrderCount-1)*sizeof(CurrentOrder[0]), // drop 1 off since the list is 1 shorter + NewOrder); + + FreePool(NewOrder); + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellInstall1HiiHandle, Target == BCFG_TARGET_BOOT_ORDER?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status); + return (SHELL_INVALID_PARAMETER); + } + + UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BCFG_TARGET_BOOT_ORDER?L"Boot":L"Driver", CurrentOrder[Location]); + Status = gRT->SetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + 0, + NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellInstall1HiiHandle, VariableName, Status); + return (SHELL_INVALID_PARAMETER); + } + + return (SHELL_SUCCESS); +} + +SHELL_STATUS +EFIAPI +BcfgMoveInstall( + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST UINT16 OldLocation, + IN CONST UINT16 NewLocation + ) +{ + UINT16 *NewOrder; + EFI_STATUS Status; + UINT16 Temp; + + NewOrder = AllocatePool(OrderCount*sizeof(CurrentOrder[0])); + ASSERT(NewOrder != NULL); + + Temp = CurrentOrder[OldLocation]; + CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0])); + CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0])); + if (NewLocation == OrderCount) { + NewOrder[OrderCount-1] = Temp; + } else { + CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0])); + NewOrder[NewLocation] = Temp; + } + + + Status = gRT->SetVariable( + Target == BCFG_TARGET_BOOT_ORDER?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", + (EFI_GUID*)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + OrderCount*sizeof(CurrentOrder[0]), + NewOrder); + + FreePool(NewOrder); + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellInstall1HiiHandle, Target == BCFG_TARGET_BOOT_ORDER?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status); + return (SHELL_INVALID_PARAMETER); + } + return (SHELL_SUCCESS); +} + +SHELL_STATUS +EFIAPI +BcfgDisplayDumpInstall( + IN CONST CHAR16 *Op, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST BOOLEAN VerboseOutput + ) +{ + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + CHAR16 VariableName[12]; + UINTN LoopVar; + UINTN LoopVar2; + CHAR16 *DevPathString; + VOID *DevPath; + + for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) { + Buffer = NULL; + BufferSize = 0; + UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]); + + Status = gRT->GetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = AllocatePool(BufferSize); + Status = gRT->GetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer); + } + + if (EFI_ERROR(Status) || Buffer == NULL) { + SHELL_FREE_NON_NULL(Buffer); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellInstall1HiiHandle, VariableName, Status); + return (SHELL_INVALID_PARAMETER); + } + + DevPath = AllocatePool(*(UINT16*)(Buffer+4)); + CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4)); + DevPathString = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, FALSE); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_BCFG_LOAD_OPTIONS), + gShellInstall1HiiHandle, + Op, + LoopVar, + (CHAR16*)(Buffer+6), + DevPathString, + (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y'); + if (VerboseOutput) { + for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2Target = BCFG_TARGET_MAX; + Struct->Type = BCFG_TYPE_MAX; + Struct->Number1 = 0; + Struct->Number2 = 0; + Struct->HandleIndex = 0; + Struct->FileName = NULL; + Struct->Description = NULL; + Struct->Order = NULL; + Struct->OptData = NULL; +} + + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-v", TypeFlag}, + {L"-opt", TypeMaxValue}, + {NULL, TypeMax} + }; + +/** + Function for 'bcfg' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunBcfgInstall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamNumber; + CONST CHAR16 *CurrentParam; + BGFG_OPERATION CurrentOperation; + UINTN Length; + + Length = 0; + ProblemParam = NULL; + Package = NULL; + ShellStatus = SHELL_SUCCESS; + + InitBcfgStructInstall(&CurrentOperation); + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // small block to read the target of the operation + // + if (ShellCommandLineGetFlag(Package, L"-opt") && ShellCommandLineGetCount(Package) < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (!ShellCommandLineGetFlag(Package, L"-opt") && ShellCommandLineGetCount(Package) < 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) { + CurrentOperation.Target = BCFG_TARGET_DRIVER_ORDER; + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) { + CurrentOperation.Target = BCFG_TARGET_BOOT_ORDER; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + // + // Read in if we are doing -OPT + // + if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BCFG_TARGET_MAX && ShellCommandLineGetFlag(Package, L"-opt")) { + CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt"); + CurrentOperation.Type = BCFG_TYPE_OPT; + } + + // + // Read in the boot or driver order environment variable (not needed for opt) + // + if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BCFG_TARGET_MAX && CurrentOperation.Type != BCFG_TYPE_OPT) { + Length = 0; + Status = gRT->GetVariable( + CurrentOperation.Target == BCFG_TARGET_BOOT_ORDER?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &Length, + CurrentOperation.Order); + if (Status == EFI_BUFFER_TOO_SMALL) { + CurrentOperation.Order = AllocatePool(Length+(4*sizeof(CurrentOperation.Order[0]))); + Status = gRT->GetVariable( + CurrentOperation.Target == BCFG_TARGET_BOOT_ORDER?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &Length, + CurrentOperation.Order); + } + } + + // + // large block to read the type of operation and verify parameter types for the info. + // + if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BCFG_TARGET_MAX) { + for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) { + CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber); + if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) { + if (ShellCommandLineGetCount(Package) > 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BCFG_TYPE_DUMP; + } else if (ShellCommandLineGetFlag(Package, L"-v")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, L"-v (without dump)"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BCFG_TYPE_ADD; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Number1 = (UINT16)StrHexToUintn(CurrentParam); + ASSERT(CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + ASSERT(CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + } + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BCFG_TYPE_ADDP; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Number1 = (UINT16)StrHexToUintn(CurrentParam); + ASSERT(CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + ASSERT(CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + } + } + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BCFG_TYPE_ADDH; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Number1 = (UINT16)StrHexToUintn(CurrentParam); + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.HandleIndex = (UINT16)StrHexToUintn(CurrentParam); + ASSERT(CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + } + } + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) { + if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BCFG_TYPE_RM; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Number1 = (UINT16)StrHexToUintn(CurrentParam); + if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_LOCATION_RANGE), gShellInstall1HiiHandle, Length / sizeof(CurrentOperation.Order[0])); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BCFG_TYPE_MV; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Number1 = (UINT16)StrHexToUintn(CurrentParam); + if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_LOCATION_RANGE), gShellInstall1HiiHandle, Length / sizeof(CurrentOperation.Order[0])); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Number2 = (UINT16)StrHexToUintn(CurrentParam); + } + if (CurrentOperation.Number2 == CurrentOperation.Number1 + ||CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0])) + ||CurrentOperation.Number2 > (Length / sizeof(CurrentOperation.Order[0])) + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_LOCATION_RANGE), gShellInstall1HiiHandle, Length / sizeof(CurrentOperation.Order[0])); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BCFG_TARGET_MAX && CurrentOperation.Type < BCFG_TYPE_MAX) { + // + // we have all the info. Do the work + // + switch (CurrentOperation.Type) { + case BCFG_TYPE_DUMP: + ShellStatus = BcfgDisplayDumpInstall( + CurrentOperation.Target == BCFG_TARGET_BOOT_ORDER?L"Boot":L"Driver", + CurrentOperation.Order, + Length / sizeof(CurrentOperation.Order[0]), + ShellCommandLineGetFlag(Package, L"-v")); + break; + case BCFG_TYPE_MV: + ShellStatus = BcfgMoveInstall( + CurrentOperation.Target, + CurrentOperation.Order, + Length / sizeof(CurrentOperation.Order[0]), + CurrentOperation.Number1, + CurrentOperation.Number2); + break; + case BCFG_TYPE_RM: + ShellStatus = BcfgRemoveInstall( + CurrentOperation.Target, + CurrentOperation.Order, + (Length / sizeof(CurrentOperation.Order[0])), + CurrentOperation.Number1); + break; + case BCFG_TYPE_ADD: + case BCFG_TYPE_ADDP: + case BCFG_TYPE_ADDH: + ShellStatus = BcfgAddInstall( + CurrentOperation.Number1, + CurrentOperation.FileName, + CurrentOperation.Description, + CurrentOperation.Order, + Length / sizeof(CurrentOperation.Order[0]), + CurrentOperation.Target, + (BOOLEAN)(CurrentOperation.Type == BCFG_TYPE_ADDH), + (BOOLEAN)(CurrentOperation.Type == BCFG_TYPE_ADD ), + CurrentOperation.HandleIndex); + break; + case BCFG_TYPE_OPT: + ShellStatus = BcfgAddOptInstall( + CurrentOperation.Target, + CurrentOperation.OptData); + break; + default: + ASSERT(FALSE); + } + } + } + + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + if (CurrentOperation.FileName != NULL) { + FreePool(CurrentOperation.FileName); + } + if (CurrentOperation.Description != NULL) { + FreePool(CurrentOperation.Description); + } + if (CurrentOperation.Order != NULL) { + FreePool(CurrentOperation.Order); + } + + return (ShellStatus); +} diff --git a/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c b/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c new file mode 100644 index 0000000000..e524e7f50a --- /dev/null +++ b/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c @@ -0,0 +1,85 @@ +/** @file + Main file for NULL named library for install1 shell command functions. + + Copyright (c) 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellInstall1CommandsLib.h" + +STATIC CONST CHAR16 mFileName[] = L"ShellCommands"; +EFI_HANDLE gShellInstall1HiiHandle = NULL; +CONST EFI_GUID gShellInstall1HiiGuid = \ + { \ + 0x7d574d54, 0xd364, 0x4d4a, { 0x95, 0xe3, 0x49, 0x45, 0xdb, 0x7a, 0xd3, 0xee } \ + }; + +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameInstall1 ( + VOID + ) +{ + return (mFileName); +} + +/** + Constructor for the Shell Level 1 Commands library. + + Install the handlers for level 1 UEFI Shell 2.0 commands. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellInstall1CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // check our bit of the profiles mask + // + if ((PcdGet8(PcdShellProfileMask) & BIT2) == 0) { + return (EFI_UNSUPPORTED); + } + + gShellInstall1HiiHandle = HiiAddPackages (&gShellInstall1HiiGuid, gImageHandle, UefiShellInstall1CommandsLibStrings, NULL); + if (gShellInstall1HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handlers that are always installed + // + ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfgInstall , ShellCommandGetManFileNameInstall1, 0, L"Install", FALSE, gShellInstall1HiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG)); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. +**/ +EFI_STATUS +EFIAPI +ShellInstall1CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellInstall1HiiHandle != NULL) { + HiiRemovePackages(gShellInstall1HiiHandle); + } + return (EFI_SUCCESS); +} diff --git a/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.h b/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.h new file mode 100644 index 0000000000..b831e4911f --- /dev/null +++ b/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.h @@ -0,0 +1,54 @@ +/** @file + Main file for NULL named library for install 1 shell command functions. + + Copyright (c) 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HANDLE gShellInstall1HiiHandle; +extern CONST EFI_GUID gShellInstall1HiiGuid; + +/** + Function for 'bcfg' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunBcfgInstall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + diff --git a/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf b/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf new file mode 100644 index 0000000000..5c7fb4eb03 --- /dev/null +++ b/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf @@ -0,0 +1,51 @@ +## @file +# Provides shell install1 functions +# +# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellInstall1CommandsLib + FILE_GUID = D250E364-51C6-49ed-AEBF-6D83F5130F74 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellInstall1CommandsLibConstructor + DESTRUCTOR = ShellInstall1CommandsLibDestructor + +[Sources.common] + UefiShellInstall1CommandsLib.c + UefiShellInstall1CommandsLib.h + UefiShellInstall1CommandsLib.uni + Bcfg.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + SortLib + PrintLib + +[Pcd] + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask # ALWAYS_CONSUMED + diff --git a/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.uni b/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.uni new file mode 100644 index 0000000000000000000000000000000000000000..9e8ae9531252c899ab86e250380b9e7e205024c9 GIT binary patch literal 14570 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 literal 0 HcmV?d00001 -- 2.39.2