【问题标题】:How do I start UEFI shell with parameters programmatically?如何以编程方式使用参数启动 UEFI shell?
【发布时间】:2022-01-07 03:36:13
【问题描述】:

我正在使用 EDKII 编写 UEFI 模块。 我希望此模块使用参数加载和启动 UEFI shell(以使用其命令行功能)。 到目前为止,我有以下代码,它成功加载并启动了 UEFI shell,但我似乎无法弄清楚如何使用参数启动它。

EFI_STATUS
LoadAndStartShell (
  IN EFI_HANDLE        ImageHandle
  )
{
  UINTN NumHandles;
  UINTN Index;
  EFI_HANDLE *SFS_Handles;
  EFI_HANDLE AppImageHandle = NULL;
  EFI_STATUS Status = EFI_SUCCESS;
  EFI_BLOCK_IO_PROTOCOL *BlkIo;
  CONST CHAR16 *FileName = L"Shell.efi";
  EFI_DEVICE_PATH_PROTOCOL *FilePath;
  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
  UINTN ExitDataSize;

  Status = gBS->LocateHandleBuffer(
          ByProtocol,
          &gEfiSimpleFileSystemProtocolGuid,
          NULL,
          &NumHandles,
          &SFS_Handles);

  if (Status != EFI_SUCCESS) {
      Print(L"Could not find handles - %r\n", Status);
      return Status;
  }

  for (Index = 0; Index < NumHandles; Index++) {
      Status = gBS->OpenProtocol(
              SFS_Handles[Index],
              &gEfiSimpleFileSystemProtocolGuid,
              (VOID**) &BlkIo,
              ImageHandle,
              NULL,
              EFI_OPEN_PROTOCOL_GET_PROTOCOL
              );
  
      if (Status != EFI_SUCCESS) {
          Print(L"Protocol is not supported - %r\n", Status);
          return Status;
      }
  
      FilePath = FileDevicePath(SFS_Handles[Index], FileName);
      Status = gBS->LoadImage(
              FALSE, 
              ImageHandle, 
              FilePath, 
              (VOID*) NULL, 
              0, 
              &AppImageHandle);

      if (Status != EFI_SUCCESS) {
          Print(L"Could not load the image - %r\n", Status);
          continue;
      }

      Print(L"Loaded the image with success\n");
      Status = gBS->OpenProtocol(
              AppImageHandle,
              &gEfiLoadedImageProtocolGuid,
              (VOID**) &ImageInfo,
              ImageHandle,
              (VOID*) NULL,
              EFI_OPEN_PROTOCOL_GET_PROTOCOL
              );

      Print(L"ImageInfo opened\n");


      if (!EFI_ERROR(Status)) {
          Print(L"ImageSize = %d\n", ImageInfo->ImageSize);
      }

      Print(L"Image start:\n");
      Status = gBS->StartImage(AppImageHandle, &ExitDataSize, (CHAR16**) NULL);
      if (Status != EFI_SUCCESS) {
          Print(L"Could not start the image - %r %x\n", Status, Status);
          Print(L"Exit data size: %d\n", ExitDataSize);
          continue;
      }
  return Status;
  }
  return Status;
}

我在加载图像后尝试访问 EFI_SHELL_PARAMETERS_PROTOCOL,但在启动它之前,我认为我可以从那里手动更改参数,但当时似乎尚未安装协议(即使它在 UEFI Shell 中显示在调用 StartImage 之前安装协议的规范。

【问题讨论】:

  • “带参数”是什么意思?您希望 shell 以与现在的行为方式不同的方式“使用参数”执行什么操作?
  • @unixsmurf 我的意思是,您可以使用命令行参数运行 shell.efi 来影响其行为。例如运行“shell.efi -exit echo Hello World!”将运行一个新的 shell 实例,使其打印“Hello World!”,然后退出该 shell。您可以在 UEFI Shell 规范中了解它。

标签: c uefi edk2


【解决方案1】:

LoadedImage 协议包含两个成员变量,可以直接访问它们来设置指向命令行的指针和命令行的字节大小。

UINT32 LoadOptionsSize;
VOID *LoadOptions;

在你的代码中已经有了 LoadedImage 协议后,只需使用 ImageInfo 指针来设置这些字段。

ImageInfo->LoadOptions = cmdline;
ImageInfo->LoadOptionsSize = cmdline_size;

加载选项的解释取决于应用程序。我相信 Shell 将其视为 Unicode 字符串(UCS-2)。

【讨论】:

  • 是的,Shell 将 LoadOptions 视为 CHAR16 字符串。 CHAR16 使用 Unicode 2.1 和 ISO/IEC 10646 标准定义的 UCS-2 编码格式。
猜你喜欢
  • 2017-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-04
  • 1970-01-01
  • 2022-10-08
相关资源
最近更新 更多