mirror of https://github.com/acidanthera/audk.git
ArmPkg/BdsLib: Rework TFTP boot
Rework the downloading of an image from a TFTP server to do not depend on any "PXE specific" setting of the DHCP server. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ronald Cron <Ronald.Cron@arm.com> Reviewed-by: Olivier Martin <olivier.martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16516 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
b4c222655c
commit
061568e2d5
|
@ -55,6 +55,10 @@
|
|||
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
|
||||
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
|
||||
|
||||
NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
|
||||
UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
|
||||
HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
|
||||
|
||||
SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf
|
||||
UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf
|
||||
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
|
||||
|
|
|
@ -14,13 +14,41 @@
|
|||
|
||||
#include "BdsInternal.h"
|
||||
|
||||
#include <Library/NetLib.h>
|
||||
|
||||
#include <Protocol/Bds.h>
|
||||
#include <Protocol/UsbIo.h>
|
||||
#include <Protocol/DiskIo.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/SimpleNetwork.h>
|
||||
#include <Protocol/Dhcp4.h>
|
||||
#include <Protocol/Mtftp4.h>
|
||||
|
||||
#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
|
||||
|
||||
/*
|
||||
Constant strings and define related to the message indicating the amount of
|
||||
progress in the dowloading of a TFTP file.
|
||||
*/
|
||||
|
||||
// Frame for the progression slider
|
||||
STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ ]";
|
||||
|
||||
// Number of steps in the progression slider
|
||||
#define TFTP_PROGRESS_SLIDER_STEPS ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3)
|
||||
|
||||
// Size in number of characters plus one (final zero) of the message to
|
||||
// indicate the progress of a tftp download. The format is "[(progress slider:
|
||||
// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There
|
||||
// are thus the number of characters in mTftpProgressFrame[] plus 11 characters
|
||||
// (2 // spaces, "Kb" and seven characters for the number of KBytes).
|
||||
#define TFTP_PROGRESS_MESSAGE_SIZE ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12)
|
||||
|
||||
// String to delete the tftp progress message to be able to update it :
|
||||
// (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b'
|
||||
STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
|
||||
|
||||
|
||||
// Extract the FilePath from the Device Path
|
||||
CHAR16*
|
||||
BdsExtractFilePathFromDevicePath (
|
||||
|
@ -723,14 +751,14 @@ BdsPxeLoadImage (
|
|||
|
||||
BOOLEAN
|
||||
BdsTftpSupport (
|
||||
IN EFI_DEVICE_PATH* DevicePath,
|
||||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DEVICE_PATH* RemainingDevicePath
|
||||
IN EFI_DEVICE_PATH *DevicePath,
|
||||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DEVICE_PATH *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS Status;
|
||||
EFI_DEVICE_PATH *NextDevicePath;
|
||||
EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol;
|
||||
VOID *Interface;
|
||||
|
||||
// Validate the Remaining Device Path
|
||||
if (IsDevicePathEnd (RemainingDevicePath)) {
|
||||
|
@ -748,151 +776,412 @@ BdsTftpSupport (
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);
|
||||
Status = gBS->HandleProtocol (
|
||||
Handle, &gEfiDevicePathProtocolGuid,
|
||||
&Interface
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function that get the size in numbers of bytes of a file from a TFTP
|
||||
server before to download the file.
|
||||
|
||||
@param[in] Mtftp4 MTFTP4 protocol interface
|
||||
@param[in] FilePath Path of the file, Ascii encoded
|
||||
@param[out] FileSize Address where to store the file size in number of
|
||||
bytes.
|
||||
|
||||
@retval EFI_SUCCESS The size of the file was returned.
|
||||
@retval !EFI_SUCCESS The size of the file was not returned.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4GetFileSize (
|
||||
IN EFI_MTFTP4_PROTOCOL *Mtftp4,
|
||||
IN CHAR8 *FilePath,
|
||||
OUT UINT64 *FileSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_MTFTP4_OPTION ReqOpt[1];
|
||||
EFI_MTFTP4_PACKET *Packet;
|
||||
UINT32 PktLen;
|
||||
EFI_MTFTP4_OPTION *TableOfOptions;
|
||||
EFI_MTFTP4_OPTION *Option;
|
||||
UINT32 OptCnt;
|
||||
UINT8 OptBuf[128];
|
||||
|
||||
ReqOpt[0].OptionStr = (UINT8*)"tsize";
|
||||
OptBuf[0] = '0';
|
||||
OptBuf[1] = 0;
|
||||
ReqOpt[0].ValueStr = OptBuf;
|
||||
|
||||
Status = Mtftp4->GetInfo (
|
||||
Mtftp4,
|
||||
NULL,
|
||||
(UINT8*)FilePath,
|
||||
NULL,
|
||||
1,
|
||||
ReqOpt,
|
||||
&PktLen,
|
||||
&Packet
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Status = Mtftp4->ParseOptions (
|
||||
Mtftp4,
|
||||
PktLen,
|
||||
Packet,
|
||||
(UINT32 *) &OptCnt,
|
||||
&TableOfOptions
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Option = TableOfOptions;
|
||||
while (OptCnt != 0) {
|
||||
if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) {
|
||||
*FileSize = AsciiStrDecimalToUint64 ((CHAR8 *)Option->ValueStr);
|
||||
break;
|
||||
}
|
||||
OptCnt--;
|
||||
Option++;
|
||||
}
|
||||
FreePool (TableOfOptions);
|
||||
|
||||
if (OptCnt == 0) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Error :
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Update the progress of a file download
|
||||
This procedure is called each time a new TFTP packet is received.
|
||||
|
||||
@param[in] This MTFTP4 protocol interface
|
||||
@param[in] Token Parameters for the download of the file
|
||||
@param[in] PacketLen Length of the packet
|
||||
@param[in] Packet Address of the packet
|
||||
|
||||
@retval EFI_SUCCESS All packets are accepted.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4CheckPacket (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_TOKEN *Token,
|
||||
IN UINT16 PacketLen,
|
||||
IN EFI_MTFTP4_PACKET *Packet
|
||||
)
|
||||
{
|
||||
BDS_TFTP_CONTEXT *Context;
|
||||
CHAR16 Progress[TFTP_PROGRESS_MESSAGE_SIZE];
|
||||
UINT64 NbOfKb;
|
||||
UINTN Index;
|
||||
UINTN LastStep;
|
||||
UINTN Step;
|
||||
UINT64 LastNbOf50Kb;
|
||||
UINT64 NbOf50Kb;
|
||||
|
||||
if ((NTOHS (Packet->OpCode)) == EFI_MTFTP4_OPCODE_DATA) {
|
||||
Context = (BDS_TFTP_CONTEXT*)Token->Context;
|
||||
|
||||
if (Context->DownloadedNbOfBytes == 0) {
|
||||
if (Context->FileSize > 0) {
|
||||
Print (L"%s 0 Kb", mTftpProgressFrame);
|
||||
} else {
|
||||
Print (L" 0 Kb");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The data is the packet are prepended with two UINT16 :
|
||||
// . OpCode = EFI_MTFTP4_OPCODE_DATA
|
||||
// . Block = the number of this block of data
|
||||
//
|
||||
Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode) - sizeof (Packet->Data.Block);
|
||||
NbOfKb = Context->DownloadedNbOfBytes / 1024;
|
||||
|
||||
Progress[0] = L'\0';
|
||||
if (Context->FileSize > 0) {
|
||||
LastStep = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;
|
||||
Step = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;
|
||||
if (Step > LastStep) {
|
||||
Print (mTftpProgressDelete);
|
||||
StrCpy (Progress, mTftpProgressFrame);
|
||||
for (Index = 1; Index < Step; Index++) {
|
||||
Progress[Index] = L'=';
|
||||
}
|
||||
Progress[Step] = L'>';
|
||||
|
||||
UnicodeSPrint (
|
||||
Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1,
|
||||
sizeof (Progress) - sizeof (mTftpProgressFrame),
|
||||
L" %7d Kb",
|
||||
NbOfKb
|
||||
);
|
||||
Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Case when we do not know the size of the final file.
|
||||
// We print the updated size every 50KB of downloaded data
|
||||
//
|
||||
LastNbOf50Kb = Context->LastReportedNbOfBytes / (50*1024);
|
||||
NbOf50Kb = Context->DownloadedNbOfBytes / (50*1024);
|
||||
if (NbOf50Kb > LastNbOf50Kb) {
|
||||
Print (L"\b\b\b\b\b\b\b\b\b\b");
|
||||
UnicodeSPrint (Progress, sizeof (Progress), L"%7d Kb", NbOfKb);
|
||||
Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;
|
||||
}
|
||||
}
|
||||
if (Progress[0] != L'\0') {
|
||||
Print (L"%s", Progress);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
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 EFI_DEVICE_PATH* DevicePath,
|
||||
IN EFI_HANDLE Handle,
|
||||
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_PXE_BASE_CODE_PROTOCOL *Pxe;
|
||||
UINT64 TftpBufferSize;
|
||||
UINT64 TftpTransferSize;
|
||||
EFI_IP_ADDRESS ServerIp;
|
||||
IPv4_DEVICE_PATH* IPv4DevicePathNode;
|
||||
FILEPATH_DEVICE_PATH* FilePathDevicePath;
|
||||
EFI_IP_ADDRESS LocalIp;
|
||||
CHAR8* AsciiPathName;
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Dhcp4ChildHandle;
|
||||
EFI_DHCP4_PROTOCOL *Dhcp4;
|
||||
BOOLEAN Dhcp4ToStop;
|
||||
EFI_HANDLE Mtftp4ChildHandle;
|
||||
EFI_MTFTP4_PROTOCOL *Mtftp4;
|
||||
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;
|
||||
FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
|
||||
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)) {
|
||||
return Status;
|
||||
Print (L"Unable to open MTFTP4 protocol\n");
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Status = Pxe->Start (Pxe, FALSE);
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
return Status;
|
||||
}
|
||||
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));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
if (!IPv4DevicePathNode->StaticIpAddress) {
|
||||
Status = Pxe->Dhcp (Pxe, TRUE);
|
||||
//
|
||||
// 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 {
|
||||
CopyMem (&LocalIp.v4, &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
Status = Pxe->SetStationIp (Pxe, &LocalIp, NULL);
|
||||
Dhcp4ToStop = TRUE;
|
||||
}
|
||||
|
||||
// If an IP Address has already been set and a different static IP address is requested then restart
|
||||
// the Network service.
|
||||
if (Status == EFI_ALREADY_STARTED) {
|
||||
Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&Snp);
|
||||
if (!EFI_ERROR (Status) && IPv4DevicePathNode->StaticIpAddress &&
|
||||
(CompareMem (&Snp->Mode->CurrentAddress, &IPv4DevicePathNode->LocalIpAddress, sizeof(EFI_MAC_ADDRESS)) != 0))
|
||||
{
|
||||
Pxe->Stop (Pxe);
|
||||
Status = Pxe->Start (Pxe, FALSE);
|
||||
if (EFI_ERROR(Status)) {
|
||||
break;
|
||||
}
|
||||
// After restarting the PXE protocol, we want to try again with our new IP Address
|
||||
Status = EFI_ALREADY_STARTED;
|
||||
}
|
||||
Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} while (Status == EFI_ALREADY_STARTED);
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
CopyMem (&ServerIp.v4, &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
// Convert the Unicode PathName to Ascii
|
||||
AsciiPathName = AllocatePool ((StrLen (FilePathDevicePath->PathName) + 1) * sizeof (CHAR8));
|
||||
if (AsciiPathName == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
UnicodeStrToAsciiStr (FilePathDevicePath->PathName, AsciiPathName);
|
||||
|
||||
// Try to get the size (required the TFTP server to have "tsize" extension)
|
||||
Status = Pxe->Mtftp (
|
||||
Pxe,
|
||||
EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
|
||||
NULL,
|
||||
FALSE,
|
||||
&TftpBufferSize,
|
||||
NULL,
|
||||
&ServerIp,
|
||||
(UINT8*)AsciiPathName,
|
||||
NULL,
|
||||
FALSE
|
||||
);
|
||||
// Pxe.Mtftp replies EFI_PROTOCOL_ERROR if tsize is not supported by the TFTP server
|
||||
if (EFI_ERROR (Status) && (Status != EFI_PROTOCOL_ERROR)) {
|
||||
if (Status == EFI_TFTP_ERROR) {
|
||||
DEBUG((EFI_D_ERROR, "TFTP Error: Fail to get the size of the file\n"));
|
||||
if (Dhcp4Mode.State != Dhcp4Bound) {
|
||||
Status = EFI_TIMEOUT;
|
||||
Print (L"DHCP configuration failed\n");
|
||||
goto Error;
|
||||
}
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Two cases:
|
||||
// 1) the file size is unknown (tsize extension not supported)
|
||||
// 2) tsize returned the file size
|
||||
// Configure the TFTP4 protocol
|
||||
//
|
||||
if (Status == EFI_PROTOCOL_ERROR) {
|
||||
for (TftpBufferSize = SIZE_8MB; TftpBufferSize <= FixedPcdGet32 (PcdMaxTftpFileSize); TftpBufferSize += SIZE_8MB) {
|
||||
// Allocate a buffer to hold the whole file.
|
||||
Status = gBS->AllocatePages (
|
||||
Type,
|
||||
EfiBootServicesCode,
|
||||
EFI_SIZE_TO_PAGES (TftpBufferSize),
|
||||
Image
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Failed to allocate space for image: %r\n", Status));
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
TftpTransferSize = TftpBufferSize;
|
||||
Status = Pxe->Mtftp (
|
||||
Pxe,
|
||||
EFI_PXE_BASE_CODE_TFTP_READ_FILE,
|
||||
(VOID *)(UINTN)*Image,
|
||||
FALSE,
|
||||
&TftpTransferSize,
|
||||
NULL,
|
||||
&ServerIp,
|
||||
(UINT8*)AsciiPathName,
|
||||
NULL,
|
||||
FALSE
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));
|
||||
} else {
|
||||
*ImageSize = (UINTN)TftpBufferSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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,
|
||||
|
@ -900,31 +1189,85 @@ BdsTftpLoadImage (
|
|||
Image
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Failed to allocate space for kernel image: %r\n", Status));
|
||||
goto EXIT;
|
||||
Print (L"Failed to allocate space for image\n");
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Status = Pxe->Mtftp (
|
||||
Pxe,
|
||||
EFI_PXE_BASE_CODE_TFTP_READ_FILE,
|
||||
(VOID *)(UINTN)*Image,
|
||||
FALSE,
|
||||
&TftpBufferSize,
|
||||
NULL,
|
||||
&ServerIp,
|
||||
(UINT8*)AsciiPathName,
|
||||
NULL,
|
||||
FALSE
|
||||
);
|
||||
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));
|
||||
} else {
|
||||
*ImageSize = (UINTN)TftpBufferSize;
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
Print (L"Downloading failed, file larger than expected.\n");
|
||||
gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));
|
||||
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);
|
||||
}
|
||||
|
||||
EXIT:
|
||||
FreePool (AsciiPathName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,11 @@ typedef struct _BDS_SYSTEM_MEMORY_RESOURCE {
|
|||
UINT64 ResourceLength;
|
||||
} BDS_SYSTEM_MEMORY_RESOURCE;
|
||||
|
||||
typedef struct {
|
||||
UINT64 FileSize;
|
||||
UINT64 DownloadedNbOfBytes;
|
||||
UINT64 LastReportedNbOfBytes;
|
||||
} BDS_TFTP_CONTEXT;
|
||||
|
||||
// BdsHelper.c
|
||||
EFI_STATUS
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
@ -53,6 +54,7 @@
|
|||
SerialPortLib
|
||||
FdtLib
|
||||
TimerLib
|
||||
NetLib
|
||||
|
||||
[LibraryClasses.AARCH64]
|
||||
ArmGicLib
|
||||
|
@ -74,6 +76,10 @@
|
|||
gEfiUsbIoProtocolGuid
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiSimpleNetworkProtocolGuid
|
||||
gEfiDhcp4ServiceBindingProtocolGuid
|
||||
gEfiDhcp4ProtocolGuid
|
||||
gEfiMtftp4ServiceBindingProtocolGuid
|
||||
gEfiMtftp4ProtocolGuid
|
||||
|
||||
[FeaturePcd]
|
||||
gArmTokenSpaceGuid.PcdArmLinuxSpinTable
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
gEfiDevicePathToTextProtocolGuid
|
||||
gEfiFirmwareVolumeBlockProtocolGuid
|
||||
gEfiFirmwareVolumeBlock2ProtocolGuid
|
||||
gEfiDhcp4ServiceBindingProtocolGuid
|
||||
gEfiMtftp4ServiceBindingProtocolGuid
|
||||
|
||||
[Pcd]
|
||||
gArmPlatformTokenSpaceGuid.PcdFirmwareVendor
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <Protocol/PxeBaseCode.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Protocol/SimpleNetwork.h>
|
||||
#include <Protocol/Dhcp4.h>
|
||||
#include <Protocol/Mtftp4.h>
|
||||
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
|
||||
|
@ -866,49 +868,96 @@ BdsLoadOptionPxeIsSupported (
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Add to the list of boot devices the devices allowing a TFTP boot
|
||||
|
||||
@param[in] BdsLoadOptionList List of devices to boot from
|
||||
|
||||
@retval EFI_SUCCESS Update completed
|
||||
@retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource
|
||||
**/
|
||||
EFI_STATUS
|
||||
BdsLoadOptionTftpList (
|
||||
IN OUT LIST_ENTRY* BdsLoadOptionList
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN HandleCount;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN Index;
|
||||
BDS_SUPPORTED_DEVICE *SupportedDevice;
|
||||
EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL* SimpleNet;
|
||||
CHAR16 DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];
|
||||
EFI_MAC_ADDRESS *Mac;
|
||||
EFI_STATUS Status;
|
||||
UINTN HandleCount;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
EFI_HANDLE Handle;
|
||||
UINTN Index;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol;
|
||||
VOID *Interface;
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetworkProtocol;
|
||||
BDS_SUPPORTED_DEVICE *SupportedDevice;
|
||||
EFI_MAC_ADDRESS *Mac;
|
||||
|
||||
// List all the PXE Protocols
|
||||
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);
|
||||
//
|
||||
// List all the handles on which the Simple Network Protocol is installed.
|
||||
//
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiSimpleNetworkProtocolGuid,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < HandleCount; Index++) {
|
||||
// We only select the handle WITH a Device Path AND the PXE Protocol AND the TFTP Protocol (the TFTP protocol is required to start PXE)
|
||||
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
// Allocate BDS Supported Device structure
|
||||
SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Mac = &SimpleNet->Mode->CurrentAddress;
|
||||
UnicodeSPrint (DeviceDescription,BOOT_DEVICE_DESCRIPTION_MAX,L"MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]);
|
||||
} else {
|
||||
Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"TFTP on %s",DeviceDescription);
|
||||
|
||||
SupportedDevice->DevicePathProtocol = DevicePathProtocol;
|
||||
SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP];
|
||||
|
||||
InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);
|
||||
Handle = HandleBuffer[Index];
|
||||
//
|
||||
// We select the handles that support :
|
||||
// . the Device Path Protocol
|
||||
// . the MTFTP4 Protocol
|
||||
//
|
||||
Status = gBS->HandleProtocol (
|
||||
Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
(VOID **)&DevicePathProtocol
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = gBS->HandleProtocol (
|
||||
Handle,
|
||||
&gEfiMtftp4ServiceBindingProtocolGuid,
|
||||
&Interface
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = gBS->HandleProtocol (
|
||||
Handle,
|
||||
&gEfiSimpleNetworkProtocolGuid,
|
||||
(VOID **)&SimpleNetworkProtocol
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Allocate BDS Supported Device structure
|
||||
SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof (BDS_SUPPORTED_DEVICE));
|
||||
if (SupportedDevice == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Mac = &SimpleNetworkProtocol->Mode->CurrentAddress;
|
||||
UnicodeSPrint (
|
||||
SupportedDevice->Description,
|
||||
BOOT_DEVICE_DESCRIPTION_MAX,
|
||||
L"TFTP on MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]
|
||||
);
|
||||
|
||||
SupportedDevice->DevicePathProtocol = DevicePathProtocol;
|
||||
SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP];
|
||||
|
||||
InsertTailList (BdsLoadOptionList, &SupportedDevice->Link);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
@ -920,38 +969,50 @@ BdsLoadOptionTftpCreateDevicePath (
|
|||
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN IsDHCP;
|
||||
EFI_IP_ADDRESS LocalIp;
|
||||
EFI_IP_ADDRESS RemoteIp;
|
||||
IPv4_DEVICE_PATH* IPv4DevicePathNode;
|
||||
FILEPATH_DEVICE_PATH* FilePathDevicePath;
|
||||
CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];
|
||||
UINTN BootFilePathSize;
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN IsDHCP;
|
||||
EFI_IP_ADDRESS LocalIp;
|
||||
EFI_IP_ADDRESS SubnetMask;
|
||||
EFI_IP_ADDRESS GatewayIp;
|
||||
EFI_IP_ADDRESS RemoteIp;
|
||||
IPv4_DEVICE_PATH *IPv4DevicePathNode;
|
||||
FILEPATH_DEVICE_PATH *FilePathDevicePath;
|
||||
CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];
|
||||
UINTN BootFilePathSize;
|
||||
|
||||
Print(L"Get the IP address from DHCP: ");
|
||||
Print (L"Get the IP address from DHCP: ");
|
||||
Status = GetHIInputBoolean (&IsDHCP);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
if (!IsDHCP) {
|
||||
Print(L"Get the static IP address: ");
|
||||
Print (L"Local static IP address: ");
|
||||
Status = GetHIInputIP (&LocalIp);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
Print (L"Get the network mask: ");
|
||||
Status = GetHIInputIP (&SubnetMask);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
Print (L"Get the gateway IP address: ");
|
||||
Status = GetHIInputIP (&GatewayIp);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
Print(L"Get the TFTP server IP address: ");
|
||||
Print (L"Get the TFTP server IP address: ");
|
||||
Status = GetHIInputIP (&RemoteIp);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Print(L"File path of the %s : ", FileName);
|
||||
Print (L"File path of the %s : ", FileName);
|
||||
Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
|
@ -967,7 +1028,13 @@ BdsLoadOptionTftpCreateDevicePath (
|
|||
IPv4DevicePathNode->Header.Type = MESSAGING_DEVICE_PATH;
|
||||
IPv4DevicePathNode->Header.SubType = MSG_IPv4_DP;
|
||||
SetDevicePathNodeLength (&IPv4DevicePathNode->Header, sizeof(IPv4_DEVICE_PATH));
|
||||
CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
if (!IsDHCP) {
|
||||
CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));
|
||||
CopyMem (&IPv4DevicePathNode->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
|
||||
CopyMem (&IPv4DevicePathNode->GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));
|
||||
}
|
||||
|
||||
CopyMem (&IPv4DevicePathNode->RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));
|
||||
IPv4DevicePathNode->LocalPort = 0;
|
||||
IPv4DevicePathNode->RemotePort = 0;
|
||||
|
@ -1021,7 +1088,11 @@ BdsLoadOptionTftpUpdateDevicePath (
|
|||
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];
|
||||
|
@ -1074,9 +1145,7 @@ BdsLoadOptionTftpUpdateDevicePath (
|
|||
if (!IsDHCP) {
|
||||
Print (L"Local static IP address: ");
|
||||
if (Ipv4Node.StaticIpAddress) {
|
||||
// Copy local IPv4 address into IPv4 or IPv6 union
|
||||
CopyMem (&OldIp.v4, &Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
Status = EditHIInputIP (&OldIp, &LocalIp);
|
||||
} else {
|
||||
Status = GetHIInputIP (&LocalIp);
|
||||
|
@ -1084,6 +1153,28 @@ BdsLoadOptionTftpUpdateDevicePath (
|
|||
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: ");
|
||||
|
@ -1126,12 +1217,18 @@ BdsLoadOptionTftpUpdateDevicePath (
|
|||
//
|
||||
// Update the IPv4 node. IPv6 case not handled yet.
|
||||
//
|
||||
if (IsDHCP == TRUE) {
|
||||
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.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
CopyMem (&Ipv4Node.RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));
|
||||
CopyMem (Ipv4NodePtr, &Ipv4Node, sizeof (IPv4_DEVICE_PATH));
|
||||
|
||||
|
|
Loading…
Reference in New Issue