ArmPkg/BdsLib: Fixed TFTP and PXE Boot

- An Ascii filename must be passed to the TFTP service (was a Unicode filename)
- If the PXE service had already configured the connection we need to restart
when we want to download a new file or do a do a PXE Boot.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14195 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin 2013-03-12 01:04:10 +00:00
parent ecc62d1390
commit 2edb5ad38c
2 changed files with 61 additions and 13 deletions

View File

@ -17,6 +17,7 @@
#include <Protocol/UsbIo.h> #include <Protocol/UsbIo.h>
#include <Protocol/DiskIo.h> #include <Protocol/DiskIo.h>
#include <Protocol/LoadedImage.h> #include <Protocol/LoadedImage.h>
#include <Protocol/SimpleNetwork.h>
#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype))) #define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
@ -661,6 +662,7 @@ BdsPxeLoadImage (
EFI_STATUS Status; EFI_STATUS Status;
EFI_LOAD_FILE_PROTOCOL *LoadFileProtocol; EFI_LOAD_FILE_PROTOCOL *LoadFileProtocol;
UINTN BufferSize; UINTN BufferSize;
EFI_PXE_BASE_CODE_PROTOCOL *Pxe;
// Get Load File Protocol attached to the PXE protocol // Get Load File Protocol attached to the PXE protocol
Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFileProtocol); Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFileProtocol);
@ -681,6 +683,15 @@ BdsPxeLoadImage (
} }
} }
if (Status == EFI_ALREADY_STARTED) {
Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
if (!EFI_ERROR(Status)) {
// If PXE is already started, we stop it
Pxe->Stop (Pxe);
// And we try again
return BdsPxeLoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, ImageSize);
}
}
return Status; return Status;
} }
@ -737,6 +748,8 @@ BdsTftpLoadImage (
IPv4_DEVICE_PATH* IPv4DevicePathNode; IPv4_DEVICE_PATH* IPv4DevicePathNode;
FILEPATH_DEVICE_PATH* FilePathDevicePath; FILEPATH_DEVICE_PATH* FilePathDevicePath;
EFI_IP_ADDRESS LocalIp; EFI_IP_ADDRESS LocalIp;
CHAR8* AsciiPathName;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)); ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP));
@ -753,18 +766,45 @@ BdsTftpLoadImage (
return Status; return Status;
} }
if (!IPv4DevicePathNode->StaticIpAddress) { do {
Status = Pxe->Dhcp(Pxe, TRUE); if (!IPv4DevicePathNode->StaticIpAddress) {
} else { Status = Pxe->Dhcp (Pxe, TRUE);
CopyMem (&LocalIp.v4, &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); } else {
Status = Pxe->SetStationIp (Pxe, &LocalIp, NULL); CopyMem (&LocalIp.v4, &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
} Status = Pxe->SetStationIp (Pxe, &LocalIp, NULL);
if (EFI_ERROR (Status)) { }
// 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;
}
}
} while (Status == EFI_ALREADY_STARTED);
if (EFI_ERROR(Status)) {
return Status; return Status;
} }
CopyMem (&ServerIp.v4, &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS)); 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);
Status = Pxe->Mtftp ( Status = Pxe->Mtftp (
Pxe, Pxe,
EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
@ -773,18 +813,22 @@ BdsTftpLoadImage (
&TftpBufferSize, &TftpBufferSize,
NULL, NULL,
&ServerIp, &ServerIp,
(UINT8 *)FilePathDevicePath->PathName, (UINT8*)AsciiPathName,
NULL, NULL,
TRUE FALSE
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR(Status)) {
return Status; if (Status == EFI_TFTP_ERROR) {
DEBUG((EFI_D_ERROR, "TFTP Error: Fail to get the size of the file\n"));
}
goto EXIT;
} }
// Allocate a buffer to hold the whole file. // Allocate a buffer to hold the whole file.
TftpBuffer = AllocatePool (TftpBufferSize); TftpBuffer = AllocatePool (TftpBufferSize);
if (TftpBuffer == NULL) { if (TftpBuffer == NULL) {
return EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
} }
Status = Pxe->Mtftp ( Status = Pxe->Mtftp (
@ -795,16 +839,19 @@ BdsTftpLoadImage (
&TftpBufferSize, &TftpBufferSize,
NULL, NULL,
&ServerIp, &ServerIp,
(UINT8 *)FilePathDevicePath->PathName, (UINT8*)AsciiPathName,
NULL, NULL,
FALSE FALSE
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (TftpBuffer); FreePool (TftpBuffer);
} else if (ImageSize != NULL) { } else if (ImageSize != NULL) {
*Image = (UINTN)TftpBuffer;
*ImageSize = (UINTN)TftpBufferSize; *ImageSize = (UINTN)TftpBufferSize;
} }
EXIT:
FreePool (AsciiPathName);
return Status; return Status;
} }

View File

@ -65,6 +65,7 @@
gEfiDiskIoProtocolGuid gEfiDiskIoProtocolGuid
gEfiUsbIoProtocolGuid gEfiUsbIoProtocolGuid
gEfiLoadedImageProtocolGuid gEfiLoadedImageProtocolGuid
gEfiSimpleNetworkProtocolGuid
[FeaturePcd] [FeaturePcd]
gArmTokenSpaceGuid.PcdArmPsciSupport gArmTokenSpaceGuid.PcdArmPsciSupport