搜尋此網誌

2012年10月3日 星期三

LoadDriver() - How to load uefi/efi driver in code?

/*You can find the function in Shell load.c*/

STATIC
EFI_STATUS
LoadDriver (
  IN EFI_HANDLE               ParentImage,
  IN SHELL_FILE_ARG           *Arg,
  IN BOOLEAN                  Connect
  )
{
  EFI_HANDLE                ImageHandle;
  EFI_STATUS                Status;
  EFI_DEVICE_PATH_PROTOCOL  *NodePath;
  EFI_DEVICE_PATH_PROTOCOL  *FilePath;
  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
  CHAR16                    *LoadOptions;
  UINTN                     LoadOptionsSize;
  CHAR16                    *Cwd;
  EFI_IMAGE_DOS_HEADER      DosHeader;
  EFI_IMAGE_FILE_HEADER     ImageHeader;
  EFI_IMAGE_OPTIONAL_HEADER OptionalHeader;

  NodePath  = FileDevicePath (NULL, Arg->FileName);
  FilePath  = AppendDevicePath (Arg->ParentDevicePath, NodePath);
  if (NodePath) {
    FreePool (NodePath);
    NodePath = NULL;
  }

  if (!FilePath) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Check whether Image is valid to be loaded.
  //
  Status = LibGetImageHeader (
    FilePath,
    &DosHeader,
    &ImageHeader,
    &OptionalHeader
    );
  if (!EFI_ERROR (Status) && !EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageHeader.Machine) &&
     (OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ||
      OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {
    FreePool (FilePath);
    PrintToken (
      STRING_TOKEN (STR_LOAD_IMAGE_TYPE_UNSUPPORTED),
      HiiLoadHandle,
      LibGetMachineTypeString (ImageHeader.Machine),
      LibGetMachineTypeString (EFI_IMAGE_MACHINE_TYPE)
      );
    return EFI_INVALID_PARAMETER;
  }

  Status = BS->LoadImage (
                FALSE,
                ParentImage,
                FilePath,
                NULL,
                0,
                &ImageHandle
                );
  FreePool (FilePath);

  if (EFI_ERROR (Status)) {
    if (Status == EFI_SECURITY_VIOLATION) {
      BS->UnloadImage (ImageHandle);
    }
    PrintToken (STRING_TOKEN (STR_LOAD_NOT_IMAGE), HiiLoadHandle, Arg->FullName);
    return EFI_INVALID_PARAMETER;
  }
  //
  // Verify the image is a driver ?
  //
  BS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &ImageInfo);
  if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {

    PrintToken (STRING_TOKEN (STR_LOAD_IMAGE_NOT_DRIVER), HiiLoadHandle, Arg->FullName);
    BS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
    return EFI_INVALID_PARAMETER;
  }
  //
  // Construct a load options buffer containing the command line and
  // current working directory.
  //
  // NOTE: To prevent memory leaks, the protocol is responsible for
  // freeing the memory associated with the load options.
  //
  // One day we'll pass arguments to the protocol....
  //
  Cwd = ShellCurDir (NULL);
  if (NULL == Cwd) {
    Cwd = StrDuplicate (L"");
  }

  LoadOptionsSize = (StrLen (Arg->FullName) + 2 + StrLen (Cwd) + 2) * sizeof (CHAR16);
  LoadOptions     = AllocatePool (LoadOptionsSize);
  ASSERT (LoadOptions);

  StrCpy (LoadOptions, Arg->FullName);
  StrCpy (&LoadOptions[StrLen (LoadOptions) + 1], Cwd);
  FreePool (Cwd);

  if (ImageInfo->LoadOptions) {
    FreePool (ImageInfo->LoadOptions);
  }

  ImageInfo->LoadOptionsSize  = (UINT32) LoadOptionsSize;
  ImageInfo->LoadOptions      = LoadOptions;

  //
  // Start the image
  //
  Status = BS->StartImage (ImageHandle, NULL, NULL);
  if (!EFI_ERROR (Status)) {
    PrintToken (
      STRING_TOKEN (STR_LOAD_IMAGE_LOADED),
      HiiLoadHandle,
      Arg->FullName,
      ImageInfo->ImageBase,
      Status
      );
  } else {
    PrintToken (
      STRING_TOKEN (STR_LOAD_IMAGE_ERROR),
      HiiLoadHandle,
      Arg->FullName,
      Status
      );
  }

  if (Connect) {
    Status = LoadConnectAllDriversToAllControllers ();
  }
  //
  // When any driver starts, turn off the watchdog timer
  //
  BS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
  return Status;
}

1 則留言: