You've already forked slimbootloader
mirror of
https://github.com/Dasharo/slimbootloader.git
synced 2026-03-06 15:26:20 -08:00
When changing a boot option from a non-RAW type to RAW, the boot command does not set the valid field of the LbaImage. Signed-off-by: Bejean Mosher <bejean.mosher@intel.com>
693 lines
22 KiB
C
693 lines
22 KiB
C
/** @file
|
|
Shell command `boot` to print or modify the OS boot option list.
|
|
|
|
Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Library/ShellLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/FileSystemLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/BootloaderCommonLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/BootOptionLib.h>
|
|
#include <Guid/OsBootOptionGuid.h>
|
|
#include "Shell.h"
|
|
|
|
/**
|
|
Print or modify the OS boot option list.
|
|
|
|
@param[in] Shell shell instance
|
|
@param[in] Argc number of command line arguments
|
|
@param[in] Argv command line arguments
|
|
|
|
@retval EFI_SUCCESS
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ShellCommandBootFunc (
|
|
IN SHELL *Shell,
|
|
IN UINTN Argc,
|
|
IN CHAR16 *Argv[]
|
|
);
|
|
|
|
CONST SHELL_COMMAND ShellCommandBoot = {
|
|
L"boot",
|
|
L"Print or modify the OS boot option list",
|
|
&ShellCommandBootFunc
|
|
};
|
|
|
|
|
|
/**
|
|
Swap two of the OS boot entries.
|
|
|
|
@param[in] Shell shell instance
|
|
@param[in, out] Buffer buffer for Shell user input
|
|
@param[in] BufferSize size of the Buffer in bytes
|
|
@param[out] BootOptionList update the OS boot option HOB
|
|
to swap the user specified boot entries
|
|
|
|
@retval EFI_SUCCESS
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SwapBootEntries (
|
|
IN SHELL *Shell,
|
|
IN OUT CHAR16 *Buffer,
|
|
IN UINTN BufferSize,
|
|
OUT OS_BOOT_OPTION_LIST *BootOptionList
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOLEAN IsHex;
|
|
UINT8 Index1;
|
|
UINT8 Index2;
|
|
OS_BOOT_OPTION BootOption;
|
|
|
|
if (BootOptionList->OsBootOptionCount < 2) {
|
|
ShellPrint (L"Only 1 index available, cannot perform swap\n");
|
|
return EFI_SUCCESS;
|
|
} else if (BootOptionList->OsBootOptionCount == 2) {
|
|
Index1 = 0;
|
|
Index2 = 1;
|
|
} else {
|
|
do {
|
|
ShellPrint (L"Enter first index to swap (0x0 to 0x%X)\n",
|
|
BootOptionList->OsBootOptionCount - 1
|
|
);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
Index1 = (UINT8) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
if (Index1 < BootOptionList->OsBootOptionCount && (StrLen (Buffer) > 0)) {
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid index '%s', please re-enter\n", Buffer);
|
|
} while (1);
|
|
|
|
do {
|
|
ShellPrint (L"Enter second index to swap (0x0 to 0x%X)\n",
|
|
BootOptionList->OsBootOptionCount - 1
|
|
);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
Index2 = (UINT8) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
if ((Index2 < BootOptionList->OsBootOptionCount) && (Index1 != Index2) && (StrLen (Buffer) > 0)) {
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid or duplicate index '%s', please re-enter\n", Buffer);
|
|
} while (1);
|
|
}
|
|
CopyMem (&BootOption, &BootOptionList->OsBootOption[Index1], sizeof (BootOption));
|
|
CopyMem (&BootOptionList->OsBootOption[Index1], &BootOptionList->OsBootOption[Index2], sizeof (BootOption));
|
|
CopyMem (&BootOptionList->OsBootOption[Index2], &BootOption, sizeof (BootOption));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get the OS boot entry's file info.
|
|
|
|
@param[in] Shell shell instance
|
|
@param[in, out] Buffer buffer for Shell user input
|
|
@param[in] BufferSize size of the Buffer in bytes
|
|
@param[out] BootOption update the boot entry with the device type,
|
|
address, and partition info
|
|
@param[in] CurrOption the current boot entry value
|
|
|
|
@retval EFI_SUCCESS
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetBootDeviceInfo (
|
|
IN SHELL *Shell,
|
|
IN OUT CHAR16 *Buffer,
|
|
IN UINTN BufferSize,
|
|
OUT OS_BOOT_OPTION *BootOption,
|
|
IN OS_BOOT_OPTION *CurrOption
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOLEAN IsHex;
|
|
|
|
do {
|
|
ShellPrint (L"Enter ImageType (Default 0x%X, Fastboot 0x%X)\n",
|
|
EnumImageTypeDefault, EnumImageTypeFastboot
|
|
);
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->ImageType);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
BootOption->ImageType = (BOOT_IMAGE_TYPE) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->ImageType = CurrOption->ImageType;
|
|
break;
|
|
} else if (BootOption->ImageType < EnumImageTypeMax) {
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid ImageType value '%s', please re-enter\n", Buffer);
|
|
} while (1);
|
|
|
|
do {
|
|
ShellPrint (L"Enter DevType (SATA 0x%X, SD 0x%X, eMMC 0x%X, UFS 0x%X, SPI 0x%X, USB 0x%X, NVMe 0x%X, MEM 0x%X)\n",
|
|
OsBootDeviceSata, OsBootDeviceSd, OsBootDeviceEmmc, OsBootDeviceUfs, OsBootDeviceSpi, OsBootDeviceUsb,
|
|
OsBootDeviceNvme, OsBootDeviceMemory);
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->DevType);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
BootOption->DevType = (OS_BOOT_MEDIUM_TYPE) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->DevType = CurrOption->DevType;
|
|
break;
|
|
} else if (BootOption->DevType < OsBootDeviceMax) {
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid DevType value '%s', please re-enter\n", Buffer);
|
|
} while (1);
|
|
|
|
if (BootOption->DevType == OsBootDeviceMemory) {
|
|
return Status;
|
|
}
|
|
|
|
ShellPrint (L"Enter DevInstance (uint)\n");
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->DevInstance);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->DevInstance = CurrOption->DevInstance;
|
|
} else {
|
|
BootOption->DevInstance = (UINT8)((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
}
|
|
|
|
do {
|
|
ShellPrint (L"Enter BootFlags (NORMAL 0x0, MISC 0x1, CRASH_OS 0x2, PREOS 0x4, EXTRA 0x8, MENDER 0x10)\n");
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->BootFlags);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->BootFlags = CurrOption->BootFlags;
|
|
break;
|
|
}
|
|
BootOption->BootFlags = (OS_FILE_SYSTEM_TYPE) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
if (((UINT8)BootOption->BootFlags) <= ((UINT8)BOOT_FLAGS_MISC | BOOT_FLAGS_CRASH_OS | BOOT_FLAGS_PREOS | BOOT_FLAGS_EXTRA | BOOT_FLAGS_MENDER)) {
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid value '%s', please re-enter\n", Buffer);
|
|
} while (1);
|
|
|
|
ShellPrint (L"Enter HwPart (uint)\n");
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->HwPart);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->HwPart = CurrOption->HwPart;
|
|
} else {
|
|
BootOption->HwPart = (UINT8) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
}
|
|
|
|
do {
|
|
ShellPrint (L"Enter FsType (FAT (0x%X), EXT2/3/4 (0x%X), Auto (0x%X), RAW (0x%X))\n",
|
|
EnumFileSystemTypeFat, EnumFileSystemTypeExt2, EnumFileSystemTypeAuto,
|
|
EnumFileSystemMax);
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->FsType);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->FsType = CurrOption->FsType;
|
|
break;
|
|
}
|
|
BootOption->FsType = (OS_FILE_SYSTEM_TYPE) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
if (((UINT8)BootOption->FsType) <= ((UINT8)EnumFileSystemMax)) {
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid value '%s', please re-enter\n", Buffer);
|
|
} while (1);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get the OS boot entry's file info.
|
|
|
|
@param[in] Shell shell instance
|
|
@param[in, out] Buffer buffer for Shell user input
|
|
@param[in] BufferSize size of the Buffer in bytes
|
|
@param[out] BootOption update the boot entry with the file system type
|
|
and file path user values
|
|
@param[in] CurrOption the current boot entry value
|
|
|
|
@retval EFI_SUCCESS
|
|
@retval EFI_NO_MAPPING LoadImageType is not a valid Image index value
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetBootFileInfo (
|
|
IN SHELL *Shell,
|
|
IN OUT CHAR16 *Buffer,
|
|
IN UINTN BufferSize,
|
|
OUT OS_BOOT_OPTION *BootOption,
|
|
IN OS_BOOT_OPTION *CurrOption,
|
|
IN UINT8 LoadImageType
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOLEAN IsHex;
|
|
UINTN Length;
|
|
|
|
if (LoadImageType >= LoadImageTypeMax) {
|
|
ShellPrint (L"Invalid LoadImageType '0x%X'\n", LoadImageType);
|
|
return EFI_NO_MAPPING;
|
|
}
|
|
|
|
if (BootOption->DevType == OsBootDeviceMemory) {
|
|
do {
|
|
ShellPrint (L"Enter Image Address in Memory\n");
|
|
|
|
ShellPrint (L"(default '#0x%x') #", CurrOption->Image[LoadImageType].LbaImage.LbaAddr);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (!EFI_ERROR (Status)) {
|
|
BootOption->Image[LoadImageType].LbaImage.LbaAddr = (UINT32) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
BootOption->Image[LoadImageType].LbaImage.Valid = 1;
|
|
ShellPrint(L"Get Memory address: 0x%x\n", BootOption->Image[LoadImageType].LbaImage.LbaAddr);
|
|
break;
|
|
}
|
|
ShellPrint(L"Not able to read from shell");
|
|
} while (1);
|
|
return Status;
|
|
}
|
|
|
|
ShellPrint (L"Enter SwPart (uint)\n");
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->Image[LoadImageType].FileImage.SwPart);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->Image[LoadImageType].FileImage.SwPart = CurrOption->Image[LoadImageType].FileImage.SwPart;
|
|
} else {
|
|
BootOption->Image[LoadImageType].FileImage.SwPart = (UINT8) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
}
|
|
if (LoadImageType == LoadImageTypeNormal) {
|
|
BootOption->SwPart = BootOption->Image[LoadImageType].FileImage.SwPart;
|
|
}
|
|
|
|
do {
|
|
if (LoadImageType == LoadImageTypeNormal){
|
|
ShellPrint (L"Enter file path string (max length of %d)\n",
|
|
sizeof (BootOption->Image[LoadImageType].FileImage.FileName) - 1
|
|
);
|
|
} else if (LoadImageType == LoadImageTypePreOs){
|
|
ShellPrint (L"Enter Pre-OS file path string (max length of %d)\n",
|
|
sizeof (BootOption->Image[LoadImageType].FileImage.FileName) - 1
|
|
);
|
|
} else if (LoadImageType >= LoadImageTypeExtra0 && LoadImageType < LoadImageTypeMax){
|
|
ShellPrint (L"Enter Extra Image %d file path string (max length of %d)\n",
|
|
LoadImageType - LoadImageTypeExtra0,
|
|
sizeof (BootOption->Image[LoadImageType].FileImage.FileName) - 1
|
|
);
|
|
}
|
|
ShellPrint (L"(default '%a') ", CurrOption->Image[LoadImageType].FileImage.FileName);
|
|
Status = ShellReadLine (Shell, Buffer, BufferSize);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
Length = StrLen (Buffer);
|
|
if (Length == 0) {
|
|
CopyMem (BootOption->Image[LoadImageType].FileImage.FileName, CurrOption->Image[LoadImageType].FileImage.FileName, sizeof (CurrOption->Image[LoadImageType].FileImage.FileName));
|
|
break;
|
|
}
|
|
if (Length < sizeof (BootOption->Image[LoadImageType].FileImage.FileName)) {
|
|
UnicodeStrToAsciiStrS (Buffer, (CHAR8 *)BootOption->Image[LoadImageType].FileImage.FileName, sizeof (BootOption->Image[LoadImageType].FileImage.FileName));
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid, too long: '%s' len=%d, please re-enter\n", Buffer, Length);
|
|
} while (1);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get the OS boot entry's LBA info.
|
|
|
|
@param[in] Shell shell instance
|
|
@param[in, out] Buffer buffer for Shell user input
|
|
@param[in] BufferSize size of the Buffer in bytes
|
|
@param[out] BootOption update the boot entry with the LBA user values
|
|
@param[in] CurrOption the current boot entry value
|
|
|
|
@retval EFI_SUCCESS
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetBootLbaInfo (
|
|
IN SHELL *Shell,
|
|
IN OUT CHAR16 *Buffer,
|
|
IN UINTN BufferSize,
|
|
OUT OS_BOOT_OPTION *BootOption,
|
|
IN OS_BOOT_OPTION *CurrOption
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOLEAN IsHex;
|
|
|
|
ShellPrint (L"Enter SwPart (uint)\n");
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->Image[0].LbaImage.SwPart);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->Image[0].LbaImage.SwPart = CurrOption->Image[0].LbaImage.SwPart;
|
|
} else {
|
|
BootOption->Image[0].LbaImage.SwPart = (UINT8) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
}
|
|
BootOption->SwPart = BootOption->Image[0].LbaImage.SwPart;
|
|
|
|
ShellPrint (L"Enter LBA Address (uint)\n");
|
|
ShellPrint (L"(default 0x%X) ", CurrOption->Image[0].LbaImage.LbaAddr);
|
|
Status = ShellReadUintn (Shell, Buffer, BufferSize, &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (StrLen (Buffer) == 0) {
|
|
BootOption->Image[0].LbaImage.LbaAddr = CurrOption->Image[0].LbaImage.LbaAddr;
|
|
} else {
|
|
BootOption->Image[0].LbaImage.LbaAddr = (UINT32) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
}
|
|
BootOption->Image[0].LbaImage.Valid = 1;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Print Pre-OS or/and extra images.
|
|
|
|
@param[in] BootOption the boot options
|
|
@param[in] Flags the boot flags
|
|
@param[in] ImageType the image types
|
|
|
|
**/
|
|
VOID
|
|
PrintExtraImage (
|
|
OS_BOOT_OPTION *BootOption,
|
|
UINT8 Flags,
|
|
LOAD_IMAGE_TYPE ImageType
|
|
)
|
|
{
|
|
BOOT_IMAGE *BootImage;
|
|
|
|
BootImage = &BootOption->Image[ImageType];
|
|
if ((BootOption->BootFlags & Flags) != 0){
|
|
if (BootImage->LbaImage.Valid == 1) {
|
|
ShellPrint (L" %6a | %4a | %4x | 0x%x\n",
|
|
GetLoadedImageTypeNameString(ImageType),
|
|
"RAW",
|
|
BootImage->LbaImage.SwPart,
|
|
BootImage->LbaImage.LbaAddr
|
|
);
|
|
} else if (BootImage->FileImage.FileName[0] != '\0') {
|
|
ShellPrint (L" %6a | %4a | %4x | %a\n",
|
|
GetLoadedImageTypeNameString(ImageType),
|
|
GetFsTypeString(BootImage->FileImage.FsType),
|
|
BootImage->FileImage.SwPart,
|
|
BootImage->FileImage.FileName
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Print the OS boot option list.
|
|
|
|
@param[in] OsBootOptionList the OS boot option list
|
|
|
|
**/
|
|
VOID
|
|
PrintBootOption (
|
|
OS_BOOT_OPTION_LIST *OsBootOptionList
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
OS_BOOT_OPTION *BootOption;
|
|
|
|
ShellPrint (L"Boot options (in HEX):\n\n");
|
|
|
|
ShellPrint (L"Idx|ImgType|DevType|DevNum|Flags|HwPart|FsType|SwPart|File/Lbaoffset\n");
|
|
for (Index = 0; Index < OsBootOptionList->OsBootOptionCount; Index++) {
|
|
BootOption = &OsBootOptionList->OsBootOption[Index];
|
|
if (BootOption->DevType == OsBootDeviceMemory) {
|
|
ShellPrint (L"%3x|%7x| %5a | - | %3x | - | - | - | 0x%x", \
|
|
Index, \
|
|
BootOption->ImageType, \
|
|
GetBootDeviceNameString(BootOption->DevType), \
|
|
BootOption->BootFlags, \
|
|
BootOption->Image[0].LbaImage.LbaAddr \
|
|
);
|
|
} else if (BootOption->FsType < EnumFileSystemMax) {
|
|
ShellPrint (L"%3x|%7x| %5a | %4x | %3x | %4x | %4a | %4x | %a", \
|
|
Index, \
|
|
BootOption->ImageType, \
|
|
GetBootDeviceNameString(BootOption->DevType), \
|
|
BootOption->DevInstance, \
|
|
BootOption->BootFlags, \
|
|
BootOption->HwPart, \
|
|
GetFsTypeString (BootOption->FsType), \
|
|
BootOption->Image[0].FileImage.SwPart, \
|
|
BootOption->Image[0].FileImage.FileName \
|
|
);
|
|
} else {
|
|
ShellPrint (L"%3x|%7x| %5a | %4x | %3x | %4x | %4a | %4x | 0x%x", \
|
|
Index, \
|
|
BootOption->ImageType, \
|
|
GetBootDeviceNameString(BootOption->DevType), \
|
|
BootOption->DevInstance, \
|
|
BootOption->BootFlags, \
|
|
BootOption->HwPart, \
|
|
GetFsTypeString (BootOption->FsType), \
|
|
BootOption->Image[0].LbaImage.SwPart, \
|
|
BootOption->Image[0].LbaImage.LbaAddr \
|
|
);
|
|
}
|
|
|
|
if (Index == OsBootOptionList->CurrentBoot) {
|
|
ShellPrint (L" *Current");
|
|
}
|
|
ShellPrint (L"\n");
|
|
|
|
//Print extra image filename
|
|
for (UINT8 Type = LoadImageTypeExtra0; Type < LoadImageTypeMax; Type++) {
|
|
PrintExtraImage (BootOption, BOOT_FLAGS_EXTRA, Type);
|
|
}
|
|
|
|
//Print Pre-OS image filename
|
|
PrintExtraImage (BootOption,BOOT_FLAGS_PREOS,LoadImageTypePreOs);
|
|
|
|
//Print misc image filename
|
|
PrintExtraImage (BootOption,BOOT_FLAGS_MISC,LoadImageTypeMisc);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Print the the command usage.
|
|
|
|
@param[in] Argv command line arguments
|
|
|
|
**/
|
|
VOID
|
|
PrintUsage (
|
|
IN CHAR16 *Argv[]
|
|
)
|
|
{
|
|
ShellPrint (L"Usage: %s [-h|-p]\n", Argv[0]);
|
|
ShellPrint (L" -h: print the usage\n");
|
|
ShellPrint (L" -p: print the Boot Option List\n");
|
|
}
|
|
|
|
/**
|
|
Print or modify the OS boot option list.
|
|
|
|
@param[in] Shell shell instance
|
|
@param[in] Argc number of command line arguments
|
|
@param[in] Argv command line arguments
|
|
|
|
@retval EFI_SUCCESS
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ShellCommandBootFunc (
|
|
IN SHELL *Shell,
|
|
IN UINTN Argc,
|
|
IN CHAR16 *Argv[]
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
CHAR16 Buffer[0x100];
|
|
OS_BOOT_OPTION_LIST *BootOptionList;
|
|
OS_BOOT_OPTION BootOption;
|
|
OS_BOOT_OPTION *CurrOption;
|
|
BOOLEAN SkipArgParse;
|
|
BOOLEAN ChangeCurrentIndex;
|
|
BOOLEAN IsHex;
|
|
BOOLEAN Swap;
|
|
EFI_STATUS Status;
|
|
|
|
SkipArgParse = FALSE;
|
|
Status = EFI_SUCCESS;
|
|
|
|
if (Argc > 2) {
|
|
PrintUsage (Argv);
|
|
return Status;
|
|
} else if (Argc == 1) {
|
|
SkipArgParse = TRUE;
|
|
}
|
|
|
|
BootOptionList = GetBootOptionList ();
|
|
if (BootOptionList == NULL || BootOptionList->OsBootOptionCount == 0) {
|
|
ShellPrint (L"No Boot Option List found!\n");
|
|
Status = EFI_ABORTED;
|
|
goto ExitBootCmd;
|
|
}
|
|
|
|
if (!SkipArgParse) {
|
|
if (StrCmp (Argv[1], L"-h") == 0) {
|
|
PrintUsage (Argv);
|
|
goto ExitBootCmd;
|
|
} else if (StrCmp (Argv[1], L"-p") == 0) {
|
|
PrintBootOption (BootOptionList);
|
|
goto ExitBootCmd;
|
|
} else {
|
|
PrintUsage (Argv);
|
|
goto ExitBootCmd;
|
|
}
|
|
}
|
|
|
|
Swap = FALSE;
|
|
ChangeCurrentIndex = FALSE;
|
|
|
|
PrintBootOption (BootOptionList);
|
|
do {
|
|
ShellPrint (L"SubCommand:\n");
|
|
ShellPrint (L" q -- quit boot option change\n");
|
|
ShellPrint (L" s -- swap boot order by index\n");
|
|
ShellPrint (L" c -- set the boot index\n");
|
|
ShellPrint (L" idx -- modify the boot option specified by idx (0");
|
|
|
|
if (BootOptionList->OsBootOptionCount > 1) {
|
|
ShellPrint (L" to %u", BootOptionList->OsBootOptionCount - 1);
|
|
}
|
|
ShellPrint (L")\n");
|
|
|
|
Status = ShellReadLine (Shell, Buffer, sizeof (Buffer));
|
|
if (EFI_ERROR (Status)) {
|
|
goto ExitBootCmd;
|
|
}
|
|
|
|
Index = 0;
|
|
if (StrCmp (Buffer, L"s") == 0) {
|
|
Swap = TRUE;
|
|
break;
|
|
} else if (StrCmp (Buffer, L"c") == 0) {
|
|
ChangeCurrentIndex = TRUE;
|
|
break;
|
|
} else if (StrCmp (Buffer, L"q") == 0) {
|
|
goto ExitBootCmd;
|
|
} else {
|
|
Index = (UINT16)StrHexToUintn (Buffer);
|
|
if ((StrLen (Buffer) > 0) && (Index < BootOptionList->OsBootOptionCount)) {
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid value '%s', please re-enter\n", Buffer);
|
|
}
|
|
} while (1);
|
|
|
|
if (Swap) {
|
|
Status = SwapBootEntries (Shell, Buffer, sizeof (Buffer), BootOptionList);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ExitBootCmd;
|
|
}
|
|
} else if (ChangeCurrentIndex) {
|
|
do {
|
|
ShellPrint (L"Enter index to change to (0 to %u)\n",
|
|
BootOptionList->OsBootOptionCount - 1
|
|
);
|
|
ShellPrint (L"(current index %u) ", BootOptionList->CurrentBoot);
|
|
Status = ShellReadUintn (Shell, Buffer, sizeof (Buffer), &IsHex);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
Index = (UINT8) ((IsHex) ? StrHexToUintn (Buffer) : StrDecimalToUintn (Buffer));
|
|
if (StrLen (Buffer) == 0) {
|
|
break;
|
|
} else if (Index < BootOptionList->OsBootOptionCount) {
|
|
BootOptionList->CurrentBoot = (UINT8) Index;
|
|
BootOptionList->BootOptionReset = 0x1;
|
|
break;
|
|
}
|
|
ShellPrint (L"Invalid index '%s', please re-enter\n", Buffer);
|
|
} while (1);
|
|
} else {
|
|
CurrOption = &BootOptionList->OsBootOption[Index];
|
|
ZeroMem (&BootOption, sizeof (BootOption));
|
|
Status = GetBootDeviceInfo (Shell, Buffer, sizeof (Buffer), &BootOption, CurrOption);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ExitBootCmd;
|
|
}
|
|
|
|
if (BootOption.FsType != EnumFileSystemMax) {
|
|
BootOption.Image[LoadImageTypeNormal].FileImage.FsType = BootOption.FsType;
|
|
Status = GetBootFileInfo (Shell, Buffer, sizeof (Buffer), &BootOption, CurrOption, LoadImageTypeNormal);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ExitBootCmd;
|
|
}
|
|
if ((BootOption.BootFlags & BOOT_FLAGS_PREOS) != 0){
|
|
Status = GetBootFileInfo (Shell, Buffer, sizeof (Buffer), &BootOption, CurrOption, LoadImageTypePreOs);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ExitBootCmd;
|
|
}
|
|
}
|
|
if ((BootOption.BootFlags & BOOT_FLAGS_EXTRA) != 0){
|
|
Status = GetBootFileInfo (Shell, Buffer, sizeof (Buffer), &BootOption, CurrOption, LoadImageTypeExtra0);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ExitBootCmd;
|
|
}
|
|
}
|
|
} else {
|
|
Status = GetBootLbaInfo (Shell, Buffer, sizeof (Buffer), &BootOption, CurrOption);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ExitBootCmd;
|
|
}
|
|
}
|
|
CopyMem (&BootOptionList->OsBootOption[Index], &BootOption, sizeof (BootOption));
|
|
}
|
|
ShellPrint (L"Updated the Boot Option List\n");
|
|
PrintBootOption (BootOptionList);
|
|
|
|
ExitBootCmd:
|
|
if (EFI_ERROR (Status)) {
|
|
ShellPrint (L"ERROR, exiting command unsuccessfully\n");
|
|
}
|
|
return Status;
|
|
}
|