enhanced UefiPxeBcDxe to support
authorvanjeff <vanjeff@de2fecce-e211-0410-80a6-f3fac2684e05>
Wed, 2 Apr 2008 08:45:36 +0000 (08:45 +0000)
committervanjeff <vanjeff@de2fecce-e211-0410-80a6-f3fac2684e05>
Wed, 2 Apr 2008 08:45:36 +0000 (08:45 +0000)
1. AutoArp. 2. SendGuid. 3 TftpError. 4. IcmpError. 5. RouteTable. 6. ArpCache.

git-svn-id: https://edk2.tianocore.org/svn/edk2/trunk@4981 de2fecce-e211-0410-80a6-f3fac2684e05

edk2/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
edk2/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.h
edk2/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c
edk2/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c
edk2/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c
edk2/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c
edk2/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c
edk2/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h
edk2/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c
edk2/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h
edk2/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf

index 514e33e..77f65d5 100644 (file)
@@ -57,7 +57,7 @@ EfiDhcp4GetModeData (
   }\r
 \r
   Instance = DHCP_INSTANCE_FROM_THIS (This);\r
-  \r
+\r
   OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
   DhcpSb  = Instance->Service;\r
 \r
@@ -840,7 +840,7 @@ Returns:
   None\r
 \r
 --*/\r
-{  \r
+{\r
 }\r
 \r
 VOID\r
@@ -873,14 +873,14 @@ PxeDhcpInput (
   }\r
 \r
   ASSERT (UdpPacket != NULL);\r
-  \r
+\r
   //\r
   // Validate the packet received\r
   //\r
   if (UdpPacket->TotalSize < sizeof (EFI_DHCP4_HEADER)) {\r
     goto RESTART;\r
   }\r
-  \r
+\r
   //\r
   // Copy the DHCP message to a continuous memory block, make the buffer size\r
   // of the EFI_DHCP4_PACKET a multiple of 4-byte.\r
@@ -900,16 +900,16 @@ PxeDhcpInput (
   if (Packet->Length != UdpPacket->TotalSize) {\r
     goto RESTART;\r
   }\r
-  \r
+\r
   //\r
   // Is this packet the answer to our packet?\r
   //\r
   if ((Head->OpCode != BOOTP_REPLY) ||\r
       (Head->Xid != Token->Packet->Dhcp4.Header.Xid) ||\r
-      !NET_MAC_EQUAL (&DhcpSb->Mac, Head->ClientHwAddr, DhcpSb->HwLen)) {\r
+      (CompareMem (DhcpSb->ClientAddressSendOut, Head->ClientHwAddr, Head->HwAddrLen) != 0)) {\r
     goto RESTART;\r
   }\r
-  \r
+\r
   //\r
   // Validate the options and retrieve the interested options\r
   //\r
@@ -979,7 +979,7 @@ SIGNAL_USER:
 \r
   if (Token->CompletionEvent != NULL) {\r
     gBS->SignalEvent (Token->CompletionEvent);\r
-  }  \r
+  }\r
 }\r
 \r
 \r
@@ -1066,6 +1066,11 @@ EfiDhcp4TransmitReceive (
     goto ON_ERROR;\r
   }\r
 \r
+  //\r
+  // Save the Client Address is sent out\r
+  //\r
+  CopyMem (&DhcpSb->ClientAddressSendOut[0], &Token->Packet->Dhcp4.Header.ClientHwAddr[0], Token->Packet->Dhcp4.Header.HwAddrLen);\r
+\r
   //\r
   // Wrap the DHCP packet into a net buffer.\r
   //\r
