summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2008-04-02 08:45:36 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2008-04-02 08:45:36 +0000
commit982a9eaea270fdc05d60d570e3d0e4d168654c05 (patch)
tree1b6c7f82c07fb4d7bf60fea12e3b2aad9631e36a
parent4965dd562e2d858c5085145de9c6a89f1c7bc020 (diff)
downloadedk2-982a9eaea270fdc05d60d570e3d0e4d168654c05.zip
edk2-982a9eaea270fdc05d60d570e3d0e4d168654c05.tar.gz
edk2-982a9eaea270fdc05d60d570e3d0e4d168654c05.tar.bz2
enhanced UefiPxeBcDxe to support
1. AutoArp. 2. SendGuid. 3 TftpError. 4. IcmpError. 5. RouteTable. 6. ArpCache. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4981 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c21
-rw-r--r--MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.h1
-rw-r--r--MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c14
-rw-r--r--MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c4
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c50
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c49
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c413
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h14
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c12
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h1
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf2
11 files changed, 551 insertions, 30 deletions
diff --git a/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c b/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
index 514e33e..77f65d5 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);
- }
+ }
}
@@ -1067,6 +1067,11 @@ EfiDhcp4TransmitReceive (
}
//
+ // 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.
//
Frag.Bulk = (UINT8 *) &Token->Packet->Dhcp4;
diff --git a/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.h b/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.h
index 9297812..d7e4113 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 19b897a..9cead84 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;
}
@@ -1362,6 +1362,12 @@ DhcpSendMessage (
}
//
+ // 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.
//
Frag.Bulk = (UINT8 *) &Packet->Dhcp4.Header;
@@ -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 d9df1d4..98b6ddd 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 b5381c7..5394680 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 48a52ce..c8ee1f7 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c
@@ -223,6 +223,28 @@ PxeBcDriverBindingStart (
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,
&gEfiMtftp4ServiceBindingProtocolGuid,
&Private->Mtftp4Child
);
@@ -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 193daf1..abe5a85 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 cd428e7..4fbdcad 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 <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;
+ //
+ // 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 ce958bb..3b2eb5b 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 79210c1..202f115 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 9e24a7b..24b916c 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