Example #1
0
BOOLEAN
BdsTftpSupport (
    IN EFI_DEVICE_PATH*           DevicePath,
    IN EFI_HANDLE                 Handle,
    IN EFI_DEVICE_PATH*           RemainingDevicePath
)
{
    EFI_STATUS  Status;
    EFI_DEVICE_PATH  *NextDevicePath;
    EFI_PXE_BASE_CODE_PROTOCOL  *PxeBcProtocol;

    // Validate the Remaining Device Path
    if (IsDevicePathEnd(RemainingDevicePath)) {
        return FALSE;
    }
    if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) &&
            !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) {
        return FALSE;
    }
    NextDevicePath = NextDevicePathNode (RemainingDevicePath);
    if (IsDevicePathEnd(NextDevicePath)) {
        return FALSE;
    }
    if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) {
        return FALSE;
    }

    Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);
    if (EFI_ERROR (Status)) {
        return FALSE;
    } else {
        return TRUE;
    }
}
Example #2
0
BOOLEAN
BdsMemoryMapSupport (
    IN EFI_DEVICE_PATH *DevicePath,
    IN EFI_HANDLE Handle,
    IN EFI_DEVICE_PATH *RemainingDevicePath
)
{
    return IS_DEVICE_PATH_NODE(DevicePath,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP) ||
           IS_DEVICE_PATH_NODE(RemainingDevicePath,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP);
}
Example #3
0
BOOLEAN
BdsTftpSupport (
  IN EFI_DEVICE_PATH  *DevicePath,
  IN EFI_HANDLE       Handle,
  IN EFI_DEVICE_PATH  *RemainingDevicePath
  )
{
  EFI_STATUS       Status;
  EFI_DEVICE_PATH  *NextDevicePath;
  VOID             *Interface;

  // Validate the Remaining Device Path
  if (IsDevicePathEnd (RemainingDevicePath)) {
    return FALSE;
  }
  if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP) &&
      !IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv6_DP)) {
    return FALSE;
  }
  NextDevicePath = NextDevicePathNode (RemainingDevicePath);
  if (IsDevicePathEnd (NextDevicePath)) {
    return FALSE;
  }
  if (!IS_DEVICE_PATH_NODE (NextDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)) {
    return FALSE;
  }

  Status = gBS->HandleProtocol (
                  Handle, &gEfiDevicePathProtocolGuid,
                  &Interface
                  );
  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  //
  // Check that the controller (identified by its handle "Handle") supports the
  // MTFTPv4 Service Binding Protocol. If it does, it means that it supports the
  // EFI MTFTPv4 Protocol needed to download the image through TFTP.
  //
  Status = gBS->HandleProtocol (
                  Handle, &gEfiMtftp4ServiceBindingProtocolGuid,
                  &Interface
                  );
  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  return TRUE;
}
Example #4
0
/**
  Check if a boot option path is a memory map boot option path or not.

  The device specified by the beginning of the path has to support the BlockIo
  protocol. Furthermore, the remaining part of the path has to be composed of
  a single node of type HARDWARE_DEVICE_PATH and sub-type HW_MEMMAP_DP.

  @param[in]  DevicePath  Complete device path of a boot option.

  @retval  FALSE  The boot option path has not been identified as that of a
                  memory map boot option.
  @retval  TRUE   The boot option path is a a memory map boot option.
**/
BOOLEAN
BdsLoadOptionMemMapIsSupported (
  IN  EFI_DEVICE_PATH  *DevicePath
  )
{
  EFI_STATUS              Status;
  EFI_HANDLE              Handle;
  EFI_DEVICE_PATH        *RemainingDevicePath;
  EFI_BLOCK_IO_PROTOCOL  *BlockIoProtocol;

  Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);
  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  Status = gBS->HandleProtocol (
                  Handle,
                  &gEfiBlockIoProtocolGuid,
                  (VOID **)(&BlockIoProtocol)
                  );
  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP))
    return FALSE;

  return TRUE;
}
Example #5
0
/**
  Check if a boot option path is a file system boot option path or not.

  The device specified by the beginning of the path has to support the Simple File
  System protocol. Furthermore, the remaining part of the path has to be composed of
  a single node of type MEDIA_DEVICE_PATH and sub-type MEDIA_FILEPATH_DP.

  @param[in]  DevicePath  Complete device path of a boot option.

  @retval  FALSE  The boot option path has not been identified as that of a
                  file system boot option.
  @retval  TRUE   The boot option path is a file system boot option.
**/
BOOLEAN
BdsLoadOptionFileSystemIsSupported (
  IN  EFI_DEVICE_PATH  *DevicePath
  )
{
  EFI_STATUS                        Status;
  EFI_HANDLE                        Handle;
  EFI_DEVICE_PATH                  *RemainingDevicePath;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FileProtocol;

  Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);
  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  Status = gBS->HandleProtocol (
                   Handle,
                   &gEfiSimpleFileSystemProtocolGuid,
                   (VOID **)(&FileProtocol)
                   );
  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP))
    return FALSE;

  return TRUE;
}
Example #6
0
BOOLEAN
BdsIsRemovableHd (
    IN  EFI_DEVICE_PATH*  DevicePath
)
{
    return IS_DEVICE_PATH_NODE(DevicePath, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP);
}
Example #7
0
BOOLEAN
BdsFirmwareVolumeSupport (
    IN EFI_DEVICE_PATH *DevicePath,
    IN EFI_HANDLE Handle,
    IN EFI_DEVICE_PATH *RemainingDevicePath
)
{
    return IS_DEVICE_PATH_NODE(RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP);
}
Example #8
0
EFI_STATUS
BdsMemoryMapLoadImage (
    IN     EFI_DEVICE_PATH *DevicePath,
    IN     EFI_HANDLE Handle,
    IN     EFI_DEVICE_PATH *RemainingDevicePath,
    IN     EFI_ALLOCATE_TYPE     Type,
    IN OUT EFI_PHYSICAL_ADDRESS* Image,
    OUT    UINTN                 *ImageSize
)
{
    EFI_STATUS            Status;
    MEMMAP_DEVICE_PATH*   MemMapPathDevicePath;
    UINTN                 Size;

    if (IS_DEVICE_PATH_NODE(RemainingDevicePath,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP)) {
        MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)RemainingDevicePath;
    } else {
        ASSERT (IS_DEVICE_PATH_NODE(DevicePath,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP));
        MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)DevicePath;
    }

    Size = MemMapPathDevicePath->EndingAddress - MemMapPathDevicePath->StartingAddress;
    if (Size == 0) {
        return EFI_INVALID_PARAMETER;
    }

    Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);
    // Try to allocate in any pages if failed to allocate memory at the defined location
    if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {
        Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);
    }
    if (!EFI_ERROR(Status)) {
        CopyMem ((VOID*)(UINTN)(*Image), (CONST VOID*)(UINTN)MemMapPathDevicePath->StartingAddress, Size);

        if (ImageSize != NULL) {
            *ImageSize = Size;
        }
    }

    return Status;
}
Example #9
0
BOOLEAN
BdsFileSystemSupport (
    IN EFI_DEVICE_PATH *DevicePath,
    IN EFI_HANDLE Handle,
    IN EFI_DEVICE_PATH *RemainingDevicePath
)
{
    EFI_STATUS  Status;
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *FsProtocol;

    Status = gBS->HandleProtocol (Handle,&gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);

    return (!EFI_ERROR(Status) && IS_DEVICE_PATH_NODE(RemainingDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP));
}
Example #10
0
/**
  Update the parameters of a TFTP boot option

  The function asks sequentially to update the IPv4 parameters as well as the boot file path,
  providing the previously set value if any.

  @param[in]   OldDevicePath  Current complete device path of the Tftp boot option.
                              This has to be a valid complete Tftp boot option path.
                              By complete, we mean that it is not only the Tftp
                              specific end part built by the
                              "BdsLoadOptionTftpCreateDevicePath()" function.
                              This path is handled as read only.
  @param[in]   FileName       Description of the file the path is asked for
  @param[out]  NewDevicePath  Pointer to the new complete device path.

  @retval  EFI_SUCCESS            Update completed
  @retval  EFI_ABORTED            Update aborted by the user
  @retval  EFI_OUT_OF_RESOURCES   Fail to perform the update due to lack of resource
**/
EFI_STATUS
BdsLoadOptionTftpUpdateDevicePath (
  IN   EFI_DEVICE_PATH            *OldDevicePath,
  IN   CHAR16                     *FileName,
  OUT  EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
  )
{
  EFI_STATUS             Status;
  EFI_DEVICE_PATH       *DevicePath;
  EFI_DEVICE_PATH       *DevicePathNode;
  UINT8                 *Ipv4NodePtr;
  IPv4_DEVICE_PATH       Ipv4Node;
  BOOLEAN                IsDHCP;
  EFI_IP_ADDRESS         OldIp;
  EFI_IP_ADDRESS         OldSubnetMask;
  EFI_IP_ADDRESS         OldGatewayIp;
  EFI_IP_ADDRESS         LocalIp;
  EFI_IP_ADDRESS         SubnetMask;
  EFI_IP_ADDRESS         GatewayIp;
  EFI_IP_ADDRESS         RemoteIp;
  UINT8                 *FileNodePtr;
  CHAR16                 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];
  UINTN                  PathSize;
  UINTN                  BootFilePathSize;
  FILEPATH_DEVICE_PATH  *NewFilePathNode;

  Ipv4NodePtr = NULL;

  //
  // Make a copy of the complete device path that is made of :
  // the device path of the device that support the Simple Network protocol
  // followed by an IPv4 node (type IPv4_DEVICE_PATH),
  // followed by a file path node (type FILEPATH_DEVICE_PATH) and ended up
  // by an end node. The IPv6 case is not handled yet.
  //

  DevicePath = DuplicateDevicePath (OldDevicePath);
  if (DevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ErrorExit;
  }

  //
  // Because of the check done by "BdsLoadOptionTftpIsSupported()" prior to the
  // call to this function, we know that the device path ends with an IPv4 node
  // followed by a file path node and finally an end node. To get the address of
  // the last IPv4 node, we loop over the whole device path, noting down the
  // address of each encountered IPv4 node.
  //

  for (DevicePathNode = DevicePath;
       !IsDevicePathEnd (DevicePathNode);
       DevicePathNode = NextDevicePathNode (DevicePathNode))
  {
    if (IS_DEVICE_PATH_NODE (DevicePathNode, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)) {
      Ipv4NodePtr = (UINT8*)DevicePathNode;
    }
  }

  // Copy for alignment of the IPv4 node data
  CopyMem (&Ipv4Node, Ipv4NodePtr, sizeof (IPv4_DEVICE_PATH));

  Print (L"Get the IP address from DHCP: ");
  Status = GetHIInputBoolean (&IsDHCP);
  if (EFI_ERROR (Status)) {
    goto ErrorExit;
  }

  if (!IsDHCP) {
    Print (L"Local static IP address: ");
    if (Ipv4Node.StaticIpAddress) {
      CopyMem (&OldIp.v4, &Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
      Status = EditHIInputIP (&OldIp, &LocalIp);
    } else {
      Status = GetHIInputIP (&LocalIp);
    }
    if (EFI_ERROR (Status)) {
      goto ErrorExit;
    }

    Print (L"Get the network mask: ");
    if (Ipv4Node.StaticIpAddress) {
      CopyMem (&OldSubnetMask.v4, &Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
      Status = EditHIInputIP (&OldSubnetMask, &SubnetMask);
    } else {
      Status = GetHIInputIP (&SubnetMask);
    }
    if (EFI_ERROR (Status)) {
      goto ErrorExit;
    }

    Print (L"Get the gateway IP address: ");
    if (Ipv4Node.StaticIpAddress) {
      CopyMem (&OldGatewayIp.v4, &Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));
      Status = EditHIInputIP (&OldGatewayIp, &GatewayIp);
    } else {
      Status = GetHIInputIP (&GatewayIp);
    }
    if (EFI_ERROR (Status)) {
      goto ErrorExit;
    }
  }

  Print (L"TFTP server IP address: ");
  // Copy remote IPv4 address into IPv4 or IPv6 union
  CopyMem (&OldIp.v4, &Ipv4Node.RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));

  Status = EditHIInputIP (&OldIp, &RemoteIp);
  if (EFI_ERROR (Status)) {
    goto ErrorExit;
  }

  // Get the path of the boot file and its size in number of bytes
  FileNodePtr = Ipv4NodePtr + sizeof (IPv4_DEVICE_PATH);
  BootFilePathSize = DevicePathNodeLength (FileNodePtr) - SIZE_OF_FILEPATH_DEVICE_PATH;

  //
  // Ask for update of the boot file path
  //
  do {
    // Copy for 2-byte alignment of the Unicode string
    CopyMem (
      BootFilePath, FileNodePtr + SIZE_OF_FILEPATH_DEVICE_PATH,
      MIN (BootFilePathSize, BOOT_DEVICE_FILEPATH_MAX)
      );
    BootFilePath[BOOT_DEVICE_FILEPATH_MAX - 1] = L'\0';

    Print (L"File path of the %s: ", FileName);
    Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);
    if (EFI_ERROR (Status)) {
      goto ErrorExit;
    }
    PathSize = StrSize (BootFilePath);
    if (PathSize > 2) {
      break;
    }
    // Empty string, give the user another try
    Print (L"Empty string - Invalid path\n");
  } while (PathSize <= 2) ;

  //
  // Update the IPv4 node. IPv6 case not handled yet.
  //
  if (IsDHCP) {
    Ipv4Node.StaticIpAddress = FALSE;
    ZeroMem (&Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
    ZeroMem (&Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
    ZeroMem (&Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));
  } else {
    Ipv4Node.StaticIpAddress = TRUE;
    CopyMem (&Ipv4Node.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Ipv4Node.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Ipv4Node.GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));
  }

  CopyMem (&Ipv4Node.RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));
  CopyMem (Ipv4NodePtr, &Ipv4Node, sizeof (IPv4_DEVICE_PATH));

  //
  // Create the new file path node
  //
  NewFilePathNode = (FILEPATH_DEVICE_PATH*)AllocatePool (
                                             SIZE_OF_FILEPATH_DEVICE_PATH +
                                             PathSize
                                             );
  NewFilePathNode->Header.Type    = MEDIA_DEVICE_PATH;
  NewFilePathNode->Header.SubType = MEDIA_FILEPATH_DP;
  SetDevicePathNodeLength (
    NewFilePathNode,
    SIZE_OF_FILEPATH_DEVICE_PATH + PathSize
    );
  CopyMem (NewFilePathNode->PathName, BootFilePath, PathSize);

  //
  // Generate the new Device Path by replacing the file path node at address
  // "FileNodePtr" by the new one "NewFilePathNode" and return its address.
  //
  SetDevicePathEndNode (FileNodePtr);
  *NewDevicePath = AppendDevicePathNode (
                     DevicePath,
                     (CONST EFI_DEVICE_PATH_PROTOCOL*)NewFilePathNode
                     );