index 9297812..d7e4113 100644 (file)
@@ -122,6 +122,7 @@ struct _DHCP_SERVICE {
   EFI_MAC_ADDRESS               Mac;\r
   UINT8                         HwType;\r
   UINT8                         HwLen;\r
+  UINT8                         ClientAddressSendOut[16];\r
 \r
   DHCP_PROTOCOL                 *ActiveChild;\r
   EFI_DHCP4_CONFIG_DATA         ActiveConfig;\r
index 19b897a..9cead84 100644 (file)
@@ -1037,7 +1037,7 @@ DhcpInput (
   //\r
   if ((Head->OpCode != BOOTP_REPLY) ||\r
       (NTOHL (Head->Xid) != DhcpSb->Xid) ||\r
-      !NET_MAC_EQUAL (&DhcpSb->Mac, Head->ClientHwAddr, DhcpSb->HwLen)) {\r
+      (CompareMem (DhcpSb->ClientAddressSendOut, Head->ClientHwAddr, Head->HwAddrLen) != 0)) {\r
     goto RESTART;\r
   }\r
 \r
@@ -1361,6 +1361,12 @@ DhcpSendMessage (
     Packet = NewPacket;\r
   }\r
 \r
+  //\r
+  // Save the Client Address will be sent out\r
+  //\r
+  CopyMem (&DhcpSb->ClientAddressSendOut[0], &Packet->Dhcp4.Header.ClientHwAddr[0], Packet->Dhcp4.Header.HwAddrLen);\r
+\r
+\r
   //\r
   // Wrap it into a netbuf then send it.\r
   //\r
@@ -1492,7 +1498,7 @@ DhcpOnTimerTick (
   DHCP_SERVICE              *DhcpSb;\r
   DHCP_PROTOCOL             *Instance;\r
   EFI_STATUS                Status;\r
-  \r
+\r
   DhcpSb   = (DHCP_SERVICE *) Context;\r
   Instance = DhcpSb->ActiveChild;\r
 \r
@@ -1513,7 +1519,7 @@ DhcpOnTimerTick (
       goto END_SESSION;\r
     }\r
   }\r
-  \r
+\r
   //\r
   // Check the retransmit timer\r
   //\r
@@ -1558,7 +1564,7 @@ DhcpOnTimerTick (
       }\r
     }\r
   }\r
-  \r
+\r
   //\r
   // If an address has been acquired, check whether need to\r
   // refresh or whether it has expired.\r
index d9df1d4..98b6ddd 100644 (file)
@@ -929,8 +929,8 @@ MnpReceivePacket (
 \r
     DEBUG_CODE (\r
       if (Status != EFI_NOT_READY) {\r
-      DEBUG ((EFI_D_ERROR, "MnpReceivePacket: Snp->Receive() = %r.\n", Status));\r
-    }\r
+        DEBUG ((EFI_D_WARN, "MnpReceivePacket: Snp->Receive() = %r.\n", Status));\r
+      }\r
     );\r
 \r
     return Status;\r
