예제 #1
0
파일: EblNetworkLib.c 프로젝트: B-Rich/edk2
EFI_STATUS
EFIAPI
EblPerformDHCP (
  IN  BOOLEAN  SortOffers
  )
{
  EFI_STATUS                  Status;
  EFI_PXE_BASE_CODE_PROTOCOL  *Pxe;
  
  Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
  if (EFI_ERROR(Status)) {
    return Status;
  }

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

  Status = Pxe->Dhcp(Pxe, TRUE);
  return Status;
}
예제 #2
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;
}
예제 #3
0
/**
  Discover all the boot information for boot file.

  @param[in, out] Private      Pointer to PxeBc private data.
  @param[out]     BufferSize   Size of the boot file to be downloaded.

  @retval EFI_SUCCESS          Successfully obtained all the boot information .
  @retval EFI_BUFFER_TOO_SMALL The buffer size is not enough for boot file.
  @retval EFI_ABORTED          User cancel current operation.
  @retval Others               Failed to parse out the boot information.

**/
EFI_STATUS
PxeBcDiscoverBootFile (
  IN OUT PXEBC_PRIVATE_DATA   *Private,
     OUT UINT64               *BufferSize
  )
{
  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;
  EFI_PXE_BASE_CODE_MODE      *Mode;
  EFI_STATUS                  Status;
  UINT16                      Type;
  UINT16                      Layer;
  BOOLEAN                     UseBis;

  PxeBc = &Private->PxeBc;
  Mode  = PxeBc->Mode;
  Type  = EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP;
  Layer = EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL;

  //
  // Start D.O.R.A/S.A.R.R exchange to acquire station ip address and
  // other pxe boot information.
  //
  Status = PxeBc->Dhcp (PxeBc, TRUE);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select a boot server from boot server list.
  //
  Status = PxeBcSelectBootPrompt (Private);

  if (Status == EFI_SUCCESS) {
    //
    // Choose by user's input.
    //
    Status = PxeBcSelectBootMenu (Private, &Type, FALSE);
  } else if (Status == EFI_TIMEOUT) {
    //
    // Choose by default item.
    //
    Status = PxeBcSelectBootMenu (Private, &Type, TRUE);
  }

  if (!EFI_ERROR (Status)) {

    if (Type == EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP) {
      //
      // Local boot(PXE bootstrap server) need abort
      //
      return EFI_ABORTED;
    }

    //
    // Start to discover the boot server to get (m)tftp server ip address, bootfile
    // name and bootfile size.
    //
    UseBis = (BOOLEAN) (Mode->BisSupported && Mode->BisDetected);
    Status = PxeBc->Discover (PxeBc, Type, &Layer, UseBis, NULL);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    if (Mode->PxeReplyReceived && !Mode->ProxyOfferReceived) {
      //
      // Some network boot loader only search the packet in Mode.ProxyOffer to get its server
      // IP address, so we need to store a copy of Mode.PxeReply packet into Mode.ProxyOffer.
      //
      if (Mode->UsingIpv6) {
        CopyMem (
          &Mode->ProxyOffer.Dhcpv6,
          &Mode->PxeReply.Dhcpv6,
          Private->PxeReply.Dhcp6.Packet.Ack.Length
          );
      } else {
        CopyMem (
          &Mode->ProxyOffer.Dhcpv4,
          &Mode->PxeReply.Dhcpv4,
          Private->PxeReply.Dhcp4.Packet.Ack.Length
          );      
      }
      Mode->ProxyOfferReceived = TRUE;
    }
  }

  //
  // Parse the boot information.
  //
  if (Mode->UsingIpv6) {
    Status = PxeBcDhcp6BootInfo (Private, BufferSize);
  } else {
    Status = PxeBcDhcp4BootInfo (Private, BufferSize);
  }

  return Status;
}