概要
这需求就是类似于linux系统下的系统调用接口system("command")
EDK中实现
Shell protocol 实现
包含协议
[Protocols]
gEfiShellProtocolGuid ## CONSUMES
Demo
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_SHELL_PROTOCOL *EfiShellProtocol;
EFI_STATUS Status;
//初始化协议
Status = gBS->LocateProtocol (&gEfiShellProtocolGuid,
NULL,
(VOID **) &EfiShellProtocol);
if (EFI_ERROR (Status)) {
return Status;
}
EfiShellProtocol->Execute (&ImageHandle,
L"echo map -r",
NULL,
&Status);
return Status;
}
Execute
在 ShellPkg/Application/Shell/ShellProtocol.c
EFI_STATUS
EFIAPI
EfiShellExecute(
IN EFI_HANDLE *ParentImageHandle,
IN CHAR16 *CommandLine OPTIONAL,
IN CHAR16 **Environment OPTIONAL,
OUT EFI_STATUS *StatusCode OPTIONAL
)
{
EFI_STATUS Status;
CHAR16 *Temp;
EFI_DEVICE_PATH_PROTOCOL *DevPath;
UINTN Size;
if ((PcdGet8(PcdShellSupportLevel) < 1)) {
return (EFI_UNSUPPORTED);
}
if (NestingEnabled()) {
DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);
DEBUG_CODE_BEGIN();
Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);
FreePool(Temp);
Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);
FreePool(Temp);
Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);
FreePool(Temp);
DEBUG_CODE_END();
Temp = NULL;
Size = 0;
ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));
StrnCatGrow(&Temp, &Size, L"Shell.efi -exit ", 0);
StrnCatGrow(&Temp, &Size, CommandLine, 0);
Status = InternalShellExecuteDevicePath(
ParentImageHandle,
DevPath,
Temp,
(CONST CHAR16**)Environment,
StatusCode);
//
// de-allocate and return
//
FreePool(DevPath);
FreePool(Temp);
} else {
Status = InternalShellExecute(
(CONST CHAR16*)CommandLine,
(CONST CHAR16**)Environment,
StatusCode);
}
return(Status);
}
需要说明的是NestingEnabled
跑到这里会返回无效的参数,InternalShellExecute
用这个接口是可以的;我使用的是UDK2018
库
使用UefiShellLib库的接口,跟方便,位置在ShellPkg/Library/UefiShellLib
#include <Library/ShellLib.h>
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
ShellExecute (&ImageHandle,
L"echo Hello World!",
FALSE,
NULL,
&Status);
return Status;
}
其实最终调用的还是EfiShellExecute
接口;
参考
https://stackoverflow.com/questions/38738862/run-a-uefi-shell-command-from-inside-uefi-application