ErrorExit:
  if (DevicePath != NULL) {
    FreePool (DevicePath) ;
  }

  return Status;
}
Example #11
0
EFI_STATUS
BdsTftpLoadImage (
    IN     EFI_DEVICE_PATH*       DevicePath,
    IN     EFI_HANDLE             Handle,
    IN     EFI_DEVICE_PATH*       RemainingDevicePath,
    IN     EFI_ALLOCATE_TYPE      Type,
    IN OUT EFI_PHYSICAL_ADDRESS   *Image,
    OUT    UINTN                  *ImageSize
)
{
    EFI_STATUS                  Status;
    EFI_PXE_BASE_CODE_PROTOCOL  *Pxe;
    UINT64                      TftpBufferSize;
    VOID*                       TftpBuffer;
    EFI_IP_ADDRESS              ServerIp;
    IPv4_DEVICE_PATH*           IPv4DevicePathNode;
    FILEPATH_DEVICE_PATH*       FilePathDevicePath;
    EFI_IP_ADDRESS              LocalIp;

    ASSERT(IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP));

    IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;
    FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);

    Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
    if (EFI_ERROR(Status)) {
        return Status;
    }

    Status = Pxe->Start (Pxe, FALSE);
    if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
        return Status;
    }

    if (!IPv4DevicePathNode->StaticIpAddress) {
        Status = Pxe->Dhcp(Pxe, TRUE);
    } else {
        CopyMem (&LocalIp.v4, &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
        Status = Pxe->SetStationIp (Pxe, &LocalIp, NULL);
    }
    if (EFI_ERROR(Status)) {
        return Status;
    }

    CopyMem (&ServerIp.v4, &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));

    Status = Pxe->Mtftp (
                 Pxe,
                 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
                 NULL,
                 FALSE,
                 &TftpBufferSize,
                 NULL,
                 &ServerIp,
                 (UINT8 *)FilePathDevicePath->PathName,
                 NULL,
                 TRUE
             );
    if (EFI_ERROR(Status)) {
        return Status;
    }

    // Allocate a buffer to hold the whole file.
    TftpBuffer = AllocatePool(TftpBufferSize);
    if (TftpBuffer == NULL) {
        return EFI_OUT_OF_RESOURCES;
    }

    Status = Pxe->Mtftp (
                 Pxe,
                 EFI_PXE_BASE_CODE_TFTP_READ_FILE,
                 TftpBuffer,
                 FALSE,
                 &TftpBufferSize,
                 NULL,
                 &ServerIp,
                 (UINT8 *)FilePathDevicePath->PathName,
                 NULL,
                 FALSE
             );
    if (EFI_ERROR(Status)) {
        FreePool(TftpBuffer);
    } else if (ImageSize != NULL) {
        *ImageSize = (UINTN)TftpBufferSize;
    }

    return Status;
}
Example #12
0
EFI_STATUS
BdsFirmwareVolumeLoadImage (
    IN     EFI_DEVICE_PATH *DevicePath,
    IN     EFI_HANDLE Handle,
    IN     EFI_DEVICE_PATH *RemainingDevicePath,
    IN     EFI_ALLOCATE_TYPE     Type,
    IN OUT EFI_PHYSICAL_ADDRESS* Image,
    OUT    UINTN                 *ImageSize
)
{
    EFI_STATUS            Status;
    EFI_FIRMWARE_VOLUME2_PROTOCOL     *FwVol;
    EFI_GUID                          *FvNameGuid;
    EFI_SECTION_TYPE                  SectionType;
    EFI_FV_FILETYPE                   FvType;
    EFI_FV_FILE_ATTRIBUTES            Attrib;
    UINT32                            AuthenticationStatus;
    VOID* ImageBuffer;

    ASSERT (IS_DEVICE_PATH_NODE(RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP));

    Status = gBS->HandleProtocol(Handle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FwVol);
    if (EFI_ERROR(Status)) {
        return Status;
    }

    FvNameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)RemainingDevicePath);
    if (FvNameGuid == NULL) {
        Status = EFI_INVALID_PARAMETER;
    }

    SectionType = EFI_SECTION_PE32;
    AuthenticationStatus = 0;
    //Note: ReadSection at the opposite of ReadFile does not allow to pass ImageBuffer == NULL to get the size of the file.
    ImageBuffer = NULL;
    Status = FwVol->ReadSection (
                 FwVol,
                 FvNameGuid,
                 SectionType,
                 0,
                 &ImageBuffer,
                 ImageSize,
                 &AuthenticationStatus
             );
    if (!EFI_ERROR (Status)) {
#if 0
        // In case the buffer has some address requirements, we must copy the buffer to a buffer following the requirements
        if (Type != AllocateAnyPages) {
            Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize),Image);
            if (!EFI_ERROR(Status)) {
                CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize);
                FreePool (ImageBuffer);
            }
        }
