]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPlatformPkg/Bds/BootOptionSupport.c
ArmPkg/BdsLib: Rework TFTP boot
[mirror_edk2.git] / ArmPlatformPkg / Bds / BootOptionSupport.c
index ee4281855e79a9208ae60d574c921917ab8bfbfa..974f220553a3f746934efb25de48f89b447b9703 100644 (file)
@@ -22,6 +22,8 @@
 #include <Protocol/PxeBaseCode.h>\r
 #include <Protocol/SimpleFileSystem.h>\r
 #include <Protocol/SimpleNetwork.h>\r
+#include <Protocol/Dhcp4.h>\r
+#include <Protocol/Mtftp4.h>\r
 \r
 #include <Guid/FileSystemInfo.h>\r
 \r
@@ -866,49 +868,96 @@ BdsLoadOptionPxeIsSupported (
   }\r
 }\r
 \r
+/**\r
+  Add to the list of boot devices the devices allowing a TFTP boot\r
+\r
+  @param[in]   BdsLoadOptionList  List of devices to boot from\r
+\r
+  @retval  EFI_SUCCESS            Update completed\r
+  @retval  EFI_OUT_OF_RESOURCES   Fail to perform the update due to lack of resource\r
+**/\r
 EFI_STATUS\r
 BdsLoadOptionTftpList (\r
   IN OUT LIST_ENTRY* BdsLoadOptionList\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  UINTN                             HandleCount;\r
-  EFI_HANDLE                        *HandleBuffer;\r
-  UINTN                             Index;\r
-  BDS_SUPPORTED_DEVICE              *SupportedDevice;\r
-  EFI_DEVICE_PATH_PROTOCOL*         DevicePathProtocol;\r
-  EFI_SIMPLE_NETWORK_PROTOCOL*      SimpleNet;\r
-  CHAR16                            DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
-  EFI_MAC_ADDRESS                   *Mac;\r
+  EFI_STATUS                   Status;\r
+  UINTN                        HandleCount;\r
+  EFI_HANDLE                   *HandleBuffer;\r
+  EFI_HANDLE                   Handle;\r
+  UINTN                        Index;\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePathProtocol;\r
+  VOID                         *Interface;\r
+  EFI_SIMPLE_NETWORK_PROTOCOL  *SimpleNetworkProtocol;\r
+  BDS_SUPPORTED_DEVICE         *SupportedDevice;\r
+  EFI_MAC_ADDRESS              *Mac;\r
 \r
-  // List all the PXE Protocols\r
-  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
+  //\r
+  // List all the handles on which the Simple Network Protocol is installed.\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSimpleNetworkProtocolGuid,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &HandleBuffer\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   for (Index = 0; Index < HandleCount; Index++) {\r
-    // 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)\r
-    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
-    if (!EFI_ERROR(Status)) {\r
-      // Allocate BDS Supported Device structure\r
-      SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
+    Handle = HandleBuffer[Index];\r
+    //\r
+    // We select the handles that support :\r
+    // . the Device Path Protocol\r
+    // . the MTFTP4 Protocol\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    Handle,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    (VOID **)&DevicePathProtocol\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
 \r
-      Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet);\r
-      if (!EFI_ERROR(Status)) {\r
-        Mac = &SimpleNet->Mode->CurrentAddress;\r
-        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]);\r
-      } else {\r
-        Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);\r
-        ASSERT_EFI_ERROR (Status);\r
-      }\r
-      UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"TFTP on %s",DeviceDescription);\r
+    Status = gBS->HandleProtocol (\r
+                    Handle,\r
+                    &gEfiMtftp4ServiceBindingProtocolGuid,\r
+                    &Interface\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
 \r
-      SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
-      SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP];\r
+    Status = gBS->HandleProtocol (\r
+                    Handle,\r
+                    &gEfiSimpleNetworkProtocolGuid,\r
+                    (VOID **)&SimpleNetworkProtocol\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
 \r
-      InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
+    // Allocate BDS Supported Device structure\r
+    SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof (BDS_SUPPORTED_DEVICE));\r
+    if (SupportedDevice == NULL) {\r
+      continue;\r
     }\r
