Fix bugs in PXE driver when using option 43 for boot server list and boot menu prompt.
authorsfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 24 Aug 2012 08:25:42 +0000 (08:25 +0000)
committersfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 24 Aug 2012 08:25:42 +0000 (08:25 +0000)
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: Ouyang Qian <qian.ouyang@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13676 6f19259b-4bc3-4df7-8a09-765794883524

NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c
NetworkPkg/UefiPxeBcDxe/PxeBcBoot.h
NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.h
NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c

index e26b412..e814d5a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Boot functions implementation for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<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
@@ -86,9 +86,9 @@ PxeBcSelectBootPrompt (
   OfferType    = Mode->UsingIpv6 ? Cache->Dhcp6.OfferType : Cache->Dhcp4.OfferType;\r
 \r
   //\r
-  // Only ProxyPxe10 offer needs boot prompt.\r
+  // Only DhcpPxe10 and ProxyPxe10 offer needs boot prompt.\r
   //\r
-  if (OfferType != PxeOfferTypeProxyPxe10) {\r
+  if (OfferType != PxeOfferTypeProxyPxe10 && OfferType != PxeOfferTypeDhcpPxe10) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
@@ -99,7 +99,7 @@ PxeBcSelectBootPrompt (
 \r
   VendorOpt = &Cache->Dhcp4.VendorOpt;\r
   if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) {\r
-    return EFI_SUCCESS;\r
+    return EFI_TIMEOUT;\r
   }\r
 \r
   Timeout   = VendorOpt->MenuPrompt->Timeout;\r
@@ -110,10 +110,10 @@ PxeBcSelectBootPrompt (
   // The valid scope of Timeout refers to PXE2.1 spec.\r
   //\r
   if (Timeout == 0) {\r
-    return EFI_SUCCESS;\r
+    return EFI_TIMEOUT;\r
   }\r
   if (Timeout == 255) {\r
-    return EFI_TIMEOUT;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   //\r
@@ -173,6 +173,7 @@ PxeBcSelectBootPrompt (
   gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow);\r
   AsciiPrint ("(%d) ", Timeout--);\r
 \r
+  Status = EFI_TIMEOUT;\r
   while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
     if (!EFI_ERROR (gBS->CheckEvent (DescendEvent))) {\r
       gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow);\r
@@ -184,6 +185,7 @@ PxeBcSelectBootPrompt (
     }\r
     //\r
     // Parse the input key by user.\r
+    // If <F8> or <Ctrl> + <M> is pressed, return success to display the boot menu.\r
     //\r
     if (InputKey.ScanCode == 0) {\r
 \r
@@ -196,7 +198,7 @@ PxeBcSelectBootPrompt (
       case CTRL ('m'):\r
       case 'm':\r
       case 'M':\r
-        Status = EFI_TIMEOUT;\r
+        Status = EFI_SUCCESS;\r
         break;\r
 \r
       default:\r
@@ -208,7 +210,7 @@ PxeBcSelectBootPrompt (
       switch (InputKey.ScanCode) {\r
 \r
       case SCAN_F8:\r
-        Status = EFI_TIMEOUT;\r
+        Status = EFI_SUCCESS;\r
         break;\r
 \r
       case SCAN_ESC:\r
@@ -284,10 +286,10 @@ PxeBcSelectBootMenu (
   OfferType = Mode->UsingIpv6 ? Cache->Dhcp6.OfferType : Cache->Dhcp4.OfferType;\r
 \r
   //\r
-  // There is no specified ProxyPxe10 for IPv6 in PXE and UEFI spec.\r
+  // There is no specified DhcpPxe10/ProxyPxe10 for IPv6 in PXE and UEFI spec.\r
   //\r
   ASSERT (!Mode->UsingIpv6);\r
-  ASSERT (OfferType == PxeOfferTypeProxyPxe10);\r
+  ASSERT (OfferType == PxeOfferTypeProxyPxe10 || OfferType == PxeOfferTypeDhcpPxe10);\r
 \r
   VendorOpt = &Cache->Dhcp4.VendorOpt;\r
   if (!IS_VALID_BOOT_MENU (VendorOpt->BitMap)) {\r
@@ -351,7 +353,7 @@ PxeBcSelectBootMenu (
       gBS->Stall (10 * TICKS_PER_MS);\r
     }\r
 \r
-    if (InputKey.ScanCode != 0) {\r
+    if (InputKey.ScanCode == 0) {\r
       switch (InputKey.UnicodeChar) {\r
       case CTRL ('c'):\r
         InputKey.ScanCode = SCAN_ESC;\r
@@ -651,7 +653,7 @@ PxeBcDhcp6BootInfo (
 \r
   @param[in]      Private      Pointer to PxeBc private data.\r
   @param[in]      Type         The type of bootstrap to perform.\r
-  @param[in, out] Info         Pointer to EFI_PXE_BASE_CODE_DISCOVER_INFO.\r
+  @param[in, out] DiscoverInfo Pointer to EFI_PXE_BASE_CODE_DISCOVER_INFO.\r
   @param[out]     BootEntry    Pointer to PXEBC_BOOT_SVR_ENTRY.\r
   @param[out]     SrvList      Pointer to EFI_PXE_BASE_CODE_SRVLIST.\r
 \r
@@ -663,7 +665,7 @@ EFI_STATUS
 PxeBcExtractDiscoverInfo (\r
   IN     PXEBC_PRIVATE_DATA               *Private,\r
   IN     UINT16                           Type,\r
-  IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO  *Info,\r
+  IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO  **DiscoverInfo,\r
      OUT PXEBC_BOOT_SVR_ENTRY             **BootEntry,\r
      OUT EFI_PXE_BASE_CODE_SRVLIST        **SrvList\r
   )\r
@@ -673,8 +675,11 @@ PxeBcExtractDiscoverInfo (
   PXEBC_VENDOR_OPTION             *VendorOpt;\r
   PXEBC_BOOT_SVR_ENTRY            *Entry;\r
   BOOLEAN                         IsFound;\r
+  EFI_PXE_BASE_CODE_DISCOVER_INFO *Info;\r
+  UINT16                          Index;\r
 \r
   Mode = Private->PxeBc.Mode;\r
+  Info = *DiscoverInfo;\r
 \r
   if (Mode->UsingIpv6) {\r
     Info->IpCnt    = 1;\r
@@ -708,7 +713,7 @@ PxeBcExtractDiscoverInfo (
     Info->UseMCast    = (BOOLEAN) !IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl);\r
     Info->UseBCast    = (BOOLEAN) !IS_DISABLE_BCAST_DISCOVER (VendorOpt->DiscoverCtrl);\r
     Info->MustUseList = (BOOLEAN) IS_ENABLE_USE_SERVER_LIST (VendorOpt->DiscoverCtrl);\r
-    Info->UseUCast    = Info->MustUseList;\r
+    Info->UseUCast    = (BOOLEAN) IS_VALID_BOOT_SERVERS (VendorOpt->BitMap);\r
 \r
     if (Info->UseMCast) {\r
       //\r
@@ -719,7 +724,7 @@ PxeBcExtractDiscoverInfo (
 \r
     Info->IpCnt = 0;\r
 \r
-    if (Info->MustUseList) {\r
+    if (Info->UseUCast) {\r
       Entry = VendorOpt->BootSvr;\r
 \r
       while (((UINT8) (Entry - VendorOpt->BootSvr)) < VendorOpt->BootSvrLen) {\r
@@ -735,9 +740,24 @@ PxeBcExtractDiscoverInfo (
       }\r
 \r
       Info->IpCnt = Entry->IpCnt;\r
+      if (Info->IpCnt >= 1) {\r
+        *DiscoverInfo = AllocatePool (sizeof (*Info) + (Info->IpCnt - 1) * sizeof (**SrvList));\r
+        if (*DiscoverInfo == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;       \r
+        }     \r
+        CopyMem (*DiscoverInfo, Info, sizeof (*Info));\r
+        Info = *DiscoverInfo;\r
+      }\r
+\r
+      for (Index = 0; Index < Info->IpCnt; Index++) {\r
+        CopyMem (&Info->SrvList[Index].IpAddr, &Entry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS));\r
+        Info->SrvList[Index].AcceptAnyResponse = !Info->MustUseList;\r
+        Info->SrvList[Index].Type = NTOHS (Entry->Type);\r
+      }\r
     }\r
 \r
     *BootEntry = Entry;\r
+    *SrvList   = Info->SrvList;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -842,12 +862,12 @@ PxeBcDiscoverBootFile (
     //\r
     // Choose by user's input.\r
     //\r
-    Status = PxeBcSelectBootMenu (Private, &Type, TRUE);\r
+    Status = PxeBcSelectBootMenu (Private, &Type, FALSE);\r
   } else if (Status == EFI_TIMEOUT) {\r
     //\r
     // Choose by default item.\r
     //\r
-    Status = PxeBcSelectBootMenu (Private, &Type, FALSE);\r
+    Status = PxeBcSelectBootMenu (Private, &Type, TRUE);\r
   }\r
 \r
   if (!EFI_ERROR (Status)) {\r
@@ -868,6 +888,27 @@ PxeBcDiscoverBootFile (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+\r
+    if (Mode->PxeReplyReceived && !Mode->ProxyOfferReceived) {\r
+      //\r
+      // Some network boot loader only search the packet in Mode.ProxyOffer to get its server\r
+      // IP address, so we need to store a copy of Mode.PxeReply packet into Mode.ProxyOffer.\r
+      //\r
+      if (Mode->UsingIpv6) {\r
+        CopyMem (\r
+          &Mode->ProxyOffer.Dhcpv6,\r
+          &Mode->PxeReply.Dhcpv6,\r
+          Private->PxeReply.Dhcp6.Packet.Ack.Length\r
+          );\r
+      } else {\r
+        CopyMem (\r
+          &Mode->ProxyOffer.Dhcpv4,\r
+          &Mode->PxeReply.Dhcpv4,\r
+          Private->PxeReply.Dhcp4.Packet.Ack.Length\r
+          );      \r
+      }\r
+      Mode->ProxyOfferReceived = TRUE;\r
+    }\r
   }\r
 \r
   //\r
index ef18907..d998200 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Boot functions declaration for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<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
@@ -29,7 +29,7 @@
 \r
   @param[in]      Private      Pointer to PxeBc private data.\r
   @param[in]      Type         The type of bootstrap to perform.\r
-  @param[in, out] Info         Pointer to EFI_PXE_BASE_CODE_DISCOVER_INFO.\r
+  @param[in, out] DiscoverInfo Pointer to EFI_PXE_BASE_CODE_DISCOVER_INFO.\r
   @param[out]     BootEntry    Pointer to PXEBC_BOOT_SVR_ENTRY.\r
   @param[out]     SrvList      Pointer to EFI_PXE_BASE_CODE_SRVLIST.\r
 \r
@@ -41,7 +41,7 @@ EFI_STATUS
 PxeBcExtractDiscoverInfo (\r
   IN     PXEBC_PRIVATE_DATA               *Private,\r
   IN     UINT16                           Type,\r
-  IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO  *Info,\r
+  IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO  **DiscoverInfo,\r
      OUT PXEBC_BOOT_SVR_ENTRY             **BootEntry,\r
      OUT EFI_PXE_BASE_CODE_SRVLIST        **SrvList\r
   );\r
index 60942fb..ecafc86 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Functions implementation related with DHCPv4 for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<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
@@ -1443,7 +1443,7 @@ PxeBcDhcp4Discover (
           break;\r
         }\r
         if ((SrvList[SrvIndex].Type == Type) &&\r
-            EFI_IP4_EQUAL (&Response->Dhcp4.Header.ServerAddr, &Private->ServerIp)) {\r
+            EFI_IP4_EQUAL (&Response->Dhcp4.Header.ServerAddr, &SrvList[SrvIndex].IpAddr)) {\r
           break;\r
         }\r
         SrvIndex++;\r
@@ -1587,6 +1587,7 @@ PxeBcDhcp4Dora (
   AsciiPrint ("\n  Station IP address is ");\r
 \r
   PxeBcShowIp4Addr (&Private->StationIp.v4);\r
+  AsciiPrint ("\n");\r
 \r
 ON_EXIT:\r
   if (EFI_ERROR (Status)) {\r
index bc21b21..37747ac 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Functions declaration related with DHCPv4 for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<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
@@ -146,6 +146,10 @@ typedef enum {
    BIT (PXEBC_VENDOR_TAG_BOOT_MENU) | \\r
    BIT (PXEBC_VENDOR_TAG_MENU_PROMPT))\r
 \r
+#define IS_VALID_BOOT_SERVERS(x) \\r
+  ((((x)[0]) & BIT (PXEBC_VENDOR_TAG_BOOT_SERVERS)) \\r
+   == BIT (PXEBC_VENDOR_TAG_BOOT_SERVERS))  \r
+\r
 #define IS_VALID_BOOT_PROMPT(x) \\r
   ((((x)[0]) & BIT (PXEBC_VENDOR_TAG_MENU_PROMPT)) \\r
    == BIT (PXEBC_VENDOR_TAG_MENU_PROMPT))\r
@@ -256,6 +260,7 @@ typedef union {
   PXEBC_DHCP4_OPTION_MAX_MESG_SIZE  *MaxMesgSize;\r
 } PXEBC_DHCP4_OPTION_ENTRY;\r
 \r
+#pragma pack(1)\r
 typedef struct {\r
   UINT16            Type;\r
   UINT8             IpCnt;\r
@@ -272,6 +277,7 @@ typedef struct {
   UINT8             Timeout;\r
   UINT8             Prompt[1];\r
 } PXEBC_MENU_PROMPT;\r
+#pragma pack()\r
 \r
 typedef struct {\r
   UINT32                BitMap[8];\r
index ba7f948..5f69372 100644 (file)
@@ -529,6 +529,7 @@ EfiPxeBcDiscover (
   UINT16                          Index;\r
   EFI_STATUS                      Status;\r
   EFI_PXE_BASE_CODE_IP_FILTER     IpFilter;\r
+  EFI_PXE_BASE_CODE_DISCOVER_INFO *NewCreatedInfo;\r
 \r
   if (This == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -541,6 +542,7 @@ EfiPxeBcDiscover (
   SrvList                 = NULL;\r
   Status                  = EFI_DEVICE_ERROR;\r
   Private->Function       = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER;\r
+  NewCreatedInfo          = NULL;\r
 \r
   if (!Mode->Started) {\r
     return EFI_NOT_STARTED;\r
@@ -594,12 +596,12 @@ EfiPxeBcDiscover (
     //\r
     // 2. Extract the discover information from the cached packets if unspecified.\r
     //\r
-    Info   = &DefaultInfo;\r
-    Status = PxeBcExtractDiscoverInfo (Private, Type, Info, &BootSvrEntry, &SrvList);\r
+    NewCreatedInfo = &DefaultInfo;\r
+    Status = PxeBcExtractDiscoverInfo (Private, Type, &NewCreatedInfo, &BootSvrEntry, &SrvList);\r
     if (EFI_ERROR (Status)) {\r
       goto ON_EXIT;\r
     }\r
-\r
+    Info = NewCreatedInfo;\r
   } else {\r
     //\r
     // 3. Take the pass-in information as the discover info, and validate the server list.\r
@@ -634,30 +636,7 @@ EfiPxeBcDiscover (
 \r
   Private->IsDoDiscover = TRUE;\r
 \r
-  if (Info->UseUCast) {\r
-    //\r
-    // Do discover by unicast.\r
-    //\r
-    for (Index = 0; Index < Info->IpCnt; Index++) {\r
-      if (BootSvrEntry == NULL) {\r
-        CopyMem (&Private->ServerIp, &SrvList[Index].IpAddr, sizeof (EFI_IP_ADDRESS));\r
-      } else {\r
-        ASSERT (!Mode->UsingIpv6);\r
-        ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS));\r
-        CopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS));\r
-      }\r
-\r
-      Status = PxeBcDiscoverBootServer (\r
-                 Private,\r
-                 Type,\r
-                 Layer,\r
-                 UseBis,\r
-                 &SrvList[Index].IpAddr,\r
-                 0,\r
-                 NULL\r
-                 );\r
-    }\r
-  } else if (Info->UseMCast) {\r
+  if (Info->UseMCast) {\r
     //\r
     // Do discover by multicast.\r
     //\r
@@ -667,8 +646,8 @@ EfiPxeBcDiscover (
                Layer,\r
                UseBis,\r
                &Info->ServerMCastIp,\r
-               0,\r
-               NULL\r
+               Info->IpCnt,\r
+               SrvList\r
                );\r
 \r
   } else if (Info->UseBCast) {\r
@@ -685,6 +664,30 @@ EfiPxeBcDiscover (
                Info->IpCnt,\r
                SrvList\r
                );\r
+\r
+  } else if (Info->UseUCast) {\r
+    //\r
+    // Do discover by unicast.\r
+    //\r
+    for (Index = 0; Index < Info->IpCnt; Index++) {\r
+      if (BootSvrEntry == NULL) {\r
+        CopyMem (&Private->ServerIp, &SrvList[Index].IpAddr, sizeof (EFI_IP_ADDRESS));\r
+      } else {\r
+        ASSERT (!Mode->UsingIpv6);\r
+        ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS));\r
+        CopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS));\r
+      }\r
+\r
+      Status = PxeBcDiscoverBootServer (\r
+                 Private,\r
+                 Type,\r
+                 Layer,\r
+                 UseBis,\r
+                 &Private->ServerIp,\r
+                 Info->IpCnt,\r
+                 SrvList\r
+                 );\r
+      }\r
   }\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -698,8 +701,8 @@ EfiPxeBcDiscover (
       if (!EFI_ERROR (Status)) {\r
         CopyMem (\r
           &Mode->PxeReply.Dhcpv6,\r
-          &Private->PxeReply.Dhcp6.Packet.Offer,\r
-          Private->PxeReply.Dhcp6.Packet.Offer.Length\r
+          &Private->PxeReply.Dhcp6.Packet.Ack.Dhcp6,\r
+          Private->PxeReply.Dhcp6.Packet.Ack.Length\r
           );\r
         Mode->PxeReplyReceived = TRUE;\r
         Mode->PxeDiscoverValid = TRUE;\r
@@ -709,8 +712,8 @@ EfiPxeBcDiscover (
       if (!EFI_ERROR (Status)) {\r
         CopyMem (\r
           &Mode->PxeReply.Dhcpv4,\r
-          &Private->PxeReply.Dhcp4.Packet.Offer,\r
-          Private->PxeReply.Dhcp4.Packet.Offer.Length\r
+          &Private->PxeReply.Dhcp4.Packet.Ack.Dhcp4,\r
+          Private->PxeReply.Dhcp4.Packet.Ack.Length\r
           );\r
         Mode->PxeReplyReceived = TRUE;\r
         Mode->PxeDiscoverValid = TRUE;\r
@@ -720,6 +723,10 @@ EfiPxeBcDiscover (
 \r
 ON_EXIT:\r
 \r
+  if (NewCreatedInfo != NULL && NewCreatedInfo != &DefaultInfo) {\r
+    FreePool (NewCreatedInfo);\r
+  }\r
+  \r
   if (Mode->UsingIpv6) {\r
     Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);\r
   } else {\r