#else
        // We must copy the buffer into a page allocations. Otherwise, the caller could call gBS->FreePages() on the pool allocation
        Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);
        // Try to allocate in any pages if failed to allocate memory at the defined location
        if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {
            Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);
        }
        if (!EFI_ERROR(Status)) {
            CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize);
            FreePool (ImageBuffer);
        }
#endif
    } else {
        // Try a raw file, since a PE32 SECTION does not exist
        Status = FwVol->ReadFile (
                     FwVol,
                     FvNameGuid,
                     NULL,
                     ImageSize,
                     &FvType,
                     &Attrib,
                     &AuthenticationStatus
                 );
        if (!EFI_ERROR(Status)) {
            Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);
            // Try to allocate in any pages if failed to allocate memory at the defined location
            if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {
                Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);
            }
            if (!EFI_ERROR(Status)) {
                Status = FwVol->ReadFile (
                             FwVol,
                             FvNameGuid,
                             (VOID*)(UINTN)(*Image),
                             ImageSize,
                             &FvType,
                             &Attrib,
                             &AuthenticationStatus
                         );
            }
        }
    }
    return Status;
}
Example #13
0
EFI_STATUS
BdsFileSystemLoadImage (
    IN     EFI_DEVICE_PATH *DevicePath,
    IN     EFI_HANDLE Handle,
    IN     EFI_DEVICE_PATH *RemainingDevicePath,
    IN     EFI_ALLOCATE_TYPE     Type,
    IN OUT EFI_PHYSICAL_ADDRESS* Image,
    OUT    UINTN                 *ImageSize
)
{
    FILEPATH_DEVICE_PATH*             FilePathDevicePath;
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *FsProtocol;
    EFI_FILE_PROTOCOL                   *Fs;
    EFI_STATUS Status;
    EFI_FILE_INFO       *FileInfo;
    EFI_FILE_PROTOCOL   *File;
    UINTN               Size;

    ASSERT (IS_DEVICE_PATH_NODE(RemainingDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP));

    FilePathDevicePath = (FILEPATH_DEVICE_PATH*)RemainingDevicePath;

    Status = gBS->HandleProtocol(Handle,&gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);
    if (EFI_ERROR(Status)) {
        return Status;
    }

    // Try to Open the volume and get root directory
    Status = FsProtocol->OpenVolume (FsProtocol, &Fs);
    if (EFI_ERROR(Status)) {
        return Status;
    }

    File = NULL;
    Status = Fs->Open(Fs, &File, FilePathDevicePath->PathName, EFI_FILE_MODE_READ, 0);
    if (EFI_ERROR(Status)) {
        return Status;
    }

    Size = 0;
    File->GetInfo(File, &gEfiFileInfoGuid, &Size, NULL);
    FileInfo = AllocatePool (Size);
    Status = File->GetInfo(File, &gEfiFileInfoGuid, &Size, FileInfo);
    if (EFI_ERROR(Status)) {
        return Status;
    }

    // Get the file size
    Size = FileInfo->FileSize;
    if (ImageSize) {
        *ImageSize = Size;
    }
    FreePool(FileInfo);

    Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);
    // Try to allocate in any pages if failed to allocate memory at the defined location
    if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {
        Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);
    }
    if (!EFI_ERROR(Status)) {
        Status = File->Read (File, &Size, (VOID*)(UINTN)(*Image));
    }

    return Status;
}
Example #14
0
/**
  Download an image from a TFTP server

  @param[in]   DevicePath           Device path of the TFTP boot option
  @param[in]   ControllerHandle     Handle of the network controller
  @param[in]   RemainingDevicePath  Device path of the TFTP boot option but
                                    the first node that identifies the network controller
  @param[in]   Type                 Type to allocate memory pages
  @param[out]  Image                Address of the bufer where the image is stored in
                                    case of success
  @param[out]  ImageSize            Size in number of bytes of the i;age in case of
                                    success

  @retval  EFI_SUCCESS   The image was returned.
  @retval  !EFI_SUCCESS  Something went wrong.

**/
EFI_STATUS
BdsTftpLoadImage (
  IN OUT EFI_DEVICE_PATH       **DevicePath,
  IN     EFI_HANDLE            ControllerHandle,
  IN     EFI_DEVICE_PATH       *RemainingDevicePath,
  IN     EFI_ALLOCATE_TYPE     Type,
  IN OUT EFI_PHYSICAL_ADDRESS  *Image,
  OUT    UINTN                 *ImageSize
  )
{
  EFI_STATUS               Status;
  EFI_HANDLE               Dhcp4ChildHandle;
  EFI_DHCP4_PROTOCOL       *Dhcp4;
  BOOLEAN                  Dhcp4ToStop;
  EFI_HANDLE               Mtftp4ChildHandle;
  EFI_MTFTP4_PROTOCOL      *Mtftp4;
  DHCP4_OPTION             ParaList;
  EFI_DHCP4_PACKET_OPTION  *OptionList[2];
  EFI_DHCP4_CONFIG_DATA    Dhcp4CfgData;
  EFI_DHCP4_MODE_DATA      Dhcp4Mode;
  EFI_MTFTP4_CONFIG_DATA   Mtftp4CfgData;
  IPv4_DEVICE_PATH         *IPv4DevicePathNode;
  FILEPATH_DEVICE_PATH     *FilePathDevicePathNode;
  CHAR8                    *AsciiFilePath;
  EFI_MTFTP4_TOKEN         Mtftp4Token;
  UINT64                   FileSize;
  UINT64                   TftpBufferSize;
  BDS_TFTP_CONTEXT         *TftpContext;

  ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP));
  IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;

  Dhcp4ChildHandle  = NULL;
  Dhcp4             = NULL;
  Dhcp4ToStop       = FALSE;
  Mtftp4ChildHandle = NULL;
  Mtftp4            = NULL;
  AsciiFilePath     = NULL;
  TftpContext       = NULL;

  if (!IPv4DevicePathNode->StaticIpAddress) {
    //
    // Using the DHCP4 Service Binding Protocol, create a child handle of the DHCP4 service and
    // install the DHCP4 protocol on it. Then, open the DHCP protocol.
    //
    Status = NetLibCreateServiceChild (
               ControllerHandle,
               gImageHandle,
               &gEfiDhcp4ServiceBindingProtocolGuid,
               &Dhcp4ChildHandle
               );
    if (!EFI_ERROR (Status)) {
      Status = gBS->OpenProtocol (
                      Dhcp4ChildHandle,
                      &gEfiDhcp4ProtocolGuid,
                      (VOID **) &Dhcp4,
                      gImageHandle,
                      ControllerHandle,
                      EFI_OPEN_PROTOCOL_BY_DRIVER
                      );
    }
    if (EFI_ERROR (Status)) {
      Print (L"Unable to open DHCP4 protocol\n");
      goto Error;
    }
  }

  //
  // Using the MTFTP4 Service Binding Protocol, create a child handle of the MTFTP4 service and
  // install the MTFTP4 protocol on it. Then, open the MTFTP4 protocol.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             gImageHandle,
             &gEfiMtftp4ServiceBindingProtocolGuid,
             &Mtftp4ChildHandle
             );
  if (!EFI_ERROR (Status)) {
    Status = gBS->OpenProtocol (
                    Mtftp4ChildHandle,
                    &gEfiMtftp4ProtocolGuid,
                    (VOID **) &Mtftp4,
                    gImageHandle,
                    ControllerHandle,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
  }
  if (EFI_ERROR (Status)) {
    Print (L"Unable to open MTFTP4 protocol\n");
    goto Error;
  }

  if (!IPv4DevicePathNode->StaticIpAddress) {
    //
    // Configure the DHCP4, all default settings. It is acceptable for the configuration to
    // fail if the return code is equal to EFI_ACCESS_DENIED which means that the configuration
    // has been done by another instance of the DHCP4 protocol or that the DHCP configuration
    // process has been started but is not completed yet.
    //
    ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));
    ParaList.Head.OpCode     = DHCP_TAG_PARA_LIST;
    ParaList.Head.Length     = 2;
    ParaList.Head.Data[0]    = DHCP_TAG_NETMASK;
    ParaList.Route           = DHCP_TAG_ROUTER;
    OptionList[0]            = &ParaList.Head;
    Dhcp4CfgData.OptionCount = 1;
    Dhcp4CfgData.OptionList  = OptionList;

    Status = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);
    if (EFI_ERROR (Status)) {
      if (Status != EFI_ACCESS_DENIED) {
        Print (L"Error while configuring the DHCP4 protocol\n");
        goto Error;
      }
    }

    //
    // Start the DHCP configuration. This may have already been done thus do not leave in error
    // if the return code is EFI_ALREADY_STARTED.
    //
    Status = Dhcp4->Start (Dhcp4, NULL);
    if (EFI_ERROR (Status)) {
      if (Status != EFI_ALREADY_STARTED) {
        Print (L"DHCP configuration failed\n");
        goto Error;
      }
    } else {
      Dhcp4ToStop = TRUE;
    }

    Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
    if (EFI_ERROR (Status)) {
      goto Error;
    }

    if (Dhcp4Mode.State != Dhcp4Bound) {
      Status = EFI_TIMEOUT;
      Print (L"DHCP configuration failed\n");
      goto Error;
    }
  }

  //
  // Configure the TFTP4 protocol
  //

  ZeroMem (&Mtftp4CfgData, sizeof (EFI_MTFTP4_CONFIG_DATA));
  Mtftp4CfgData.UseDefaultSetting = FALSE;
  Mtftp4CfgData.TimeoutValue      = 4;
  Mtftp4CfgData.TryCount          = 6;

  if (IPv4DevicePathNode->StaticIpAddress) {
    CopyMem (&Mtftp4CfgData.StationIp , &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.SubnetMask, &IPv4DevicePathNode->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.GatewayIp , &IPv4DevicePathNode->GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));
  } else {
    CopyMem (&Mtftp4CfgData.StationIp , &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.SubnetMask, &Dhcp4Mode.SubnetMask   , sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.GatewayIp , &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
  }

  CopyMem (&Mtftp4CfgData.ServerIp  , &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));

  Status = Mtftp4->Configure (Mtftp4, &Mtftp4CfgData);
  if (EFI_ERROR (Status)) {
    Print (L"Error while configuring the MTFTP4 protocol\n");
    goto Error;
  }

  //
  // Convert the Unicode path of the file to Ascii
  //

  FilePathDevicePathNode = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);
  AsciiFilePath = AllocatePool ((StrLen (FilePathDevicePathNode->PathName) + 1) * sizeof (CHAR8));
  if (AsciiFilePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }
  UnicodeStrToAsciiStr (FilePathDevicePathNode->PathName, AsciiFilePath);

  //
  // Try to get the size of the file in bytes from the server. If it fails,
  // start with a 8MB buffer to download the file.
  //
  FileSize = 0;
  if (Mtftp4GetFileSize (Mtftp4, AsciiFilePath, &FileSize) == EFI_SUCCESS) {
    TftpBufferSize = FileSize;
  } else {
    TftpBufferSize = SIZE_8MB;
  }

  TftpContext = AllocatePool (sizeof (BDS_TFTP_CONTEXT));
  if (TftpContext == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }
  TftpContext->FileSize = FileSize;

  for (; TftpBufferSize <= FixedPcdGet32 (PcdMaxTftpFileSize);
         TftpBufferSize = (TftpBufferSize + SIZE_8MB) & (~(SIZE_8MB-1))) {
    //
    // Allocate a buffer to hold the whole file.
    //
    Status = gBS->AllocatePages (
                    Type,
                    EfiBootServicesCode,
                    EFI_SIZE_TO_PAGES (TftpBufferSize),
                    Image
                    );
    if (EFI_ERROR (Status)) {
      Print (L"Failed to allocate space for image\n");
      goto Error;
    }

    TftpContext->DownloadedNbOfBytes   = 0;
    TftpContext->LastReportedNbOfBytes = 0;

    ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));
    Mtftp4Token.Filename    = (UINT8*)AsciiFilePath;
    Mtftp4Token.BufferSize  = TftpBufferSize;
    Mtftp4Token.Buffer      = (VOID *)(UINTN)*Image;
    Mtftp4Token.CheckPacket = Mtftp4CheckPacket;
    Mtftp4Token.Context     = (VOID*)TftpContext;

    Print (L"Downloading the file <%s> from the TFTP server\n", FilePathDevicePathNode->PathName);
    Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);
    Print (L"\n");
    if (EFI_ERROR (Status)) {
      gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));
      if (Status == EFI_BUFFER_TOO_SMALL) {
        Print (L"Downloading failed, file larger than expected.\n");
        continue;
      } else {
        goto Error;
      }
    }

    *ImageSize = Mtftp4Token.BufferSize;
    break;
  }