index b5381c7..5394680 100644 (file)
@@ -754,11 +754,14 @@ PxeBcDhcpCallBack (
   UINT16                              Value;\r
   EFI_STATUS                          Status;\r
   BOOLEAN                             Received;\r
+  CHAR8                               *SystemSerialNumber;\r
+  EFI_DHCP4_HEADER                    *DhcpHeader;\r
 \r
   if ((Dhcp4Event != Dhcp4RcvdOffer) &&\r
       (Dhcp4Event != Dhcp4SelectOffer) &&\r
       (Dhcp4Event != Dhcp4SendDiscover) &&\r
-      (Dhcp4Event != Dhcp4RcvdAck)) {\r
+      (Dhcp4Event != Dhcp4RcvdAck) &&\r
+      (Dhcp4Event != Dhcp4SendRequest)) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -798,10 +801,32 @@ PxeBcDhcpCallBack (
   switch (Dhcp4Event) {\r
 \r
   case Dhcp4SendDiscover:\r
-    //\r
-    // Cache the dhcp discover packet, of which some information will be used later.\r
-    //\r
-    CopyMem (Mode->DhcpDiscover.Raw, &Packet->Dhcp4, Packet->Length);\r
+  case Dhcp4SendRequest:\r
+    if (Mode->SendGUID) {\r
+      //\r
+      // send the system GUID instead of the MAC address as the hardware address\r
+      // in the DHCP packet header.\r
+      //\r
+      DhcpHeader = &Packet->Dhcp4.Header;\r
+\r
+      if (EFI_ERROR (GetSmbiosSystemGuidAndSerialNumber ((EFI_GUID *) DhcpHeader->ClientHwAddr, &SystemSerialNumber))) {\r
+        //\r
+        // GUID not yet set - send all 0xff's to show programable (via SetVariable)\r
+        // SetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff);\r
+        // GUID not yet set - send all 0's to show not programable\r
+        //\r
+        ZeroMem (DhcpHeader->ClientHwAddr, sizeof (EFI_GUID));\r
+      }\r
+\r
+      DhcpHeader->HwAddrLen = sizeof (EFI_GUID);\r
+    }\r
+\r
+    if (Dhcp4Event == Dhcp4SendDiscover) {\r
+      //\r
+      // Cache the dhcp discover packet, of which some information will be used later.\r
+      //\r
+      CopyMem (Mode->DhcpDiscover.Raw, &Packet->Dhcp4, Packet->Length);\r
+    }\r
 \r
     break;\r
 \r
@@ -1044,6 +1069,9 @@ PxeBcDiscvBootService (
   EFI_DHCP4_PACKET_OPTION             *PxeOpt;\r
   PXEBC_OPTION_BOOT_ITEM              *PxeBootItem;\r
   UINT8                               VendorOptLen;\r
+  CHAR8                               *SystemSerialNumber;\r
+  EFI_DHCP4_HEADER                    *DhcpHeader;\r
+\r
 \r
   Mode      = Private->PxeBc.Mode;\r
   Dhcp4     = Private->Dhcp4;\r
@@ -1098,6 +1126,18 @@ PxeBcDiscvBootService (
     return Status;\r
   }\r
 \r
+  DhcpHeader = &Token.Packet->Dhcp4.Header;\r
+  if (Mode->SendGUID) {\r
+    if (EFI_ERROR (GetSmbiosSystemGuidAndSerialNumber ((EFI_GUID *) DhcpHeader->ClientHwAddr, &SystemSerialNumber))) {\r
+      //\r
+      // GUID not yet set - send all 0's to show not programable\r
+      //\r
+      ZeroMem (DhcpHeader->ClientHwAddr, sizeof (EFI_GUID));\r
+    }\r
+\r
+    DhcpHeader->HwAddrLen = sizeof (EFI_GUID);\r
+  }\r
+\r
   Token.Packet->Dhcp4.Header.Xid      = NET_RANDOM (NetRandomInitSeed ());\r
   Token.Packet->Dhcp4.Header.Reserved = (UINT16) ((IsBCast) ? 0xf000 : 0x0);\r
   CopyMem (&Token.Packet->Dhcp4.Header.ClientAddr, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
index 48a52ce..c8ee1f7 100644 (file)
@@ -220,6 +220,28 @@ PxeBcDriverBindingStart (
     goto ON_ERROR;\r
   }\r
 \r
+  Status = NetLibCreateServiceChild (\r
+             ControllerHandle,\r
+             This->DriverBindingHandle,\r
+             &gEfiIp4ServiceBindingProtocolGuid,\r
+             &Private->Ip4Child\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Private->Ip4Child,\r
+                  &gEfiIp4ProtocolGuid,\r
+                  (VOID **) &Private->Ip4,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   Status = NetLibCreateServiceChild (\r
              ControllerHandle,\r
              This->DriverBindingHandle,\r
@@ -280,6 +302,17 @@ PxeBcDriverBindingStart (
   Private->Udp4CfgData.UseDefaultAddress  = FALSE;\r
 \r
   PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4);\r
+  Private->MacLen = Private->SeedPacket.Dhcp4.Header.HwAddrLen;\r
+  CopyMem (&Private->Mac, &Private->SeedPacket.Dhcp4.Header.ClientHwAddr[0], Private->MacLen);\r
+\r
+\r
+  ZeroMem (&Private->Ip4ConfigData, sizeof (EFI_IP4_CONFIG_DATA));\r
+  Private->Ip4ConfigData.DefaultProtocol   = EFI_IP_PROTO_ICMP;\r
+  Private->Ip4ConfigData.AcceptIcmpErrors  = TRUE;\r
+  Private->Ip4ConfigData.TypeOfService     = DEFAULT_ToS;\r
+  Private->Ip4ConfigData.TimeToLive        = DEFAULT_TTL;\r
+  Private->Ip4ConfigData.DoNotFragment     = FALSE;\r
+  Private->Ip4ConfigData.RawData           = FALSE;\r
 \r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &ControllerHandle,\r
@@ -328,6 +361,22 @@ ON_ERROR:
       );\r
   }\r
 \r
+  if (Private->Ip4Child != NULL) {\r
+    gBS->CloseProtocol (\r
+          Private->Ip4Child,\r
+          &gEfiIp4ProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      This->DriverBindingHandle,\r
+      &gEfiIp4ServiceBindingProtocolGuid,\r
+      Private->Ip4Child\r
+      );\r
+  }\r
+\r
   if (Private->Dhcp4Child != NULL) {\r
     gBS->CloseProtocol (\r
           Private->Dhcp4Child,\r
index 193daf1..abe5a85 100644 (file)
@@ -23,6 +23,204 @@ Abstract:
 \r
 #include "PxeBcImpl.h"\r
 \r
+/**\r
+  Get and record the arp cache\r
+\r
+  @param  This                    Pointer to EFI_PXE_BC_PROTOCOL\r
+\r
+  @retval EFI_SUCCESS             Arp cache updated successfully\r
+  @retval others                  If error occurs when updating arp cache\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+UpdateArpCache (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL     * This\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_STATUS              Status;\r
+  UINT32                  EntryLength;\r
+  UINT32                  EntryCount;\r
+  EFI_ARP_FIND_DATA       *Entries;\r
+  UINT32                  Index;\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode    = Private->PxeBc.Mode;\r
+\r
+  Status = Private->Arp->Find (Private->Arp, TRUE, NULL, &EntryLength, &EntryCount, &Entries, TRUE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Mode->ArpCacheEntries = MIN (EntryCount, EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES);\r
+  for (Index = 0; Index < Mode->ArpCacheEntries; Index ++) {\r
+    CopyMem (&Mode->ArpCache[Index].IpAddr, Entries + 1, Entries->SwAddressLength);\r
+    CopyMem (&Mode->ArpCache[Index].MacAddr, (UINT8 *)(Entries + 1) + Entries->SwAddressLength, Entries->HwAddressLength);\r
+    //\r
+    // Slip to the next FindData.\r
+    //\r
+    Entries = (EFI_ARP_FIND_DATA *)((UINT8 *)Entries + EntryLength);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Timeout routine to catch arp cache.\r
+\r
+  @param  Event              Pointer to EFI_PXE_BC_PROTOCOL\r
+  @param  Context            Context of the timer event\r
+\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ArpCacheUpdateTimeout (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  UpdateArpCache ((EFI_PXE_BASE_CODE_PROTOCOL *) Context);\r
+}\r
+\r
+/**\r
+  Timeout routine to catch arp cache.\r
+\r
+  @param  Event                    Pointer to EFI_PXE_BC_PROTOCOL\r
+  @param  Context\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+FindInArpCache (\r
+  EFI_PXE_BASE_CODE_MODE    *PxeBcMode,\r
+  EFI_IPv4_ADDRESS          *Ip4Addr,\r
+  EFI_MAC_ADDRESS           *MacAddress\r
+  )\r
+{\r
+  UINT32                  Index;\r
+\r
+  for (Index = 0; Index < PxeBcMode->ArpCacheEntries; Index ++) {\r
+    if (EFI_IP4_EQUAL (&PxeBcMode->ArpCache[Index].IpAddr.v4, Ip4Addr)) {\r
+      CopyMem (MacAddress, &PxeBcMode->ArpCache[Index].MacAddr, sizeof (EFI_MAC_ADDRESS));\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Notify function for the ICMP receive token, used to process\r
+  the received ICMP packets.\r
+\r
+  @param  Context               The context passed in by the event notifier.\r
+\r
+  @return None.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+IcmpErrorListenHandlerDpc (\r
+  IN VOID      *Context\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_IP4_RECEIVE_DATA    *RxData;\r
+  EFI_IP4_PROTOCOL        *Ip4;\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  UINTN                   Index;\r
+  UINT32                  CopiedLen;\r
+  UINT8                   *CopiedPointer;\r
+\r
+  Private = (PXEBC_PRIVATE_DATA *) Context;\r
+  Mode    = &Private->Mode;\r
+  Status  = Private->IcmpErrorRcvToken.Status;\r
+  RxData  = Private->IcmpErrorRcvToken.Packet.RxData;\r
+  Ip4     = Private->Ip4;\r
+\r
+  if (EFI_ABORTED == Status) {\r
+    //\r
+    // The reception is actively aborted by the consumer, directly return.\r
+    //\r
+    return;\r
+  }\r
+\r
+  if ((EFI_SUCCESS != Status) || (NULL == RxData)) {\r
+    //\r
+    // Only process the normal packets and the icmp error packets, if RxData is NULL\r
+    // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although\r
+    // this should be a bug of the low layer (IP).\r
+    //\r
+    goto Resume;\r
+  }\r
+\r
+  if ((EFI_IP4 (RxData->Header->SourceAddress) != 0) &&\r
+    !Ip4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {\r
+    //\r
+    // The source address is not zero and it's not a unicast IP address, discard it.\r
+    //\r
+    goto CleanUp;\r
+  }\r
+\r
+  if (!EFI_IP4_EQUAL (&RxData->Header->DestinationAddress, &Mode->StationIp.v4)) {\r
+    //\r
+    // The dest address is not equal to Station Ip address, discard it.\r
+    //\r
+    goto CleanUp;\r
+  }\r
+\r
+  //\r
+  // Constructor ICMP error packet\r
+  //\r
+  CopiedLen = 0;\r
+  CopiedPointer = (UINT8 *) &Mode->IcmpError;\r
+\r
+  for (Index = 0; Index < RxData->FragmentCount; Index ++) {\r
+    CopiedLen += RxData->FragmentTable[Index].FragmentLength;\r
+    if (CopiedLen <= sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)) {\r
+      CopyMem (CopiedPointer, RxData->FragmentTable[Index].FragmentBuffer, RxData->FragmentTable[Index].FragmentLength);\r
+    } else {\r
+      CopyMem (CopiedPointer, RxData->FragmentTable[Index].FragmentBuffer, CopiedLen - sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR));\r
+    }\r
+    CopiedPointer += CopiedLen;\r
+  }\r
+\r
+  goto Resume;\r
+\r
+CleanUp:\r
+  gBS->SignalEvent (RxData->RecycleSignal);\r
+\r
+Resume:\r
+  Ip4->Receive (Ip4, &(Private->IcmpErrorRcvToken));\r
+}\r
+\r
+/**\r
+  Request IcmpErrorListenHandlerDpc as a DPC at TPL_CALLBACK\r
+\r
+  @param  Event                 The event signaled.\r
+  @param  Context               The context passed in by the event notifier.\r
+\r
+  @return None.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+IcmpErrorListenHandler (\r
+  IN EFI_EVENT Event,\r
+  IN VOID      *Context\r
+  )\r
+{\r
+  //\r
+  // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
+  //\r
+  NetLibQueueDpc (TPL_CALLBACK, IcmpErrorListenHandlerDpc, Context);\r
+}\r
 \r
 /**\r
   GC_NOTO: Add function description\r
@@ -53,6 +251,7 @@ EfiPxeBcStart (
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
   EFI_STATUS              Status;\r
 \r
+  CpuDeadLoop ();\r
   if (This == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -88,7 +287,78 @@ EfiPxeBcStart (
   Mode->ToS     = DEFAULT_ToS;\r
   Mode->AutoArp = TRUE;\r
 \r
-  return EFI_SUCCESS;\r
+  //\r
+  // Create the event for Arp Cache checking.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  ArpCacheUpdateTimeout,\r
+                  This,\r
+                  &Private->GetArpCacheEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Start the timeout timer event.\r
+  //\r
+  Status = gBS->SetTimer (\r
+                  Private->GetArpCacheEvent,\r
+                  TimerPeriodic,\r
+                  TICKS_PER_SECOND\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Create ICMP error receiving event\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  IcmpErrorListenHandler,\r
+                  Private,\r
+                  &(Private->IcmpErrorRcvToken.Event)\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = Private->Ip4->Configure (Private->Ip4, &Private->Ip4ConfigData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // start to listen incoming packet\r
+  //\r
+  Status = Private->Ip4->Receive (Private->Ip4, &Private->IcmpErrorRcvToken);\r
+  if (!EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+ON_EXIT:\r
+  Private->Ip4->Configure (Private->Ip4, NULL);\r
+\r
+  if (Private->IcmpErrorRcvToken.Event != NULL) {\r
+    gBS->CloseEvent (Private->IcmpErrorRcvToken.Event);\r
+  }\r
+\r
+  if (Private->GetArpCacheEvent != NULL) {\r
+    gBS->SetTimer (Private->GetArpCacheEvent, TimerCancel, 0);\r
+    gBS->CloseEvent (Private->GetArpCacheEvent);\r
+  }\r
+\r
+  Mode->Started = FALSE;\r
+  Mode->TTL     = 0;\r
+  Mode->ToS     = 0;\r
+  Mode->AutoArp = FALSE;\r
+\r
+  return Status;\r
 }\r
 \r
 \r
@@ -126,8 +396,33 @@ EfiPxeBcStop (
     return EFI_NOT_STARTED;\r
   }\r
 \r
+  Private->Ip4->Cancel (Private->Ip4, NULL);\r
+  //\r
+  // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's\r
+  // events.\r
+  //\r
+  NetLibDispatchDpc ();\r
+\r
+  Private->Ip4->Configure (Private->Ip4, NULL);\r
+\r
+  //\r
+  // Close the ICMP error receiving event.\r
+  //\r
+  gBS->CloseEvent (Private->IcmpErrorRcvToken.Event);\r
+\r
+  //\r
+  // Cancel the TimeoutEvent timer.\r
+  //\r
+  gBS->SetTimer (Private->GetArpCacheEvent, TimerCancel, 0);\r
+\r
+  //\r
+  // Close the TimeoutEvent event.\r
+  //\r
+  gBS->CloseEvent (Private->GetArpCacheEvent);\r
+\r
   Mode->Started = FALSE;\r
 \r
+\r
   //\r
   // Reset and leave joined groups\r
   //\r
@@ -191,6 +486,9 @@ EfiPxeBcDhcp (
   if (!Mode->Started) {\r
     return EFI_NOT_STARTED;\r
   }\r
+\r
+  Mode->IcmpErrorReceived = FALSE;\r
+\r
   //\r
   // Initialize the DHCP options and build the option list\r
   //\r
@@ -234,6 +532,9 @@ EfiPxeBcDhcp (
         //\r
         continue;\r
       }\r
+      if (Status == EFI_ICMP_ERROR) {\r
+        Mode->IcmpErrorReceived = TRUE;\r
+      }\r
       //\r
       // Other error status means the DHCP really fails.\r
       //\r
@@ -286,6 +587,24 @@ EfiPxeBcDhcp (
 \r
       Private->Arp->Configure (Private->Arp, NULL);\r
       Private->Arp->Configure (Private->Arp, &ArpConfigData);\r
+\r
+      //\r
+      // Updated the route table. Fill the first entry.\r
+      //\r
+      Mode->RouteTableEntries                = 1;\r
+      Mode->RouteTable[0].IpAddr.Addr[0]     = Private->StationIp.Addr[0] & Private->SubnetMask.Addr[0];\r
+      Mode->RouteTable[0].SubnetMask.Addr[0] = Private->SubnetMask.Addr[0];\r
+      Mode->RouteTable[0].GwAddr.Addr[0]     = 0;\r
+\r
+      //\r
+      // Create the default route entry if there is a default router.\r
+      //\r
+      if (Private->GatewayIp.Addr[0] != 0) {\r
+        Mode->RouteTableEntries                = 2;\r
+        Mode->RouteTable[1].IpAddr.Addr[0]     = 0;\r
+        Mode->RouteTable[1].SubnetMask.Addr[0] = 0;\r
+        Mode->RouteTable[1].GwAddr.Addr[0]     = Private->GatewayIp.Addr[0];\r
+      }\r
     }\r
   }\r
 \r
@@ -361,6 +680,8 @@ EfiPxeBcDiscover (
     return EFI_NOT_STARTED;\r
   }\r
 \r
+  Mode->IcmpErrorReceived = FALSE;\r
+\r
   //\r
   // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,\r
   //   use the previous setting;\r
@@ -511,8 +832,11 @@ EfiPxeBcDiscover (
   }\r
 \r
   if (EFI_ERROR (Status) || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {\r
-\r
-    Status = EFI_DEVICE_ERROR;\r
+    if (Status == EFI_ICMP_ERROR) {\r
+      Mode->IcmpErrorReceived = TRUE;\r
+    } else {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
   } else {\r
     PxeBcParseCachedDhcpPacket (&Private->PxeReply);\r
   }\r
@@ -571,6 +895,8 @@ EfiPxeBcMtftp (
   PXEBC_PRIVATE_DATA      *Private;\r
   EFI_MTFTP4_CONFIG_DATA  Mtftp4Config;\r
   EFI_STATUS              Status;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_MAC_ADDRESS         TempMacAddr;\r
 \r
   if ((This == NULL) ||\r
       (Filename == NULL) ||\r
@@ -584,6 +910,20 @@ EfiPxeBcMtftp (
 \r
   Status  = EFI_DEVICE_ERROR;\r
   Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode    = &Private->Mode;\r
+\r
+  if (!Mode->AutoArp) {\r
+    //\r
+    // If AutoArp is set false, check arp cache\r
+    //\r
+    UpdateArpCache (This);\r
+    if (!FindInArpCache (Mode, &ServerIp->v4, &TempMacAddr)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  Mode->TftpErrorReceived = FALSE;\r
+  Mode->IcmpErrorReceived = FALSE;\r
 \r
   Mtftp4Config.UseDefaultSetting = FALSE;\r
   Mtftp4Config.TimeoutValue      = PXEBC_MTFTP_TIMEOUT;\r
@@ -666,6 +1006,10 @@ EfiPxeBcMtftp (
     break;\r
   }\r
 \r
+  if (Status == EFI_ICMP_ERROR) {\r
+    Mode->IcmpErrorReceived = TRUE;\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -734,6 +1078,8 @@ EfiPxeBcUdpWrite (
   EFI_STATUS                Status;\r
   BOOLEAN                   IsDone;\r
   UINT16                    RandomSrcPort;\r
+  EFI_PXE_BASE_CODE_MODE    *Mode;\r
+  EFI_MAC_ADDRESS           TempMacAddr;\r
 \r
   IsDone = FALSE;\r
 \r
@@ -762,11 +1108,24 @@ EfiPxeBcUdpWrite (
 \r
   Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
   Udp4    = Private->Udp4;\r
+  Mode    = &Private->Mode;\r
 \r
   if (!Private->AddressIsOk && (SrcIp == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if (!Mode->AutoArp) {\r
+    //\r
+    // If AutoArp is set false, check arp cache\r
+    //\r
+    UpdateArpCache (This);\r
+    if (!FindInArpCache (Mode, &DestIp->v4, &TempMacAddr)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  Mode->IcmpErrorReceived = FALSE;\r
+\r
   if (SrcIp == NULL) {\r
     SrcIp = &Private->StationIp;\r
 \r
@@ -831,6 +1190,9 @@ EfiPxeBcUdpWrite (
 \r
   Status = Udp4->Transmit (Udp4, &Token);\r
   if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_ICMP_ERROR) {\r
+      Mode->IcmpErrorReceived = TRUE;\r
+    }\r
     goto ON_EXIT;\r
   }\r
 \r
@@ -881,7 +1243,7 @@ CheckIpByFilter (
 \r
   CopyMem (&DestIp4Address, &Session->DestinationAddress, sizeof (DestIp4Address));\r
   if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) &&\r
-      IP4_IS_MULTICAST (NTOHL (EFI_IP4 (DestIp4Address)))\r
+      IP4_IS_MULTICAST (EFI_NTOHL (DestIp4Address))\r
       ) {\r
     return TRUE;\r
   }\r
@@ -894,7 +1256,7 @@ CheckIpByFilter (
 \r
   CopyMem (&Ip4Address, &PxeBcMode->StationIp.v4, sizeof (Ip4Address));\r
   if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) &&\r
-      EFI_IP4_EQUAL (&PxeBcMode->StationIp.v4, &DestIp4Address)\r
+      EFI_IP4_EQUAL (&Ip4Address, &DestIp4Address)\r
       ) {\r
     return TRUE;\r
   }\r
@@ -999,6 +1361,8 @@ EfiPxeBcUdpRead (
     return EFI_NOT_STARTED;\r
   }\r
 \r
+  Mode->IcmpErrorReceived = FALSE;\r
+\r
   Status = gBS->CreateEvent (\r
                   EVT_NOTIFY_SIGNAL,\r
                   TPL_NOTIFY,\r
@@ -1013,6 +1377,9 @@ EfiPxeBcUdpRead (
   IsDone = FALSE;\r
   Status = Udp4->Receive (Udp4, &Token);\r
   if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_ICMP_ERROR) {\r
+      Mode->IcmpErrorReceived = TRUE;\r
+    }\r
     goto ON_EXIT;\r
   }\r
 \r
@@ -1338,9 +1705,24 @@ EfiPxeBcArp (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Status = Private->Arp->Request (Private->Arp, &IpAddr->v4, NULL, &TempMacAddr);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+  Mode->IcmpErrorReceived = FALSE;\r
+\r
+  if (!Mode->AutoArp) {\r
+    //\r
+    // If AutoArp is set false, check arp cache\r
+    //\r
+    UpdateArpCache (This);\r
+    if (!FindInArpCache (Mode, &IpAddr->v4, &TempMacAddr)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  } else {\r
+    Status = Private->Arp->Request (Private->Arp, &IpAddr->v4, NULL, &TempMacAddr);\r
+    if (EFI_ERROR (Status)) {\r
+      if (Status == EFI_ICMP_ERROR) {\r
+        Mode->IcmpErrorReceived = TRUE;\r
+      }\r
+      return Status;\r
+    }\r
   }\r
 \r
   if (MacAddr != NULL) {\r
@@ -1519,11 +1901,13 @@ EfiPxeBcSetStationIP (
   }\r
 \r
   if (NewStationIp != NULL) {\r
-    Mode->StationIp = *NewStationIp;\r
+    Mode->StationIp    = *NewStationIp;\r
+    Private->StationIp = *NewStationIp;\r
   }\r
 \r
   if (NewSubnetMask != NULL) {\r
-    Mode->SubnetMask = *NewSubnetMask;\r
+    Mode->SubnetMask    = *NewSubnetMask;\r
+    Private->SubnetMask = *NewSubnetMask;\r
   }\r
 \r
   Private->AddressIsOk = TRUE;\r
@@ -1541,6 +1925,14 @@ EfiPxeBcSetStationIP (
 \r
     Private->Arp->Configure (Private->Arp, NULL);\r
     Private->Arp->Configure (Private->Arp, &ArpConfigData);\r
+\r
+    //\r
+    // Update the route table.\r
+    //\r
+    Mode->RouteTableEntries                = 1;\r
+    Mode->RouteTable[0].IpAddr.Addr[0]     = Private->StationIp.Addr[0] & Private->SubnetMask.Addr[0];\r
+    Mode->RouteTable[0].SubnetMask.Addr[0] = Private->SubnetMask.Addr[0];\r
+    Mode->RouteTable[0].GwAddr.Addr[0]     = 0;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -1964,6 +2356,7 @@ EfiPxeLoadFile (
   BlockSize       = 0x8000;\r
   Status          = EFI_DEVICE_ERROR;\r
 \r
+  CpuDeadLoop ();\r
   if (This == NULL || BufferSize == NULL) {\r
 \r
     return EFI_INVALID_PARAMETER;\r
index cd428e7..4fbdcad 100644 (file)
@@ -36,6 +36,7 @@ typedef struct _PXEBC_PRIVATE_DATA  PXEBC_PRIVATE_DATA;
 #include <Protocol/NetworkInterfaceIdentifier.h>
 #include <Protocol/PxeBaseCodeCallBack.h>
 #include <Protocol/Arp.h>
+#include <Protocol/Ip4.h>
 
 #include <Library/DebugLib.h>
 #include <Library/BaseMemoryLib.h>
@@ -61,9 +62,11 @@ struct _PXEBC_PRIVATE_DATA {
   EFI_HANDLE                                Image;
   EFI_HANDLE                                ArpChild;
   EFI_HANDLE                                Dhcp4Child;
+  EFI_HANDLE                                Ip4Child;
   EFI_HANDLE                                Mtftp4Child;
   EFI_HANDLE                                Udp4Child;
 
+
   EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
 
   EFI_PXE_BASE_CODE_PROTOCOL                PxeBc;
@@ -72,10 +75,13 @@ struct _PXEBC_PRIVATE_DATA {
   EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL       *PxeBcCallback;
   EFI_ARP_PROTOCOL                          *Arp;
   EFI_DHCP4_PROTOCOL                        *Dhcp4;
+  EFI_IP4_PROTOCOL                          *Ip4;
+  EFI_IP4_CONFIG_DATA                       Ip4ConfigData;
   EFI_MTFTP4_PROTOCOL                       *Mtftp4;
   EFI_UDP4_PROTOCOL                         *Udp4;
   EFI_UDP4_CONFIG_DATA                      Udp4CfgData;
 
+
   EFI_PXE_BASE_CODE_MODE                    Mode;
   EFI_PXE_BASE_CODE_FUNCTION                Function;
 
@@ -91,6 +97,8 @@ struct _PXEBC_PRIVATE_DATA {
 
   UINT8                                     OptionBuffer[PXEBC_DHCP4_MAX_OPTION_SIZE];
   EFI_DHCP4_PACKET                          SeedPacket;
+  EFI_MAC_ADDRESS                           Mac;
+  UINT8                                     MacLen;
 
   BOOLEAN                                   SortOffers;
   UINT32                                    NumOffers;
@@ -115,6 +123,12 @@ struct _PXEBC_PRIVATE_DATA {
   UINT32                                    BootpIndex;
   UINT32                                    ProxyIndex[DHCP4_PACKET_TYPE_MAX];
   UINT32                                    BinlIndex[PXEBC_MAX_OFFER_NUM];
+
+  EFI_EVENT                                 GetArpCacheEvent;
+  //\r
+  // token and event used to get ICMP error data from IP\r
+  //\r
+  EFI_IP4_COMPLETION_TOKEN                  IcmpErrorRcvToken;
 };
 
 #define PXEBC_PRIVATE_DATA_FROM_PXEBC(a)          CR (a, PXEBC_PRIVATE_DATA, PxeBc, PXEBC_PRIVATE_DATA_SIGNATURE)
index ce958bb..3b2eb5b 100644 (file)
@@ -60,6 +60,12 @@ PxeBcCheckPacket (
   Callback  = Private->PxeBcCallback;\r
   Status    = EFI_SUCCESS;\r
 \r
+  if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) {\r
+    Private->Mode.TftpErrorReceived = TRUE;\r
+    Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;\r
+    AsciiStrnCpy (Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, 127);\r
+  }\r
+\r
   if (Callback != NULL) {\r
 \r
     Status = Callback->Callback (\r
@@ -152,7 +158,11 @@ PxeBcTftpGetFileSize (
                     );\r
 \r
   if (EFI_ERROR (Status)) {\r
-\r
+    if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) {\r
+      Private->Mode.TftpErrorReceived = TRUE;\r
+      Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;\r
+      AsciiStrnCpy (Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, 127);\r
+    }\r
     goto ON_ERROR;\r
   }\r
 \r
index 9e24a7b..24b916c 100644 (file)
@@ -91,4 +91,6 @@
   gEfiDhcp4ProtocolGuid                            # PROTOCOL ALWAYS_CONSUMED\r
   gEfiUdp4ProtocolGuid                             # PROTOCOL ALWAYS_CONSUMED\r
   gEfiNetworkInterfaceIdentifierProtocolGuid_31    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiIp4ServiceBindingProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiIp4ProtocolGuid                              # PROTOCOL ALWAYS_CONSUMED\r
 \r