- // Convert the Unicode PathName to Ascii\r
- AsciiPathName = AllocatePool ((StrLen (FilePathDevicePath->PathName) + 1) * sizeof (CHAR8));\r
- if (AsciiPathName == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- UnicodeStrToAsciiStr (FilePathDevicePath->PathName, AsciiPathName);\r
-\r
- // Try to get the size (required the TFTP server to have "tsize" extension)\r
- Status = Pxe->Mtftp (\r
- Pxe,\r
- EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,\r
- NULL,\r
- FALSE,\r
- &TftpBufferSize,\r
- NULL,\r
- &ServerIp,\r
- (UINT8*)AsciiPathName,\r
- NULL,\r
- FALSE\r
- );\r
- // Pxe.Mtftp replies EFI_PROTOCOL_ERROR if tsize is not supported by the TFTP server\r
- if (EFI_ERROR (Status) && (Status != EFI_PROTOCOL_ERROR)) {\r
- if (Status == EFI_TFTP_ERROR) {\r
- DEBUG((EFI_D_ERROR, "TFTP Error: Fail to get the size of the file\n"));\r
+/**\r
+ Download an image from a TFTP server\r
+\r
+ @param[in] DevicePath Device path of the TFTP boot option\r
+ @param[in] ControllerHandle Handle of the network controller\r
+ @param[in] RemainingDevicePath Device path of the TFTP boot option but\r
+ the first node that identifies the network controller\r
+ @param[in] Type Type to allocate memory pages\r
+ @param[out] Image Address of the bufer where the image is stored in\r
+ case of success\r
+ @param[out] ImageSize Size in number of bytes of the i;age in case of\r
+ success\r
+\r
+ @retval EFI_SUCCESS The image was returned.\r
+ @retval !EFI_SUCCESS Something went wrong.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsTftpLoadImage (\r
+ IN OUT EFI_DEVICE_PATH **DevicePath,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH *RemainingDevicePath,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN OUT EFI_PHYSICAL_ADDRESS *Image,\r
+ OUT UINTN *ImageSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Dhcp4ChildHandle;\r
+ EFI_DHCP4_PROTOCOL *Dhcp4;\r
+ BOOLEAN Dhcp4ToStop;\r
+ EFI_HANDLE Mtftp4ChildHandle;\r
+ EFI_MTFTP4_PROTOCOL *Mtftp4;\r
+ DHCP4_OPTION ParaList;\r
+ EFI_DHCP4_PACKET_OPTION *OptionList[2];\r
+ EFI_DHCP4_CONFIG_DATA Dhcp4CfgData;\r
+ EFI_DHCP4_MODE_DATA Dhcp4Mode;\r
+ EFI_MTFTP4_CONFIG_DATA Mtftp4CfgData;\r
+ IPv4_DEVICE_PATH *IPv4DevicePathNode;\r
+ CHAR16 *PathName;\r
+ CHAR8 *AsciiFilePath;\r
+ EFI_MTFTP4_TOKEN Mtftp4Token;\r
+ UINT64 FileSize;\r
+ UINT64 TftpBufferSize;\r
+ BDS_TFTP_CONTEXT *TftpContext;\r
+ UINTN PathNameLen;\r
+\r
+ ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP));\r
+ IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;\r
+\r
+ Dhcp4ChildHandle = NULL;\r
+ Dhcp4 = NULL;\r
+ Dhcp4ToStop = FALSE;\r
+ Mtftp4ChildHandle = NULL;\r
+ Mtftp4 = NULL;\r
+ AsciiFilePath = NULL;\r
+ TftpContext = NULL;\r
+\r
+ if (!IPv4DevicePathNode->StaticIpAddress) {\r
+ //\r
+ // Using the DHCP4 Service Binding Protocol, create a child handle of the DHCP4 service and\r
+ // install the DHCP4 protocol on it. Then, open the DHCP protocol.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ ControllerHandle,\r
+ gImageHandle,\r
+ &gEfiDhcp4ServiceBindingProtocolGuid,\r
+ &Dhcp4ChildHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ Dhcp4ChildHandle,\r
+ &gEfiDhcp4ProtocolGuid,\r
+ (VOID **) &Dhcp4,\r
+ gImageHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ Print (L"Unable to open DHCP4 protocol\n");\r
+ goto Error;\r