Error:
  if (Dhcp4ChildHandle != NULL) {
    if (Dhcp4 != NULL) {
      if (Dhcp4ToStop) {
        Dhcp4->Stop (Dhcp4);
      }
      gBS->CloseProtocol (
             Dhcp4ChildHandle,
             &gEfiDhcp4ProtocolGuid,
             gImageHandle,
             ControllerHandle
            );
    }
    NetLibDestroyServiceChild (
      ControllerHandle,
      gImageHandle,
      &gEfiDhcp4ServiceBindingProtocolGuid,
      Dhcp4ChildHandle
      );
  }

  if (Mtftp4ChildHandle != NULL) {
    if (Mtftp4 != NULL) {
      if (AsciiFilePath != NULL) {
        FreePool (AsciiFilePath);
      }
      if (TftpContext != NULL) {
        FreePool (TftpContext);
      }
      gBS->CloseProtocol (
             Mtftp4ChildHandle,
             &gEfiMtftp4ProtocolGuid,
             gImageHandle,
             ControllerHandle
            );
    }
    NetLibDestroyServiceChild (
      ControllerHandle,
      gImageHandle,
      &gEfiMtftp4ServiceBindingProtocolGuid,
      Mtftp4ChildHandle
      );
  }

  if (EFI_ERROR (Status)) {
    Print (L"Failed to download the file - Error=%r\n", Status);
  }

  return Status;
}
STATIC VOID
AddEfiBootOptions (
  VOID
)
{
  UINTN                         Index;
  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption;
  UINTN                         BootOptionCount;
  BOOLEAN                       First = TRUE;
  MENU_ENTRY                    *Entry;
  EFI_DEVICE_PATH*              DevicePathNode;

  BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);

  for (Index = 0; Index < BootOptionCount; Index++) {
    //
    // Don't display the hidden/inactive boot option
    //
    if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {
      continue;
    }

    if (First) {
      // GROUP: UEFI
      Entry = MenuCreateGroupEntry();
      Entry->Name = AsciiStrDup("UEFI");
      Entry->Update = UefiMenuEntryUpdate;
      MenuAddEntry(mBootMenuMain, Entry);
      First = FALSE;
    }

    Entry = MenuCreateEntry();
    if(Entry == NULL) {
      break;
    }

    CONST CHAR8* IconPath = "icons/uefi.png";

    DevicePathNode = BootOption[Index].FilePath;
    while ((DevicePathNode != NULL) && !IsDevicePathEnd (DevicePathNode)) {

      // detect shell
      if (IS_DEVICE_PATH_NODE (DevicePathNode, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP)) {
        CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH* FvDevicePathNode =  ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevicePathNode);
        if (FvDevicePathNode != NULL && CompareGuid (&FvDevicePathNode->FvFileName, &mUefiShellFileGuid)) {
          IconPath = "icons/efi_shell.png";
          break;
        }
      }

      // next
      DevicePathNode     = NextDevicePathNode (DevicePathNode);
    }

    Entry->Icon = libaroma_stream_ramdisk(IconPath);
    Entry->Name = Unicode2Ascii(BootOption[Index].Description);
    Entry->Callback = BootOptionEfiOption;
    Entry->Private = &BootOption[Index];
    Entry->ResetGop = TRUE;
    Entry->Update = UefiMenuEntryUpdate;
    MenuAddEntry(mBootMenuMain, Entry);
  }
}