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:
Ronald Cron
2014-12-12 19:14:22 +00:00
committed by oliviermartin
parent b4c222655c
commit 061568e2d5
6 changed files with 643 additions and 186 deletions

View File

@@ -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));