]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c
NetworkPkg: Add assert for buffer pointer from DHCP driver.
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcBoot.c
index e814d5a84c48da4f361a924782c1889803de1c79..1f8895fdaa68480046a972169a78084004603eb0 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   Boot functions implementation for UefiPxeBc Driver.\r
 \r
 /** @file\r
   Boot functions implementation for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -98,6 +99,17 @@ PxeBcSelectBootPrompt (
   ASSERT (!Mode->UsingIpv6);\r
 \r
   VendorOpt = &Cache->Dhcp4.VendorOpt;\r
   ASSERT (!Mode->UsingIpv6);\r
 \r
   VendorOpt = &Cache->Dhcp4.VendorOpt;\r
+  //\r
+  // According to the PXE specification 2.1, Table 2-1 PXE DHCP Options,\r
+  // we must not consider a boot prompt or boot menu if all of the following hold:\r
+  //   - the PXE_DISCOVERY_CONTROL tag(6) is present inside the Vendor Options(43), and has bit 3 set  \r
+  //   - a boot file name has been presented in the initial DHCP or ProxyDHCP offer packet.\r
+  //\r
+  if (IS_DISABLE_PROMPT_MENU (VendorOpt->DiscoverCtrl) &&\r
+      Cache->Dhcp4.OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {\r
+    return EFI_ABORTED;\r
+  }\r
+  \r
   if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) {\r
     return EFI_TIMEOUT;\r
   }\r
   if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) {\r
     return EFI_TIMEOUT;\r
   }\r
@@ -133,7 +145,7 @@ PxeBcSelectBootPrompt (
   Status = gBS->SetTimer (\r
                   TimeoutEvent,\r
                   TimerRelative,\r
   Status = gBS->SetTimer (\r
                   TimeoutEvent,\r
                   TimerRelative,\r
-                  Timeout * TICKS_PER_SECOND\r
+                  MultU64x32 (Timeout, TICKS_PER_SECOND)\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
@@ -278,7 +290,7 @@ PxeBcSelectBootMenu (
   PXEBC_BOOT_MENU_ENTRY      *MenuArray[PXEBC_MENU_MAX_NUM];\r
 \r
   Finish    = FALSE;\r
   PXEBC_BOOT_MENU_ENTRY      *MenuArray[PXEBC_MENU_MAX_NUM];\r
 \r
   Finish    = FALSE;\r
-  Select    = 1;\r
+  Select    = 0;\r
   Index     = 0;\r
   *Type     = 0;\r
   Mode      = Private->PxeBc.Mode;\r
   Index     = 0;\r
   *Type     = 0;\r
   Mode      = Private->PxeBc.Mode;\r
@@ -457,7 +469,9 @@ PxeBcDhcp4BootInfo (
   EFI_STATUS                  Status;\r
   PXEBC_DHCP4_PACKET_CACHE    *Cache4;\r
   UINT16                      Value;\r
   EFI_STATUS                  Status;\r
   PXEBC_DHCP4_PACKET_CACHE    *Cache4;\r
   UINT16                      Value;\r
-\r
+  PXEBC_VENDOR_OPTION         *VendorOpt;\r
+  PXEBC_BOOT_SVR_ENTRY        *Entry;\r
+  \r
   PxeBc       = &Private->PxeBc;\r
   Mode        = PxeBc->Mode;\r
   Status      = EFI_SUCCESS;\r
   PxeBc       = &Private->PxeBc;\r
   Mode        = PxeBc->Mode;\r
   Status      = EFI_SUCCESS;\r
@@ -474,17 +488,40 @@ PxeBcDhcp4BootInfo (
     Cache4 = &Private->DhcpAck.Dhcp4;\r
   }\r
 \r
     Cache4 = &Private->DhcpAck.Dhcp4;\r
   }\r
 \r
+  ASSERT (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL);\r
+\r
   //\r
   //\r
-  // Parse the boot server Ipv4 address by next server address.\r
-  // If this field isn't available, use option 54 instead.\r
+  // Parse the boot server address.\r
+  // If prompt/discover is disabled, get the first boot server from the boot servers list.\r
+  // Otherwise, parse the boot server Ipv4 address from next server address field in DHCP header.\r
+  // If all these fields are not available, use option 54 instead.\r
   //\r
   //\r
-  CopyMem (\r
-    &Private->ServerIp,\r
-    &Cache4->Packet.Offer.Dhcp4.Header.ServerAddr,\r
-    sizeof (EFI_IPv4_ADDRESS)\r
-    );\r
-\r
+  VendorOpt = &Cache4->VendorOpt;\r
+  if (IS_DISABLE_PROMPT_MENU (VendorOpt->DiscoverCtrl) && IS_VALID_BOOT_SERVERS (VendorOpt->BitMap)) {\r
+    Entry = VendorOpt->BootSvr;\r
+    if (VendorOpt->BootSvrLen >= sizeof (PXEBC_BOOT_SVR_ENTRY) && Entry->IpCnt > 0) {\r
+      CopyMem (\r
+        &Private->ServerIp,\r
+        &Entry->IpAddr[0],\r
+        sizeof (EFI_IPv4_ADDRESS)\r
+        );\r
+    }\r
+  }\r
+  if (Private->ServerIp.Addr[0] == 0) {\r
+    //\r
+    // ServerIp.Addr[0] equals zero means we failed to get IP address from boot server list.\r
+    // Try to use next server address field.\r
+    //\r
+    CopyMem (\r
+      &Private->ServerIp,\r
+      &Cache4->Packet.Offer.Dhcp4.Header.ServerAddr,\r
+      sizeof (EFI_IPv4_ADDRESS)\r
+      );\r
+  }\r
   if (Private->ServerIp.Addr[0] == 0) {\r
   if (Private->ServerIp.Addr[0] == 0) {\r
+    //\r
+    // Still failed , use the IP address from option 54.\r
+    //\r
     CopyMem (\r
       &Private->ServerIp,\r
       Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->Data,\r
     CopyMem (\r
       &Private->ServerIp,\r
       Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->Data,\r
@@ -495,7 +532,6 @@ PxeBcDhcp4BootInfo (
   //\r
   // Parse the boot file name by option.\r
   //\r
   //\r
   // Parse the boot file name by option.\r
   //\r
-  ASSERT (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL);\r
   Private->BootFileName = Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data;\r
 \r
   if (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN] != NULL) {\r
   Private->BootFileName = Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data;\r
 \r
   if (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN] != NULL) {\r
@@ -584,10 +620,20 @@ PxeBcDhcp6BootInfo (
 \r
   ASSERT (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] != NULL);\r
 \r
 \r
   ASSERT (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] != NULL);\r
 \r
+  //\r
+  // Set the station address to IP layer.\r
+  //\r
+  Status = PxeBcSetIp6Address (Private);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+\r
   //\r
   // Parse (m)tftp server ip address and bootfile name.\r
   //\r
   Status = PxeBcExtractBootFileUrl (\r
   //\r
   // Parse (m)tftp server ip address and bootfile name.\r
   //\r
   Status = PxeBcExtractBootFileUrl (\r
+             Private,\r
              &Private->BootFileName,\r
              &Private->ServerIp.v6,\r
              (CHAR8 *) (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data),\r
              &Private->BootFileName,\r
              &Private->ServerIp.v6,\r
              (CHAR8 *) (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data),\r
@@ -948,7 +994,7 @@ PxeBcInstallCallback (
   //\r
   PxeBc  = &Private->PxeBc;\r
   Status = gBS->HandleProtocol (\r
   //\r
   PxeBc  = &Private->PxeBc;\r
   Status = gBS->HandleProtocol (\r
-                  Private->Controller,\r
+                  Private->Mode.UsingIpv6 ? Private->Ip6Nic->Controller : Private->Ip4Nic->Controller,\r
                   &gEfiPxeBaseCodeCallbackProtocolGuid,\r
                   (VOID **) &Private->PxeBcCallback\r
                   );\r
                   &gEfiPxeBaseCodeCallbackProtocolGuid,\r
                   (VOID **) &Private->PxeBcCallback\r
                   );\r
@@ -964,7 +1010,7 @@ PxeBcInstallCallback (
     // Install a default callback if user didn't offer one.\r
     //\r
     Status = gBS->InstallProtocolInterface (\r
     // Install a default callback if user didn't offer one.\r
     //\r
     Status = gBS->InstallProtocolInterface (\r
-                    &Private->Controller,\r
+                    Private->Mode.UsingIpv6 ? &Private->Ip6Nic->Controller : &Private->Ip4Nic->Controller,\r
                     &gEfiPxeBaseCodeCallbackProtocolGuid,\r
                     EFI_NATIVE_INTERFACE,\r
                     &Private->LoadFileCallback\r
                     &gEfiPxeBaseCodeCallbackProtocolGuid,\r
                     EFI_NATIVE_INTERFACE,\r
                     &Private->LoadFileCallback\r
@@ -1008,7 +1054,7 @@ PxeBcUninstallCallback (
     PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, &NewMakeCallback);\r
 \r
     gBS->UninstallProtocolInterface (\r
     PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, &NewMakeCallback);\r
 \r
     gBS->UninstallProtocolInterface (\r
-          Private->Controller,\r
+          Private->Mode.UsingIpv6 ? Private->Ip6Nic->Controller : Private->Ip4Nic->Controller,\r
           &gEfiPxeBaseCodeCallbackProtocolGuid,\r
           &Private->LoadFileCallback\r
           );\r
           &gEfiPxeBaseCodeCallbackProtocolGuid,\r
           &Private->LoadFileCallback\r
           );\r
@@ -1185,7 +1231,7 @@ ON_EXIT:
   PxeBcUninstallCallback(Private, NewMakeCallback);\r
 \r
   if (Status == EFI_SUCCESS) {\r
   PxeBcUninstallCallback(Private, NewMakeCallback);\r
 \r
   if (Status == EFI_SUCCESS) {\r
-    AsciiPrint ("\n  Succeed to download NBP file.\n");\r
+    AsciiPrint ("\n  NBP file downloaded successfully.\n");\r
     return EFI_SUCCESS;\r
   } else if (Status == EFI_BUFFER_TOO_SMALL && Buffer != NULL) {\r
     AsciiPrint ("\n  PXE-E05: Buffer size is smaller than the requested file.\n");\r
     return EFI_SUCCESS;\r
   } else if (Status == EFI_BUFFER_TOO_SMALL && Buffer != NULL) {\r
     AsciiPrint ("\n  PXE-E05: Buffer size is smaller than the requested file.\n");\r
@@ -1196,7 +1242,7 @@ ON_EXIT:
   } else if (Status == EFI_NO_MEDIA) {\r
     AsciiPrint ("\n  PXE-E12: Could not detect network connection.\n");\r
   } else if (Status == EFI_NO_RESPONSE) {\r
   } else if (Status == EFI_NO_MEDIA) {\r
     AsciiPrint ("\n  PXE-E12: Could not detect network connection.\n");\r
   } else if (Status == EFI_NO_RESPONSE) {\r
-    AsciiPrint ("\n  PXE-E16: No offer received.\n");\r
+    AsciiPrint ("\n  PXE-E16: No valid offer received.\n");\r
   } else if (Status == EFI_TIMEOUT) {\r
     AsciiPrint ("\n  PXE-E18: Server response timeout.\n");\r
   } else if (Status == EFI_ABORTED) {\r
   } else if (Status == EFI_TIMEOUT) {\r
     AsciiPrint ("\n  PXE-E18: Server response timeout.\n");\r
   } else if (Status == EFI_ABORTED) {\r