简体   繁体   中英

How do I start UEFI shell with parameters programmatically?

I'm using EDKII to write a UEFI module. I want this module to load and start UEFI shell with parameters (to use its command lines capabilities). So far I have the following code, which successfully loads and starts the UEFI shell, but I can't seem to figure out how to start it with parameters.

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;
}

I tried accessing the EFI_SHELL_PARAMETERS_PROTOCOL after loading the image but before starting it, thinking I could manually change the parameters from there, but it seems like the protocol isn't installed yet at that point (even though it says at the UEFI Shell Specification that the protocol is installed before StartImage is called).

The LoadedImage protocol contains two member variables that can be accessed directly to set the pointer to the command line and the size in bytes of the command line.

UINT32 LoadOptionsSize;
VOID *LoadOptions;

After getting the LoadedImage protocol which you already have in your code, just use the ImageInfo pointer to set these fields.

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

The interpretation of the load options is up to the application. I believe that the Shell treats it as a Unicode string (UCS-2).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM