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