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