+\r
+    Mac = &SimpleNetworkProtocol->Mode->CurrentAddress;\r
+    UnicodeSPrint (\r
+      SupportedDevice->Description,\r
+      BOOT_DEVICE_DESCRIPTION_MAX,\r
+      L"TFTP on MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",\r
+      Mac->Addr[0],  Mac->Addr[1],  Mac->Addr[2],  Mac->Addr[3],  Mac->Addr[4],  Mac->Addr[5]\r
+      );\r
+\r
+    SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
+    SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP];\r
+\r
+    InsertTailList (BdsLoadOptionList, &SupportedDevice->Link);\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -920,38 +969,50 @@ BdsLoadOptionTftpCreateDevicePath (
   OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes\r
   )\r
 {\r
-  EFI_STATUS    Status;\r
-  BOOLEAN       IsDHCP;\r
-  EFI_IP_ADDRESS  LocalIp;\r
-  EFI_IP_ADDRESS  RemoteIp;\r
-  IPv4_DEVICE_PATH*   IPv4DevicePathNode;\r
-  FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
-  CHAR16      BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
-  UINTN       BootFilePathSize;\r
+  EFI_STATUS            Status;\r
+  BOOLEAN               IsDHCP;\r
+  EFI_IP_ADDRESS        LocalIp;\r
+  EFI_IP_ADDRESS        SubnetMask;\r
+  EFI_IP_ADDRESS        GatewayIp;\r
+  EFI_IP_ADDRESS        RemoteIp;\r
+  IPv4_DEVICE_PATH      *IPv4DevicePathNode;\r
+  FILEPATH_DEVICE_PATH  *FilePathDevicePath;\r
+  CHAR16                BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
+  UINTN                 BootFilePathSize;\r
 \r
-  Print(L"Get the IP address from DHCP: ");\r
+  Print (L"Get the IP address from DHCP: ");\r
   Status = GetHIInputBoolean (&IsDHCP);\r
-  if (EFI_ERROR(Status)) {\r
+  if (EFI_ERROR (Status)) {\r
     return EFI_ABORTED;\r
   }\r
 \r
   if (!IsDHCP) {\r
-    Print(L"Get the static IP address: ");\r
+    Print (L"Local static IP address: ");\r
     Status = GetHIInputIP (&LocalIp);\r
-    if (EFI_ERROR(Status)) {\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_ABORTED;\r
+    }\r
+    Print (L"Get the network mask: ");\r
+    Status = GetHIInputIP (&SubnetMask);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_ABORTED;\r
+    }\r
+    Print (L"Get the gateway IP address: ");\r
+    Status = GetHIInputIP (&GatewayIp);\r
+    if (EFI_ERROR (Status)) {\r
       return EFI_ABORTED;\r
     }\r
   }\r
 \r
-  Print(L"Get the TFTP server IP address: ");\r
+  Print (L"Get the TFTP server IP address: ");\r
   Status = GetHIInputIP (&RemoteIp);\r
-  if (EFI_ERROR(Status)) {\r
+  if (EFI_ERROR (Status)) {\r
     return EFI_ABORTED;\r
   }\r
 \r
-  Print(L"File path of the %s : ", FileName);\r
+  Print (L"File path of the %s : ", FileName);\r
   Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
-  if (EFI_ERROR(Status)) {\r
+  if (EFI_ERROR (Status)) {\r
     return EFI_ABORTED;\r
   }\r
 \r
@@ -967,7 +1028,13 @@ BdsLoadOptionTftpCreateDevicePath (
   IPv4DevicePathNode->Header.Type    = MESSAGING_DEVICE_PATH;\r
   IPv4DevicePathNode->Header.SubType = MSG_IPv4_DP;\r
   SetDevicePathNodeLength (&IPv4DevicePathNode->Header, sizeof(IPv4_DEVICE_PATH));\r
-  CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+  if (!IsDHCP) {\r
+    CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&IPv4DevicePathNode->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&IPv4DevicePathNode->GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
+  }\r
+\r
   CopyMem (&IPv4DevicePathNode->RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
   IPv4DevicePathNode->LocalPort  = 0;\r
   IPv4DevicePathNode->RemotePort = 0;\r
@@ -1021,7 +1088,11 @@ BdsLoadOptionTftpUpdateDevicePath (
   IPv4_DEVICE_PATH       Ipv4Node;\r
   BOOLEAN                IsDHCP;\r
   EFI_IP_ADDRESS         OldIp;\r
+  EFI_IP_ADDRESS         OldSubnetMask;\r
+  EFI_IP_ADDRESS         OldGatewayIp;\r
   EFI_IP_ADDRESS         LocalIp;\r
+  EFI_IP_ADDRESS         SubnetMask;\r
+  EFI_IP_ADDRESS         GatewayIp;\r
   EFI_IP_ADDRESS         RemoteIp;\r
   UINT8                 *FileNodePtr;\r
   CHAR16                 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
@@ -1074,9 +1145,7 @@ BdsLoadOptionTftpUpdateDevicePath (
   if (!IsDHCP) {\r
     Print (L"Local static IP address: ");\r
     if (Ipv4Node.StaticIpAddress) {\r
-      // Copy local IPv4 address into IPv4 or IPv6 union\r
       CopyMem (&OldIp.v4, &Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
-\r
       Status = EditHIInputIP (&OldIp, &LocalIp);\r
     } else {\r
       Status = GetHIInputIP (&LocalIp);\r
@@ -1084,6 +1153,28 @@ BdsLoadOptionTftpUpdateDevicePath (
     if (EFI_ERROR (Status)) {\r
       goto ErrorExit;\r
     }\r
+\r
+    Print (L"Get the network mask: ");\r
+    if (Ipv4Node.StaticIpAddress) {\r
+      CopyMem (&OldSubnetMask.v4, &Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+      Status = EditHIInputIP (&OldSubnetMask, &SubnetMask);\r
+    } else {\r
+      Status = GetHIInputIP (&SubnetMask);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      goto ErrorExit;\r
+    }\r
+\r
+    Print (L"Get the gateway IP address: ");\r
+    if (Ipv4Node.StaticIpAddress) {\r
+      CopyMem (&OldGatewayIp.v4, &Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
+      Status = EditHIInputIP (&OldGatewayIp, &GatewayIp);\r
+    } else {\r
+      Status = GetHIInputIP (&GatewayIp);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      goto ErrorExit;\r
+    }\r
   }\r
 \r
   Print (L"TFTP server IP address: ");\r
@@ -1126,12 +1217,18 @@ BdsLoadOptionTftpUpdateDevicePath (
   //\r
   // Update the IPv4 node. IPv6 case not handled yet.\r
   //\r
-  if (IsDHCP == TRUE) {\r
+  if (IsDHCP) {\r
     Ipv4Node.StaticIpAddress = FALSE;\r
+    ZeroMem (&Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
+    ZeroMem (&Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+    ZeroMem (&Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
   } else {\r
     Ipv4Node.StaticIpAddress = TRUE;\r
+    CopyMem (&Ipv4Node.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&Ipv4Node.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&Ipv4Node.GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
   }\r
-  CopyMem (&Ipv4Node.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
+\r
   CopyMem (&Ipv4Node.RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
   CopyMem (Ipv4NodePtr, &Ipv4Node, sizeof (IPv4_DEVICE_PATH));\r
 \r