コード例 #1
0
/**
  Start an EFI Application from a Device Path

  @param  ParentImageHandle     Handle of the calling image
  @param  DevicePath            Location of the EFI Application

  @retval EFI_SUCCESS           All drivers have been connected
  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found
  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.

**/
EFI_STATUS
BdsStartEfiApplication (
    IN EFI_HANDLE                  ParentImageHandle,
    IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
    IN UINTN                       LoadOptionsSize,
    IN VOID*                       LoadOptions
)
{
    EFI_STATUS                   Status;
    EFI_HANDLE                   ImageHandle;
    EFI_PHYSICAL_ADDRESS         BinaryBuffer;
    UINTN                        BinarySize;
    EFI_LOADED_IMAGE_PROTOCOL*   LoadedImage;

    // Find the nearest supported file loader
    Status = BdsLoadImage (DevicePath, AllocateAnyPages, &BinaryBuffer, &BinarySize);
    if (EFI_ERROR(Status)) {
        return Status;
    }

    // Load the image from the Buffer with Boot Services function
    Status = gBS->LoadImage (TRUE, ParentImageHandle, DevicePath, (VOID*)(UINTN)BinaryBuffer, BinarySize, &ImageHandle);
    if (EFI_ERROR(Status)) {
        return Status;
    }

    // Passed LoadOptions to the EFI Application
    if (LoadOptionsSize != 0) {
        Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
        if (EFI_ERROR(Status)) {
            return Status;
        }

        LoadedImage->LoadOptionsSize  = LoadOptionsSize;
        LoadedImage->LoadOptions      = LoadOptions;
    }

    // Before calling the image, enable the Watchdog Timer for  the 5 Minute period
    gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
    // Start the image
    Status = gBS->StartImage (ImageHandle, NULL, NULL);
    // Clear the Watchdog Timer after the image returns
    gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);

    return Status;
}
コード例 #2
0
ファイル: BootOptionSupport.c プロジェクト: hzhuang1/uefi
EFI_STATUS
BootDeviceGetType (
  IN  EFI_DEVICE_PATH* DevicePath,
  OUT ARM_BDS_LOADER_TYPE *BootType,
  OUT UINT32 *Attributes
  )
{
  EFI_STATUS              Status;
  BOOLEAN                 IsEfiApp;
  BOOLEAN                 IsBootLoader;
  BOOLEAN                 HasFDTSupport;
  CHAR16*                 FileName;
  EFI_DEVICE_PATH*        PrevDevicePathNode;
  EFI_DEVICE_PATH*        DevicePathNode;
  EFI_PHYSICAL_ADDRESS    Image;
  UINTN                   FileSize;
  EFI_IMAGE_DOS_HEADER*   DosHeader;
  UINTN                   PeCoffHeaderOffset;
  EFI_IMAGE_NT_HEADERS32* NtHeader;

  //
  // Check if the last node of the device path is a FilePath node
  //
  PrevDevicePathNode = NULL;
  DevicePathNode = DevicePath;
  while ((DevicePathNode != NULL) && !IsDevicePathEnd (DevicePathNode)) {
    PrevDevicePathNode = DevicePathNode;
    DevicePathNode = NextDevicePathNode (DevicePathNode);
  }

  if ((PrevDevicePathNode != NULL) &&
      (PrevDevicePathNode->Type == MEDIA_DEVICE_PATH) &&
      (PrevDevicePathNode->SubType == MEDIA_FILEPATH_DP))
  {
    FileName = ((FILEPATH_DEVICE_PATH*)PrevDevicePathNode)->PathName;
  } else {
    FileName = NULL;
  }

  if (FileName == NULL) {
    Print(L"Is an EFI Application? ");
    Status = GetHIInputBoolean (&IsEfiApp);
    if (EFI_ERROR(Status)) {
      return EFI_ABORTED;
    }
  } else if (HasFilePathEfiExtension(FileName)) {
    IsEfiApp = TRUE;
  } else {
    // Check if the file exist
    Status = BdsLoadImage (DevicePath, AllocateAnyPages, &Image, &FileSize);
    if (!EFI_ERROR (Status)) {

      DosHeader = (EFI_IMAGE_DOS_HEADER *)(UINTN) Image;
      if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
        //
        // DOS image header is present,
        // so read the PE header after the DOS image header.
        //
        PeCoffHeaderOffset = DosHeader->e_lfanew;
      } else {
        PeCoffHeaderOffset = 0;
      }

      //
      // Check PE/COFF image.
      //
      NtHeader = (EFI_IMAGE_NT_HEADERS32 *)(UINTN) (Image + PeCoffHeaderOffset);
      if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
        IsEfiApp = FALSE;
      } else {
        IsEfiApp = TRUE;
      }

      // Free memory
      gBS->FreePages (Image, EFI_SIZE_TO_PAGES(FileSize));
    } else {
      // If we did not manage to open it then ask for the type
      Print(L"Is an EFI Application? ");
      Status = GetHIInputBoolean (&IsEfiApp);
      if (EFI_ERROR(Status)) {
        return EFI_ABORTED;
      }
    }
  }

  if (IsEfiApp) {
    Print(L"Is your application an OS loader? ");
    Status = GetHIInputBoolean (&IsBootLoader);
    if (EFI_ERROR(Status)) {
      return EFI_ABORTED;
    }
    if (!IsBootLoader) {
      *Attributes |= LOAD_OPTION_CATEGORY_APP;
    }
    *BootType = BDS_LOADER_EFI_APPLICATION;
  } else {
    Print(L"Has FDT support? ");
    Status = GetHIInputBoolean (&HasFDTSupport);
    if (EFI_ERROR(Status)) {
      return EFI_ABORTED;
    }
    if (HasFDTSupport) {
      *BootType = BDS_LOADER_KERNEL_LINUX_FDT;
    } else {
      *BootType = BDS_LOADER_KERNEL_LINUX_ATAG;
    }
  }

  return EFI_SUCCESS;
}
コード例 #3
0
ファイル: BdsLinuxLoader.c プロジェクト: FishYu1222/edk2
/**
  Start a Linux kernel from a Device Path

  @param  LinuxKernelDevicePath  Device Path to the Linux Kernel
  @param  InitrdDevicePath       Device Path to the Initrd
  @param  CommandLineArguments   Linux command line

  @retval EFI_SUCCESS           All drivers have been connected
  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found
  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.

**/
EFI_STATUS
BdsBootLinuxFdt (
  IN  EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
  IN  EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,
  IN  CONST CHAR8*              CommandLineArguments
  )
{
  EFI_STATUS               Status;
  UINT32                   LinuxImageSize;
  UINT32                   InitrdImageBaseSize = 0;
  UINT32                   InitrdImageSize = 0;
  VOID                     *InstalledFdtBase;
  UINT32                   FdtBlobSize;
  EFI_PHYSICAL_ADDRESS     FdtBlobBase;
  EFI_PHYSICAL_ADDRESS     LinuxImage;
  EFI_PHYSICAL_ADDRESS     InitrdImageBase = 0;
  EFI_PHYSICAL_ADDRESS     InitrdImage = 0;

  PERF_START (NULL, "BDS", NULL, 0);

  // Load the Linux kernel from a device path
  LinuxImage = LINUX_KERNEL_MAX_OFFSET;
  Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);
  if (EFI_ERROR(Status)) {
    Print (L"ERROR: Did not find Linux kernel.\n");
    return Status;
  }

  if (InitrdDevicePath) {
    InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;
    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);
    if (Status == EFI_OUT_OF_RESOURCES) {
      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);
    }
    if (EFI_ERROR(Status)) {
      Print (L"ERROR: Did not find initrd image.\n");
      goto EXIT_FREE_LINUX;
    }

    // Check if the initrd is a uInitrd
    if (*(UINT32*)((UINTN)InitrdImageBase) == LINUX_UIMAGE_SIGNATURE) {
      // Skip the 64-byte image header
      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);
      InitrdImageSize = InitrdImageBaseSize - 64;
    } else {
      InitrdImage = InitrdImageBase;
      InitrdImageSize = InitrdImageBaseSize;
    }
  }

  //
  // Get the FDT from the Configuration Table.
  // The FDT will be reloaded in PrepareFdt() to a more appropriate
  // location for the Linux Kernel.
  //
  Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &InstalledFdtBase);
  if (EFI_ERROR (Status)) {
    Print (L"ERROR: Did not get the Device Tree blob (%r).\n", Status);
    goto EXIT_FREE_INITRD;
  }
  FdtBlobBase = (EFI_PHYSICAL_ADDRESS)(UINTN)InstalledFdtBase;
  FdtBlobSize = fdt_totalsize (InstalledFdtBase);

  // Update the Fdt with the Initrd information. The FDT will increase in size.
  // By setting address=0 we leave the memory allocation to the function
  Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);
  if (EFI_ERROR(Status)) {
    Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status);
    goto EXIT_FREE_FDT;
  }

  return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, ARM_FDT_MACHINE_TYPE);

