/** @file
Shell command `fs` to view partition information
Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
STATIC OS_BOOT_MEDIUM_TYPE mDeviceType = OsBootDeviceMax;
STATIC UINT8 mDeviceInstance = 0;
STATIC EFI_HANDLE mHwPartHandle = NULL;
STATIC EFI_HANDLE mFsHandle = NULL;
/**
Show media information
@param[in] Shell shell instance
@param[in] Argc number of command line arguments
@param[in] Argv command line arguments
@retval EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
ShellCommandFsFunc (
IN SHELL *Shell,
IN UINTN Argc,
IN CHAR16 *Argv[]
);
CONST SHELL_COMMAND ShellCommandFs = {
L"fs",
L"filesystem access command",
&ShellCommandFsFunc
};
/**
Print available platform devices
@retval none
**/
STATIC
VOID
PrintPlatformDevices (
IN VOID
)
{
PLT_DEVICE_TABLE *DeviceTable;
UINT16 Count;
UINT16 Index;
OS_BOOT_MEDIUM_TYPE DeviceType;
UINT8 DeviceInstance;
Count = 0;
DeviceTable = (PLT_DEVICE_TABLE *)GetDeviceTable ();
if (DeviceTable != NULL) {
Count = DeviceTable->DeviceNumber;
for (Index = 0; Index < Count; Index++) {
DeviceType = (OS_BOOT_MEDIUM_TYPE)DeviceTable->Device[Index].Type;
if (DeviceType >= OsBootDeviceMax)
continue;
DeviceInstance = DeviceTable->Device[Index].Instance;
ShellPrint (L" %d:%d %a", DeviceType, DeviceInstance, GetBootDeviceNameString (DeviceType));
if (DeviceTable->Device[Index].Dev.PciDev.IsMmioDevice != 0) {
ShellPrint (L"(MEM 0x%x)\n", DeviceTable->Device[Index].Dev.DevAddr);
} else {
ShellPrint (L"(PCI 0x%x:0x%x:0x%x)\n",
DeviceTable->Device[Index].Dev.PciDev.PciBusNumber,
DeviceTable->Device[Index].Dev.PciDev.PciDeviceNumber,
DeviceTable->Device[Index].Dev.PciDev.PciFunctionNumber);
}
}
}
}
/**
Close file system
@retval EFI_SUCCESS
**/
STATIC
EFI_STATUS
CmdFsClose (
IN VOID
)
{
if (mFsHandle != NULL) {
CloseFileSystem (mFsHandle);
mFsHandle = NULL;
}
if (mHwPartHandle != NULL) {
ClosePartitions (mHwPartHandle);
mHwPartHandle = NULL;
}
if (mDeviceType != OsBootDeviceMax) {
// De-init the current media device
// If USB keyboard console is used, don't DeInit USB yet.
if (!((mDeviceType == OsBootDeviceUsb) &&
((PcdGet32 (PcdConsoleInDeviceMask) & ConsoleInUsbKeyboard) != 0))) {
MediaInitialize (0, DevDeinit);
}
mDeviceType = OsBootDeviceMax;
mDeviceInstance = 0;
}
return EFI_SUCCESS;
}
/**
Initialize file system
@param[in] DeviceType Platform Device Index
@param[in] DeviceInstance The device instance number starting from 0.
@param[in] HwPartNo HW Partition Number
@param[in] SwPartNo SW Partition Number
@retval EFI_SUCCESS FS init success
@retval Others Error
**/
STATIC
EFI_STATUS
CmdFsInit (
IN OS_BOOT_MEDIUM_TYPE DeviceType,
IN UINT8 DeviceInstance,
IN UINT32 HwPartNo,
IN UINT32 SwPartNo
)
{
EFI_STATUS Status;
OS_FILE_SYSTEM_TYPE FsType;
UINTN BaseAddress;
// Get device bar
BaseAddress = GetDeviceAddr (DeviceType, DeviceInstance);
if (BaseAddress == 0) {
ShellPrint (L"Device no. %d (%a) is not in platform devices. - ",
DeviceType, GetBootDeviceNameString (DeviceType));
PrintPlatformDevices ();
return EFI_ABORTED;
} else if (!(BaseAddress & 0xFF000000)) {
BaseAddress = TO_MM_PCI_ADDRESS (BaseAddress);
}
if (mDeviceType != OsBootDeviceMax) {
CmdFsClose ();
}
// Set media interface
Status = MediaSetInterfaceType (DeviceType);
if (EFI_ERROR (Status)) {
return Status;
}
Status = MediaInitialize (BaseAddress, DevInitAll);
ShellPrint (L"Media(%a) Init ", GetBootDeviceNameString (DeviceType));
mDeviceType = DeviceType;
mDeviceInstance = DeviceInstance;
if (!EFI_ERROR (Status)) {
ShellPrint (L"Success!\n");
} else {
ShellPrint (L"Fail!\n");
goto Error;
}
// Find a partition
ShellPrint (L"Find a Partition\n");
Status = FindPartitions (HwPartNo, &mHwPartHandle);
ShellPrint (L"Partition Detect (device:%d, hwpart:%d) ", mDeviceType, HwPartNo);
if (!EFI_ERROR (Status)) {
ShellPrint (L"Success!\n");
} else {
ShellPrint (L"Fail!\n");
goto Error;
}
ShellPrint (L"Init FileSystem\n");
Status = InitFileSystem (SwPartNo, EnumFileSystemTypeAuto, mHwPartHandle, &mFsHandle);
ShellPrint (L"FileSystem Detect (device:%d, hwpart:%d, swpart:%d) ",
mDeviceType, HwPartNo, SwPartNo);
if (!EFI_ERROR (Status)) {
FsType = GetFileSystemType (mFsHandle);
ShellPrint (L"Success! (%a)\n", GetFsTypeString (FsType));
} else {
ShellPrint (L"Fail!\n");
goto Error;
}
return EFI_SUCCESS;
Error:
CmdFsClose ();
return Status;
}
/**
Print directory or file list
@retval EFI_SUCCESS
@retval EFI_ABORTED
**/
STATIC
EFI_STATUS
CmdFsFsListDir (
IN CHAR16 *DirFilePath
)
{
EFI_STATUS Status;
if (mFsHandle == NULL) {
ShellPrint (L"FileSystem is not initialized!\n");
return EFI_ABORTED;
}
Status = ListDir (mFsHandle, DirFilePath);
if (Status == EFI_NOT_FOUND) {
ShellPrint (L"Not found!\n");
} else if (Status == EFI_UNSUPPORTED) {
ShellPrint (L"This command has been disabled.\n");
}
return EFI_SUCCESS;
}
/**
Load a file into memory.
@param[in] File path to load.
@param[in] LoadAddr Memory address to load.
@retval EFI_SUCCESS File was loaded successfully.
@retval EFI_ABORTED File system is not initialized.
@retval EFI_OUT_OF_RESOURCES Insufficant memory.
@retval EFI_BAD_BUFFER_SIZE File size is 0.
**/
STATIC
EFI_STATUS
CmdFsLoad (
IN CHAR16 *FilePath,
IN UINTN LoadAddr
)
{
EFI_STATUS Status;
UINTN ImageSize;
VOID *Image;
EFI_HANDLE FsHandle;
EFI_HANDLE FileHandle;
FsHandle = mFsHandle;
if (FsHandle == NULL) {
ShellPrint (L"FileSystem is not initialized!\n");
return EFI_ABORTED;
}
FileHandle = NULL;
Status = OpenFile (FsHandle, FilePath, &FileHandle);
if (EFI_ERROR (Status)) {
goto FileLoadErrOut;
}
Status = GetFileSize (FileHandle, &ImageSize);
if (EFI_ERROR (Status)) {
goto FileLoadErrOut;
}
if (ImageSize == 0) {
Status = EFI_BAD_BUFFER_SIZE;
goto FileLoadErrOut;
}
if (LoadAddr == 0) {
// Allocate space for loading
Image = AllocatePages (EFI_SIZE_TO_PAGES (ImageSize));
if (Image == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto FileLoadErrOut;
}
} else {
Image = (VOID *)LoadAddr;
}
Status = ReadFile (FileHandle, Image, &ImageSize);
if (EFI_ERROR (Status)) {
if ((Image != NULL) && (LoadAddr == 0)) {
FreePages (Image, EFI_SIZE_TO_PAGES (ImageSize));
}
goto FileLoadErrOut;
}
FileLoadErrOut:
if (EFI_ERROR (Status)) {
ShellPrint (L"Failed to load file: %r\n", Status);
} else {
ShellPrint (L"File was loaded at 0x%p with length 0x%X!\n", Image, ImageSize);
}
if (FileHandle != NULL) {
CloseFile (FileHandle);
}
return Status;
}
/**
Display current filesystem info
@retval EFI_SUCCESS
**/
STATIC
EFI_STATUS
CmdFsInfo (
IN VOID
)
{
EFI_STATUS Status;
UINT32 HwPartNo;
UINT32 SwPartNo;
OS_FILE_SYSTEM_TYPE FsType;
ShellPrint (L"Current DeviceType: %a\n", (mDeviceType != OsBootDeviceMax) ?
GetBootDeviceNameString (mDeviceType) : "Not Initialized");
ShellPrint (L"Current DeviceInstance: %d\n", mDeviceInstance);
ShellPrint (L"Current HwPart: ");
Status = GetPartitionCurrentPartNo (mHwPartHandle, &HwPartNo);
if (!EFI_ERROR (Status)) {
ShellPrint (L"%d\n", HwPartNo);
} else {
ShellPrint (L"Not Initialized\n");
}
ShellPrint (L"Current SwPart: ");
Status = GetFileSystemCurrentPartNo (mFsHandle, &SwPartNo);
if (!EFI_ERROR (Status)) {
ShellPrint (L"%d\n", SwPartNo);
} else {
ShellPrint (L"Not Initialized\n");
}
FsType = GetFileSystemType (mFsHandle);
ShellPrint (L"Current FileSystem: %a\n", (FsType != EnumFileSystemMax) ?
GetFsTypeString (FsType) : "Not Detected");
return EFI_SUCCESS;
}
/**
Basic file system test commands
@param[in] Shell shell instance
@param[in] Argc number of command line arguments
@param[in] Argv command line arguments
@retval EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
ShellCommandFsFunc (
IN SHELL *Shell,
IN UINTN Argc,
IN CHAR16 *Argv[]
)
{
EFI_STATUS Status;
OS_BOOT_MEDIUM_TYPE DeviceType;
UINT8 DeviceInstance;
UINT32 HwPartNo;
UINT32 SwPartNo;
CHAR16 *SubCmd;
CHAR16 *String;
UINTN Result;
UINTN LoadAddr;
if (Argc < 2) {
goto Usage;
}
SubCmd = Argv[1];
if (StrCmp (SubCmd, L"init") == 0) {
if (Argc < 3) {
DeviceType = 0;
DeviceInstance = 0;
} else {
Status = StrHexToUintnS (Argv[2], &String, &Result);
if (EFI_ERROR (Status)) {
goto Usage;
}
DeviceType = (OS_BOOT_MEDIUM_TYPE)Result;
Result = 0;
if (String[0] == L':') {
String++;
Status = StrHexToUintnS (String, NULL, &Result);
if (EFI_ERROR (Status)) {
goto Usage;
}
}
DeviceInstance = (UINT8)Result;
}
HwPartNo = (Argc < 4) ? 0 : (UINT32)StrHexToUintn (Argv[3]);
SwPartNo = (Argc < 5) ? 0 : (UINT32)StrHexToUintn (Argv[4]);
Status = CmdFsInit (DeviceType, DeviceInstance, HwPartNo, SwPartNo);
} else if (StrCmp (SubCmd, L"close") == 0) {
Status = CmdFsClose ();
} else if (StrCmp (SubCmd, L"ls") == 0) {
Status = CmdFsFsListDir ((Argc < 3) ? L"/" : Argv[2]);
} else if (StrCmp (SubCmd, L"info") == 0) {
Status = CmdFsInfo ();
} else if (StrCmp (SubCmd, L"load") == 0) {
LoadAddr = (Argc < 4) ? 0 : StrHexToUintn (Argv[3]);
Status = CmdFsLoad ((Argc < 3) ? L"/" : Argv[2], LoadAddr);
} else {
goto Usage;
}
return Status;
Usage:
ShellPrint (L"Usage: %s init [DevType[:DevInstance]] [HwPart] [SwPart]\n", Argv[0]);
ShellPrint (L" %s close\n", Argv[0]);
ShellPrint (L" %s info\n", Argv[0]);
ShellPrint (L" %s ls [dir or file path]\n", Argv[0]);
ShellPrint (L" %s load [dir or file path] [Address]\n", Argv[0]);
ShellPrint (L"\nDevType:DevInstance - Media type and instance number in the same media type\n");
PrintPlatformDevices ();
ShellPrint (L"HwPart - HW partition or port number\n");
ShellPrint (L"SwPart - Logical partition number from MBR or GPT\n");
return EFI_ABORTED;
}