EXIT_FREE_FDT:
  gBS->FreePages (FdtBlobBase, EFI_SIZE_TO_PAGES (FdtBlobSize));

EXIT_FREE_INITRD:
  if (InitrdDevicePath) {
    gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));
  }

EXIT_FREE_LINUX:
  gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));

  return Status;
}
コード例 #4
0
ファイル: BootLinux.c プロジェクト: binsys/VisualUefi
/**
 * This function check if the DevicePath defines an EFI binary
 *
 * This function is used when the BDS support Linux loader to
 * detect if the binary is an EFI application or potentially a
 * Linux kernel.
 */
EFI_STATUS
IsEfiBinary (
  IN  EFI_DEVICE_PATH* DevicePath,
  OUT BOOLEAN          *EfiBinary
  )
{
  EFI_STATUS              Status;
  CHAR16*                 FileName;
  EFI_DEVICE_PATH*        PrevDevicePathNode;
  EFI_DEVICE_PATH*        DevicePathNode;
  EFI_PHYSICAL_ADDRESS    Image;
  UINTN                   FileSize;
  EFI_IMAGE_DOS_HEADER*   DosHeader;
  UINTN                   PeCoffHeaderOffset;
  EFI_IMAGE_NT_HEADERS32* NtHeader;

  ASSERT (EfiBinary != NULL);

  //
  // Check if the last node of the device path is a FilePath node
  //
  PrevDevicePathNode = NULL;
  DevicePathNode = DevicePath;
  while ((DevicePathNode != NULL) && !IsDevicePathEnd (DevicePathNode)) {
    PrevDevicePathNode = DevicePathNode;
    DevicePathNode     = NextDevicePathNode (DevicePathNode);
  }

  if ((PrevDevicePathNode != NULL) &&
      (PrevDevicePathNode->Type == MEDIA_DEVICE_PATH) &&
      (PrevDevicePathNode->SubType == MEDIA_FILEPATH_DP))
  {
    FileName = ((FILEPATH_DEVICE_PATH*)PrevDevicePathNode)->PathName;
  } else {
    FileName = NULL;
  }

  if (FileName == NULL) {
    Print (L"Is an EFI Application? ");
    Status = GetHIInputBoolean (EfiBinary);
    if (EFI_ERROR (Status)) {
      return EFI_ABORTED;
    }
  } else if (HasFilePathEfiExtension (FileName)) {
    *EfiBinary = TRUE;
  } else {
    // Check if the file exist
    Status = BdsLoadImage (DevicePath, AllocateAnyPages, &Image, &FileSize);
    if (!EFI_ERROR (Status)) {

      DosHeader = (EFI_IMAGE_DOS_HEADER *)(UINTN) Image;
      if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
        //
        // DOS image header is present,
        // so read the PE header after the DOS image header.
        //
        PeCoffHeaderOffset = DosHeader->e_lfanew;
      } else {
        PeCoffHeaderOffset = 0;
      }

      //
      // Check PE/COFF image.
      //
      NtHeader = (EFI_IMAGE_NT_HEADERS32 *)(UINTN) (Image + PeCoffHeaderOffset);
      if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
        *EfiBinary = FALSE;
      } else {
        *EfiBinary = TRUE;
      }

      // Free memory
      gBS->FreePages (Image, EFI_SIZE_TO_PAGES (FileSize));
    } else {
      // If we did not manage to open it then ask for the type
      Print (L"Is an EFI Application? ");
      Status = GetHIInputBoolean (EfiBinary);
      if (EFI_ERROR (Status)) {
        return EFI_ABORTED;
      }
    }
  }

  return EFI_SUCCESS;
}
コード例 #5
0
ファイル: BdsLinuxLoader.c プロジェクト: FishYu1222/edk2
/**
  Start a Linux kernel from a Device Path

  @param  LinuxKernel           Device Path to the Linux Kernel
  @param  Parameters            Linux kernel arguments
  @param  Fdt                   Device Path to the Flat Device Tree

  @retval EFI_SUCCESS           All drivers have been connected
  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found
  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.

**/
EFI_STATUS
BdsBootLinuxAtag (
  IN  EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
  IN  EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,
  IN  CONST CHAR8*              CommandLineArguments
  )
{
  EFI_STATUS            Status;
  UINT32                LinuxImageSize;
  UINT32                InitrdImageBaseSize = 0;
  UINT32                InitrdImageSize = 0;
  UINT32                AtagSize;
  EFI_PHYSICAL_ADDRESS  AtagBase;
  EFI_PHYSICAL_ADDRESS  LinuxImage;
  EFI_PHYSICAL_ADDRESS  InitrdImageBase = 0;
  EFI_PHYSICAL_ADDRESS  InitrdImage = 0;

  PERF_START (NULL, "BDS", NULL, 0);

  // Load the Linux kernel from a device path
  LinuxImage = LINUX_KERNEL_MAX_OFFSET;
  Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);
  if (EFI_ERROR(Status)) {
    Print (L"ERROR: Did not find Linux kernel.\n");
    return Status;
  }

  if (InitrdDevicePath) {
    // Load the initrd near to the Linux kernel
    InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;
    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);
    if (Status == EFI_OUT_OF_RESOURCES) {
      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);
    }
    if (EFI_ERROR(Status)) {
      Print (L"ERROR: Did not find initrd image.\n");
      goto EXIT_FREE_LINUX;
    }

    // Check if the initrd is a uInitrd
    if (*(UINT32*)((UINTN)InitrdImageBase) == LINUX_UIMAGE_SIGNATURE) {
      // Skip the 64-byte image header
      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);
      InitrdImageSize = InitrdImageBaseSize - 64;
    } else {
      InitrdImage = InitrdImageBase;
      InitrdImageSize = InitrdImageBaseSize;
    }
  }

  //
  // Setup the Linux Kernel Parameters
  //

  // By setting address=0 we leave the memory allocation to the function
  Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);
  if (EFI_ERROR(Status)) {
    Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);
    goto EXIT_FREE_INITRD;
  }

  return StartLinux (LinuxImage, LinuxImageSize, AtagBase, AtagSize, PcdGet32(PcdArmMachineType));

EXIT_FREE_INITRD:
  if (InitrdDevicePath) {
    gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));
  }

EXIT_FREE_LINUX:
  gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));

  return Status;
}