3 Copyright (c) 2007 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Interface routines for PxeBc
24 #include "PxeBcImpl.h"
27 Get and record the arp cache
29 @param This Pointer to EFI_PXE_BC_PROTOCOL
31 @retval EFI_SUCCESS Arp cache updated successfully
32 @retval others If error occurs when updating arp cache
38 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
41 PXEBC_PRIVATE_DATA
*Private
;
42 EFI_PXE_BASE_CODE_MODE
*Mode
;
46 EFI_ARP_FIND_DATA
*Entries
;
49 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
50 Mode
= Private
->PxeBc
.Mode
;
52 Status
= Private
->Arp
->Find (Private
->Arp
, TRUE
, NULL
, &EntryLength
, &EntryCount
, &Entries
, TRUE
);
53 if (EFI_ERROR (Status
)) {
57 Mode
->ArpCacheEntries
= MIN (EntryCount
, EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES
);
58 for (Index
= 0; Index
< Mode
->ArpCacheEntries
; Index
++) {
59 CopyMem (&Mode
->ArpCache
[Index
].IpAddr
, Entries
+ 1, Entries
->SwAddressLength
);
60 CopyMem (&Mode
->ArpCache
[Index
].MacAddr
, (UINT8
*)(Entries
+ 1) + Entries
->SwAddressLength
, Entries
->HwAddressLength
);
62 // Slip to the next FindData.
64 Entries
= (EFI_ARP_FIND_DATA
*)((UINT8
*)Entries
+ EntryLength
);
71 Timeout routine to catch arp cache.
73 @param Event Pointer to EFI_PXE_BC_PROTOCOL
74 @param Context Context of the timer event
80 ArpCacheUpdateTimeout (
85 UpdateArpCache ((EFI_PXE_BASE_CODE_PROTOCOL
*) Context
);
89 Timeout routine to catch arp cache.
91 @param Event Pointer to EFI_PXE_BC_PROTOCOL
98 EFI_PXE_BASE_CODE_MODE
*PxeBcMode
,
99 EFI_IPv4_ADDRESS
*Ip4Addr
,
100 EFI_MAC_ADDRESS
*MacAddress
105 for (Index
= 0; Index
< PxeBcMode
->ArpCacheEntries
; Index
++) {
106 if (EFI_IP4_EQUAL (&PxeBcMode
->ArpCache
[Index
].IpAddr
.v4
, Ip4Addr
)) {
107 CopyMem (MacAddress
, &PxeBcMode
->ArpCache
[Index
].MacAddr
, sizeof (EFI_MAC_ADDRESS
));
116 Notify function for the ICMP receive token, used to process
117 the received ICMP packets.
119 @param Context The context passed in by the event notifier.
127 IcmpErrorListenHandlerDpc (
132 EFI_IP4_RECEIVE_DATA
*RxData
;
133 EFI_IP4_PROTOCOL
*Ip4
;
134 PXEBC_PRIVATE_DATA
*Private
;
135 EFI_PXE_BASE_CODE_MODE
*Mode
;
138 UINT8
*CopiedPointer
;
140 Private
= (PXEBC_PRIVATE_DATA
*) Context
;
141 Mode
= &Private
->Mode
;
142 Status
= Private
->IcmpErrorRcvToken
.Status
;
143 RxData
= Private
->IcmpErrorRcvToken
.Packet
.RxData
;
146 if (EFI_ABORTED
== Status
) {
148 // The reception is actively aborted by the consumer, directly return.
153 if ((EFI_SUCCESS
!= Status
) || (NULL
== RxData
)) {
155 // Only process the normal packets and the icmp error packets, if RxData is NULL
156 // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
157 // this should be a bug of the low layer (IP).
162 if ((EFI_IP4 (RxData
->Header
->SourceAddress
) != 0) &&
163 !Ip4IsUnicast (EFI_NTOHL (RxData
->Header
->SourceAddress
), 0)) {
165 // The source address is not zero and it's not a unicast IP address, discard it.
170 if (!EFI_IP4_EQUAL (&RxData
->Header
->DestinationAddress
, &Mode
->StationIp
.v4
)) {
172 // The dest address is not equal to Station Ip address, discard it.
178 // Constructor ICMP error packet
181 CopiedPointer
= (UINT8
*) &Mode
->IcmpError
;
183 for (Index
= 0; Index
< RxData
->FragmentCount
; Index
++) {
184 CopiedLen
+= RxData
->FragmentTable
[Index
].FragmentLength
;
185 if (CopiedLen
<= sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
)) {
186 CopyMem (CopiedPointer
, RxData
->FragmentTable
[Index
].FragmentBuffer
, RxData
->FragmentTable
[Index
].FragmentLength
);
188 CopyMem (CopiedPointer
, RxData
->FragmentTable
[Index
].FragmentBuffer
, CopiedLen
- sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
));
190 CopiedPointer
+= CopiedLen
;
196 gBS
->SignalEvent (RxData
->RecycleSignal
);
199 Ip4
->Receive (Ip4
, &(Private
->IcmpErrorRcvToken
));
203 Request IcmpErrorListenHandlerDpc as a DPC at TPL_CALLBACK
205 @param Event The event signaled.
206 @param Context The context passed in by the event notifier.
214 IcmpErrorListenHandler (
220 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
222 NetLibQueueDpc (TPL_CALLBACK
, IcmpErrorListenHandlerDpc
, Context
);
226 GC_NOTO: Add function description
228 @param This GC_NOTO: add argument
230 @param UseIpv6 GC_NOTO: add argument
233 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
235 @retval EFI_ALREADY_STARTED GC_NOTO: Add description for
237 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
239 @retval EFI_SUCCESS GC_NOTO: Add description for
246 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
250 PXEBC_PRIVATE_DATA
*Private
;
251 EFI_PXE_BASE_CODE_MODE
*Mode
;
256 return EFI_INVALID_PARAMETER
;
259 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
260 Mode
= Private
->PxeBc
.Mode
;
263 return EFI_ALREADY_STARTED
;
268 // IPv6 is not supported now.
270 return EFI_UNSUPPORTED
;
274 // Configure the udp4 instance to let it receive data
276 Status
= Private
->Udp4
->Configure (Private
->Udp4
, &Private
->Udp4CfgData
);
277 if (EFI_ERROR (Status
)) {
281 Private
->AddressIsOk
= FALSE
;
283 ZeroMem (Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
285 Mode
->Started
= TRUE
;
286 Mode
->TTL
= DEFAULT_TTL
;
287 Mode
->ToS
= DEFAULT_ToS
;
288 Mode
->AutoArp
= TRUE
;
291 // Create the event for Arp Cache checking.
293 Status
= gBS
->CreateEvent (
294 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
296 ArpCacheUpdateTimeout
,
298 &Private
->GetArpCacheEvent
300 if (EFI_ERROR (Status
)) {
305 // Start the timeout timer event.
307 Status
= gBS
->SetTimer (
308 Private
->GetArpCacheEvent
,
313 if (EFI_ERROR (Status
)) {
318 // Create ICMP error receiving event
320 Status
= gBS
->CreateEvent (
323 IcmpErrorListenHandler
,
325 &(Private
->IcmpErrorRcvToken
.Event
)
327 if (EFI_ERROR (Status
)) {
331 Status
= Private
->Ip4
->Configure (Private
->Ip4
, &Private
->Ip4ConfigData
);
332 if (EFI_ERROR (Status
)) {
337 // start to listen incoming packet
339 Status
= Private
->Ip4
->Receive (Private
->Ip4
, &Private
->IcmpErrorRcvToken
);
340 if (!EFI_ERROR (Status
)) {
345 Private
->Ip4
->Configure (Private
->Ip4
, NULL
);
347 if (Private
->IcmpErrorRcvToken
.Event
!= NULL
) {
348 gBS
->CloseEvent (Private
->IcmpErrorRcvToken
.Event
);
351 if (Private
->GetArpCacheEvent
!= NULL
) {
352 gBS
->SetTimer (Private
->GetArpCacheEvent
, TimerCancel
, 0);
353 gBS
->CloseEvent (Private
->GetArpCacheEvent
);
356 Mode
->Started
= FALSE
;
359 Mode
->AutoArp
= FALSE
;
366 GC_NOTO: Add function description
368 @param This GC_NOTO: add argument
371 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
373 @retval EFI_NOT_STARTED GC_NOTO: Add description for
375 @retval EFI_SUCCESS GC_NOTO: Add description for
382 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
385 PXEBC_PRIVATE_DATA
*Private
;
386 EFI_PXE_BASE_CODE_MODE
*Mode
;
389 return EFI_INVALID_PARAMETER
;
392 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
393 Mode
= Private
->PxeBc
.Mode
;
395 if (!Mode
->Started
) {
396 return EFI_NOT_STARTED
;
399 Private
->Ip4
->Cancel (Private
->Ip4
, NULL
);
401 // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's
404 NetLibDispatchDpc ();
406 Private
->Ip4
->Configure (Private
->Ip4
, NULL
);
409 // Close the ICMP error receiving event.
411 gBS
->CloseEvent (Private
->IcmpErrorRcvToken
.Event
);
414 // Cancel the TimeoutEvent timer.
416 gBS
->SetTimer (Private
->GetArpCacheEvent
, TimerCancel
, 0);
419 // Close the TimeoutEvent event.
421 gBS
->CloseEvent (Private
->GetArpCacheEvent
);
423 Mode
->Started
= FALSE
;
427 // Reset and leave joined groups
429 Private
->Udp4
->Groups (Private
->Udp4
, FALSE
, NULL
);
431 Private
->Udp4
->Configure (Private
->Udp4
, NULL
);
433 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
434 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
436 Private
->FileSize
= 0;
443 GC_NOTO: Add function description
445 @param This GC_NOTO: add argument
447 @param SortOffers GC_NOTO: add argument
450 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
452 @retval EFI_NOT_STARTED GC_NOTO: Add description for
459 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
460 IN BOOLEAN SortOffers
463 PXEBC_PRIVATE_DATA
*Private
;
464 EFI_PXE_BASE_CODE_MODE
*Mode
;
465 EFI_DHCP4_PROTOCOL
*Dhcp4
;
466 EFI_DHCP4_CONFIG_DATA Dhcp4CfgData
;
467 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
468 EFI_DHCP4_PACKET_OPTION
*OptList
[PXEBC_DHCP4_MAX_OPTION_NUM
];
470 UINT32 DiscoverTimeout
;
473 EFI_ARP_CONFIG_DATA ArpConfigData
;
476 return EFI_INVALID_PARAMETER
;
479 Status
= EFI_SUCCESS
;
480 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
481 Mode
= Private
->PxeBc
.Mode
;
482 Dhcp4
= Private
->Dhcp4
;
483 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
484 Private
->SortOffers
= SortOffers
;
486 if (!Mode
->Started
) {
487 return EFI_NOT_STARTED
;
490 Mode
->IcmpErrorReceived
= FALSE
;
493 // Initialize the DHCP options and build the option list
495 OptCount
= PxeBcBuildDhcpOptions (Private
, OptList
, TRUE
);
498 // Set the DHCP4 config data.
500 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
501 Dhcp4CfgData
.OptionCount
= OptCount
;
502 Dhcp4CfgData
.OptionList
= OptList
;
503 Dhcp4CfgData
.Dhcp4Callback
= PxeBcDhcpCallBack
;
504 Dhcp4CfgData
.CallbackContext
= Private
;
505 Dhcp4CfgData
.DiscoverTryCount
= 1;
506 Dhcp4CfgData
.DiscoverTimeout
= &DiscoverTimeout
;
508 for (Index
= 0; Index
< PXEBC_DHCP4_DISCOVER_RETRIES
; Index
++) {
510 // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.
512 DiscoverTimeout
= (PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT
<< Index
);
514 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
515 if (EFI_ERROR (Status
)) {
519 // Zero those arrays to record the varies numbers of DHCP OFFERS.
521 Private
->NumOffers
= 0;
522 Private
->BootpIndex
= 0;
523 ZeroMem (Private
->ServerCount
, sizeof (Private
->ServerCount
));
524 ZeroMem (Private
->ProxyIndex
, sizeof (Private
->ProxyIndex
));
526 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
527 if (EFI_ERROR (Status
)) {
528 if (Status
== EFI_TIMEOUT
) {
530 // If no response is received or all received offers don't match
531 // the PXE boot requirements, EFI_TIMEOUT will be returned.
535 if (Status
== EFI_ICMP_ERROR
) {
536 Mode
->IcmpErrorReceived
= TRUE
;
539 // Other error status means the DHCP really fails.
544 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
545 if (EFI_ERROR (Status
)) {
549 ASSERT (Dhcp4Mode
.State
== Dhcp4Bound
);
551 CopyMem (&Private
->StationIp
, &Dhcp4Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
552 CopyMem (&Private
->SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
553 CopyMem (&Private
->GatewayIp
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
556 // Check the selected offer to see whether BINL is required, if no or BINL is
557 // finished, set the various Mode members.
559 Status
= PxeBcCheckSelectedOffer (Private
);
560 if (!EFI_ERROR (Status
)) {
565 if (EFI_ERROR (Status
)) {
567 Dhcp4
->Configure (Dhcp4
, NULL
);
570 // Remove the previously configured option list and callback function
572 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
573 Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
575 Private
->AddressIsOk
= TRUE
;
577 if (!Mode
->UsingIpv6
) {
579 // If in IPv4 mode, configure the corresponding ARP with this new
580 // station IP address.
582 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
584 ArpConfigData
.SwAddressType
= 0x0800;
585 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
586 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
588 Private
->Arp
->Configure (Private
->Arp
, NULL
);
589 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
592 // Updated the route table. Fill the first entry.
594 Mode
->RouteTableEntries
= 1;
595 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
596 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
597 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
600 // Create the default route entry if there is a default router.
602 if (Private
->GatewayIp
.Addr
[0] != 0) {
603 Mode
->RouteTableEntries
= 2;
604 Mode
->RouteTable
[1].IpAddr
.Addr
[0] = 0;
605 Mode
->RouteTable
[1].SubnetMask
.Addr
[0] = 0;
606 Mode
->RouteTable
[1].GwAddr
.Addr
[0] = Private
->GatewayIp
.Addr
[0];
616 GC_NOTO: Add function description
618 @param This GC_NOTO: add argument
620 @param Type GC_NOTO: add argument
622 @param Layer GC_NOTO: add argument
624 @param UseBis GC_NOTO: add argument
626 @param Info GC_NOTO: add argument
629 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
631 @retval EFI_NOT_STARTED GC_NOTO: Add description for
633 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
635 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
637 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
639 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
646 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
650 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*Info OPTIONAL
653 PXEBC_PRIVATE_DATA
*Private
;
654 EFI_PXE_BASE_CODE_MODE
*Mode
;
655 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
656 EFI_PXE_BASE_CODE_SRVLIST
*SrvList
;
657 EFI_PXE_BASE_CODE_SRVLIST DefaultSrvList
;
658 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
659 PXEBC_VENDOR_OPTION
*VendorOpt
;
662 PXEBC_BOOT_SVR_ENTRY
*BootSvrEntry
;
665 return EFI_INVALID_PARAMETER
;
668 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
669 Mode
= Private
->PxeBc
.Mode
;
672 Status
= EFI_DEVICE_ERROR
;
673 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
675 if (!Private
->AddressIsOk
) {
676 return EFI_INVALID_PARAMETER
;
679 if (!Mode
->Started
) {
680 return EFI_NOT_STARTED
;
683 Mode
->IcmpErrorReceived
= FALSE
;
686 // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
687 // use the previous setting;
688 // If info isn't offered,
689 // use the cached DhcpAck and ProxyOffer packets.
691 if (*Layer
!= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
) {
693 if (!Mode
->PxeDiscoverValid
|| !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
695 return EFI_INVALID_PARAMETER
;
698 DefaultInfo
.IpCnt
= 1;
699 DefaultInfo
.UseUCast
= TRUE
;
701 DefaultSrvList
.Type
= Type
;
702 DefaultSrvList
.AcceptAnyResponse
= FALSE
;
703 DefaultSrvList
.IpAddr
.Addr
[0] = Private
->ServerIp
.Addr
[0];
705 SrvList
= &DefaultSrvList
;
707 } else if (Info
== NULL
) {
709 // Create info by the cached packet before
711 Packet
= (Mode
->ProxyOfferReceived
) ? &Private
->ProxyOffer
: &Private
->Dhcp4Ack
;
712 VendorOpt
= &Packet
->PxeVendorOption
;
714 if (!Mode
->DhcpAckReceived
|| !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt
->BitMap
)) {
716 // Address is not acquired or no discovery options.
718 return EFI_INVALID_PARAMETER
;
721 DefaultInfo
.UseMCast
= (BOOLEAN
)!IS_DISABLE_MCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
722 DefaultInfo
.UseBCast
= (BOOLEAN
)!IS_DISABLE_BCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
723 DefaultInfo
.MustUseList
= (BOOLEAN
) IS_ENABLE_USE_SERVER_LIST (VendorOpt
->DiscoverCtrl
);
724 DefaultInfo
.UseUCast
= DefaultInfo
.MustUseList
;
726 if (DefaultInfo
.UseMCast
) {
728 // Get the multicast discover ip address from vendor option.
730 CopyMem (&DefaultInfo
.ServerMCastIp
.Addr
, &VendorOpt
->DiscoverMcastIp
, sizeof (EFI_IPv4_ADDRESS
));
733 DefaultInfo
.IpCnt
= 0;
735 if (DefaultInfo
.MustUseList
) {
736 BootSvrEntry
= VendorOpt
->BootSvr
;
737 Status
= EFI_INVALID_PARAMETER
;
739 while (((UINT8
) (BootSvrEntry
- VendorOpt
->BootSvr
)) < VendorOpt
->BootSvrLen
) {
741 if (BootSvrEntry
->Type
== HTONS (Type
)) {
742 Status
= EFI_SUCCESS
;
746 BootSvrEntry
= GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry
);
749 if (EFI_ERROR (Status
)) {
753 DefaultInfo
.IpCnt
= BootSvrEntry
->IpCnt
;
759 SrvList
= Info
->SrvList
;
761 if (!SrvList
[0].AcceptAnyResponse
) {
763 for (Index
= 1; Index
< Info
->IpCnt
; Index
++) {
764 if (SrvList
[Index
].AcceptAnyResponse
) {
769 if (Index
!= Info
->IpCnt
) {
770 return EFI_INVALID_PARAMETER
;
775 if ((!Info
->UseUCast
&& !Info
->UseBCast
&& !Info
->UseMCast
) || (Info
->MustUseList
&& Info
->IpCnt
== 0)) {
777 return EFI_INVALID_PARAMETER
;
780 // Execute discover by UniCast/BroadCast/MultiCast
782 if (Info
->UseUCast
) {
784 for (Index
= 0; Index
< Info
->IpCnt
; Index
++) {
786 if (BootSvrEntry
== NULL
) {
787 Private
->ServerIp
.Addr
[0] = SrvList
[Index
].IpAddr
.Addr
[0];
789 CopyMem (&Private
->ServerIp
, &BootSvrEntry
->IpAddr
[Index
], sizeof (EFI_IPv4_ADDRESS
));
792 Status
= PxeBcDiscvBootService (
797 &SrvList
[Index
].IpAddr
,
801 &Private
->PxeReply
.Packet
.Ack
805 } else if (Info
->UseMCast
) {
807 Status
= PxeBcDiscvBootService (
812 &Info
->ServerMCastIp
,
816 &Private
->PxeReply
.Packet
.Ack
819 } else if (Info
->UseBCast
) {
821 Status
= PxeBcDiscvBootService (
830 &Private
->PxeReply
.Packet
.Ack
834 if (EFI_ERROR (Status
) || !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
835 if (Status
== EFI_ICMP_ERROR
) {
836 Mode
->IcmpErrorReceived
= TRUE
;
838 Status
= EFI_DEVICE_ERROR
;
841 PxeBcParseCachedDhcpPacket (&Private
->PxeReply
);
844 if (Mode
->PxeBisReplyReceived
) {
845 CopyMem (&Private
->ServerIp
, &Mode
->PxeReply
.Dhcpv4
.BootpSiAddr
, sizeof (EFI_IPv4_ADDRESS
));
853 GC_NOTO: Add function description
855 @param This GC_NOTO: add argument
857 @param Operation GC_NOTO: add argument
859 @param BufferPtr GC_NOTO: add argument
861 @param Overwrite GC_NOTO: add argument
863 @param BufferSize GC_NOTO: add argument
865 @param BlockSize GC_NOTO: add argument
867 @param ServerIp GC_NOTO: add argument
869 @param Filename GC_NOTO: add argument
871 @param Info GC_NOTO: add argument
873 @param DontUseBuffer GC_NOTO: add argument
876 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
883 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
884 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
885 IN OUT VOID
*BufferPtr
,
886 IN BOOLEAN Overwrite
,
887 IN OUT UINT64
*BufferSize
,
888 IN UINTN
*BlockSize OPTIONAL
,
889 IN EFI_IP_ADDRESS
*ServerIp
,
891 IN EFI_PXE_BASE_CODE_MTFTP_INFO
*Info OPTIONAL
,
892 IN BOOLEAN DontUseBuffer
895 PXEBC_PRIVATE_DATA
*Private
;
896 EFI_MTFTP4_CONFIG_DATA Mtftp4Config
;
898 EFI_PXE_BASE_CODE_MODE
*Mode
;
899 EFI_MAC_ADDRESS TempMacAddr
;
901 if ((This
== NULL
) ||
902 (Filename
== NULL
) ||
903 (BufferSize
== NULL
) ||
904 ((ServerIp
== NULL
) || !Ip4IsUnicast (NTOHL (ServerIp
->Addr
[0]), 0)) ||
905 ((BufferPtr
== NULL
) && DontUseBuffer
) ||
906 ((BlockSize
!= NULL
) && (*BlockSize
< 512))) {
908 return EFI_INVALID_PARAMETER
;
911 Status
= EFI_DEVICE_ERROR
;
912 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
913 Mode
= &Private
->Mode
;
915 if (!Mode
->AutoArp
) {
917 // If AutoArp is set false, check arp cache
919 UpdateArpCache (This
);
920 if (!FindInArpCache (Mode
, &ServerIp
->v4
, &TempMacAddr
)) {
921 return EFI_DEVICE_ERROR
;
925 Mode
->TftpErrorReceived
= FALSE
;
926 Mode
->IcmpErrorReceived
= FALSE
;
928 Mtftp4Config
.UseDefaultSetting
= FALSE
;
929 Mtftp4Config
.TimeoutValue
= PXEBC_MTFTP_TIMEOUT
;
930 Mtftp4Config
.TryCount
= PXEBC_MTFTP_RETRIES
;
932 CopyMem (&Mtftp4Config
.StationIp
, &Private
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
933 CopyMem (&Mtftp4Config
.SubnetMask
, &Private
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
934 CopyMem (&Mtftp4Config
.GatewayIp
, &Private
->GatewayIp
, sizeof (EFI_IPv4_ADDRESS
));
935 CopyMem (&Mtftp4Config
.ServerIp
, ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
939 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
:
941 Status
= PxeBcTftpGetFileSize (
949 if (!EFI_ERROR (Status
)) {
950 Status
= EFI_BUFFER_TOO_SMALL
;
955 case EFI_PXE_BASE_CODE_TFTP_READ_FILE
:
957 Status
= PxeBcTftpReadFile (
969 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
:
971 Status
= PxeBcTftpWriteFile (
983 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY
:
985 Status
= PxeBcTftpReadDirectory (
997 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE
:
998 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE
:
999 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY
:
1000 Status
= EFI_UNSUPPORTED
;
1005 Status
= EFI_INVALID_PARAMETER
;
1009 if (Status
== EFI_ICMP_ERROR
) {
1010 Mode
->IcmpErrorReceived
= TRUE
;
1018 GC_NOTO: Add function description
1020 @param This GC_NOTO: add argument
1022 @param OpFlags GC_NOTO: add argument
1024 @param DestIp GC_NOTO: add argument
1026 @param DestPort GC_NOTO: add argument
1028 @param GatewayIp GC_NOTO: add argument
1030 @param SrcIp GC_NOTO: add argument
1032 @param SrcPort GC_NOTO: add argument
1034 @param HeaderSize GC_NOTO: add argument
1036 @param HeaderPtr GC_NOTO: add argument
1038 @param BufferSize GC_NOTO: add argument
1040 @param BufferPtr GC_NOTO: add argument
1043 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1045 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1047 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1049 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1051 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1058 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1060 IN EFI_IP_ADDRESS
*DestIp
,
1061 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
,
1062 IN EFI_IP_ADDRESS
*GatewayIp OPTIONAL
,
1063 IN EFI_IP_ADDRESS
*SrcIp OPTIONAL
,
1064 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort OPTIONAL
,
1065 IN UINTN
*HeaderSize OPTIONAL
,
1066 IN VOID
*HeaderPtr OPTIONAL
,
1067 IN UINTN
*BufferSize
,
1071 PXEBC_PRIVATE_DATA
*Private
;
1072 EFI_UDP4_PROTOCOL
*Udp4
;
1073 EFI_UDP4_COMPLETION_TOKEN Token
;
1074 EFI_UDP4_TRANSMIT_DATA
*Udp4TxData
;
1077 EFI_UDP4_SESSION_DATA Udp4Session
;
1080 UINT16 RandomSrcPort
;
1081 EFI_PXE_BASE_CODE_MODE
*Mode
;
1082 EFI_MAC_ADDRESS TempMacAddr
;
1086 if ((This
== NULL
) || (DestIp
== NULL
) || (DestPort
== NULL
)) {
1087 return EFI_INVALID_PARAMETER
;
1090 if ((GatewayIp
!= NULL
) && !Ip4IsUnicast (NTOHL (GatewayIp
->Addr
[0]), 0)) {
1092 // Gateway is provided but it's not a unicast IP address.
1094 return EFI_INVALID_PARAMETER
;
1097 if ((HeaderSize
!= NULL
) && ((*HeaderSize
== 0) || (HeaderPtr
== NULL
))) {
1099 // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
1102 return EFI_INVALID_PARAMETER
;
1105 if ((BufferSize
== NULL
) || ((*BufferSize
!= 0) && (BufferPtr
== NULL
))) {
1106 return EFI_INVALID_PARAMETER
;
1109 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1110 Udp4
= Private
->Udp4
;
1111 Mode
= &Private
->Mode
;
1113 if (!Private
->AddressIsOk
&& (SrcIp
== NULL
)) {
1114 return EFI_INVALID_PARAMETER
;
1117 if (!Mode
->AutoArp
) {
1119 // If AutoArp is set false, check arp cache
1121 UpdateArpCache (This
);
1122 if (!FindInArpCache (Mode
, &DestIp
->v4
, &TempMacAddr
)) {
1123 return EFI_DEVICE_ERROR
;
1127 Mode
->IcmpErrorReceived
= FALSE
;
1129 if (SrcIp
== NULL
) {
1130 SrcIp
= &Private
->StationIp
;
1132 if (GatewayIp
== NULL
) {
1133 GatewayIp
= &Private
->GatewayIp
;
1137 if ((SrcPort
== NULL
) || (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
)) {
1138 RandomSrcPort
= (UINT16
) (NET_RANDOM (NetRandomInitSeed ()) % 10000 + 1024);
1140 if (SrcPort
== NULL
) {
1142 SrcPort
= &RandomSrcPort
;
1145 *SrcPort
= RandomSrcPort
;
1149 ZeroMem (&Token
, sizeof (EFI_UDP4_COMPLETION_TOKEN
));
1150 ZeroMem (&Udp4Session
, sizeof (EFI_UDP4_SESSION_DATA
));
1152 CopyMem (&Udp4Session
.DestinationAddress
, DestIp
, sizeof (EFI_IPv4_ADDRESS
));
1153 Udp4Session
.DestinationPort
= *DestPort
;
1154 CopyMem (&Udp4Session
.SourceAddress
, SrcIp
, sizeof (EFI_IPv4_ADDRESS
));
1155 Udp4Session
.SourcePort
= *SrcPort
;
1157 FragCount
= (HeaderSize
!= NULL
) ? 2 : 1;
1158 Udp4TxData
= (EFI_UDP4_TRANSMIT_DATA
*) AllocatePool (sizeof (EFI_UDP4_TRANSMIT_DATA
) + (FragCount
- 1) * sizeof (EFI_UDP4_FRAGMENT_DATA
));
1159 if (Udp4TxData
== NULL
) {
1160 return EFI_OUT_OF_RESOURCES
;
1163 Udp4TxData
->FragmentCount
= FragCount
;
1164 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentLength
= (UINT32
) *BufferSize
;
1165 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentBuffer
= BufferPtr
;
1166 DataLength
= (UINT32
) *BufferSize
;
1168 if (FragCount
== 2) {
1170 Udp4TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) *HeaderSize
;
1171 Udp4TxData
->FragmentTable
[0].FragmentBuffer
= HeaderPtr
;
1172 DataLength
+= (UINT32
) *HeaderSize
;
1175 Udp4TxData
->GatewayAddress
= (EFI_IPv4_ADDRESS
*) GatewayIp
;
1176 Udp4TxData
->UdpSessionData
= &Udp4Session
;
1177 Udp4TxData
->DataLength
= DataLength
;
1178 Token
.Packet
.TxData
= Udp4TxData
;
1180 Status
= gBS
->CreateEvent (
1187 if (EFI_ERROR (Status
)) {
1191 Status
= Udp4
->Transmit (Udp4
, &Token
);
1192 if (EFI_ERROR (Status
)) {
1193 if (Status
== EFI_ICMP_ERROR
) {
1194 Mode
->IcmpErrorReceived
= TRUE
;
1204 Status
= Token
.Status
;
1208 if (Token
.Event
!= NULL
) {
1209 gBS
->CloseEvent (Token
.Event
);
1212 gBS
->FreePool (Udp4TxData
);
1218 Validate IP packages by IP filter settings
1220 @param PxeBcMode Pointer to EFI_PXEBC_MODE
1222 @param Session Received UDP session
1224 @retval TRUE The UDP package matches IP filters
1226 @retval FLASE The UDP package doesn't matches IP filters
1232 EFI_PXE_BASE_CODE_MODE
*PxeBcMode
,
1233 EFI_UDP4_SESSION_DATA
*Session
1237 EFI_IPv4_ADDRESS Ip4Address
;
1238 EFI_IPv4_ADDRESS DestIp4Address
;
1240 if (PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1244 CopyMem (&DestIp4Address
, &Session
->DestinationAddress
, sizeof (DestIp4Address
));
1245 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) &&
1246 IP4_IS_MULTICAST (EFI_NTOHL (DestIp4Address
))
1251 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) &&
1252 IP4_IS_LOCAL_BROADCAST (EFI_NTOHL (DestIp4Address
))
1257 CopyMem (&Ip4Address
, &PxeBcMode
->StationIp
.v4
, sizeof (Ip4Address
));
1258 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) &&
1259 EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)
1264 for (Index
= 0; Index
< PxeBcMode
->IpFilter
.IpCnt
; ++Index
) {
1265 CopyMem (&Ip4Address
, &PxeBcMode
->IpFilter
.IpList
[Index
].v4
, sizeof (Ip4Address
));
1266 if (EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)) {
1275 GC_NOTO: Add function description
1277 @param This GC_NOTO: add argument
1279 @param OpFlags GC_NOTO: add argument
1281 @param DestIp GC_NOTO: add argument
1283 @param DestPort GC_NOTO: add argument
1285 @param SrcIp GC_NOTO: add argument
1287 @param SrcPort GC_NOTO: add argument
1289 @param HeaderSize GC_NOTO: add argument
1291 @param HeaderPtr GC_NOTO: add argument
1293 @param BufferSize GC_NOTO: add argument
1295 @param BufferPtr GC_NOTO: add argument
1298 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1300 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1302 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1304 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1306 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1308 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1315 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1317 IN OUT EFI_IP_ADDRESS
*DestIp
, OPTIONAL
1318 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
, OPTIONAL
1319 IN OUT EFI_IP_ADDRESS
*SrcIp
, OPTIONAL
1320 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort
, OPTIONAL
1321 IN UINTN
*HeaderSize
, OPTIONAL
1322 IN VOID
*HeaderPtr
, OPTIONAL
1323 IN OUT UINTN
*BufferSize
,
1327 PXEBC_PRIVATE_DATA
*Private
;
1328 EFI_PXE_BASE_CODE_MODE
*Mode
;
1329 EFI_UDP4_PROTOCOL
*Udp4
;
1330 EFI_UDP4_COMPLETION_TOKEN Token
;
1331 EFI_UDP4_RECEIVE_DATA
*RxData
;
1332 EFI_UDP4_SESSION_DATA
*Session
;
1338 if (This
== NULL
|| DestIp
== NULL
|| DestPort
== NULL
) {
1339 return EFI_INVALID_PARAMETER
;
1342 if ((!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (DestPort
== NULL
)) ||
1343 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (SrcIp
== NULL
)) ||
1344 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && (SrcPort
== NULL
))) {
1345 return EFI_INVALID_PARAMETER
;
1348 if (((HeaderSize
!= NULL
) && (*HeaderSize
== 0)) || ((HeaderPtr
== NULL
) && (*HeaderSize
!= 0))) {
1349 return EFI_INVALID_PARAMETER
;
1352 if ((BufferSize
== NULL
) || ((BufferPtr
== NULL
) && (*BufferSize
!= 0))) {
1353 return EFI_INVALID_PARAMETER
;
1356 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1357 Mode
= Private
->PxeBc
.Mode
;
1358 Udp4
= Private
->Udp4
;
1360 if (!Mode
->Started
) {
1361 return EFI_NOT_STARTED
;
1364 Mode
->IcmpErrorReceived
= FALSE
;
1366 Status
= gBS
->CreateEvent (
1373 if (EFI_ERROR (Status
)) {
1374 return EFI_OUT_OF_RESOURCES
;
1378 Status
= Udp4
->Receive (Udp4
, &Token
);
1379 if (EFI_ERROR (Status
)) {
1380 if (Status
== EFI_ICMP_ERROR
) {
1381 Mode
->IcmpErrorReceived
= TRUE
;
1389 Status
= EFI_TIMEOUT
;
1393 // check whether this packet matches the filters
1395 if (EFI_ERROR (Token
.Status
)){
1399 RxData
= Token
.Packet
.RxData
;
1400 Session
= &RxData
->UdpSession
;
1404 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
) {
1406 // Check UDP package by IP filter settings
1408 if (CheckIpByFilter (Mode
, Session
)) {
1415 // Match the destination ip of the received udp dgram
1417 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
) {
1420 if (DestIp
!= NULL
) {
1421 CopyMem (DestIp
, &Session
->DestinationAddress
, sizeof (EFI_IPv4_ADDRESS
));
1424 if (DestIp
!= NULL
) {
1425 if (EFI_IP4_EQUAL (DestIp
, &Session
->DestinationAddress
)) {
1429 if (EFI_IP4_EQUAL (&Private
->StationIp
, &Session
->DestinationAddress
)) {
1438 // Match the destination port of the received udp dgram
1440 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) {
1442 if (DestPort
!= NULL
) {
1443 *DestPort
= Session
->DestinationPort
;
1447 if (*DestPort
!= Session
->DestinationPort
) {
1455 // Match the source ip of the received udp dgram
1457 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) {
1459 if (SrcIp
!= NULL
) {
1460 CopyMem (SrcIp
, &Session
->SourceAddress
, sizeof (EFI_IPv4_ADDRESS
));
1464 if (!EFI_IP4_EQUAL (SrcIp
, &Session
->SourceAddress
)) {
1472 // Match the source port of the received udp dgram
1474 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
1476 if (SrcPort
!= NULL
) {
1477 *SrcPort
= Session
->SourcePort
;
1481 if (*SrcPort
!= Session
->SourcePort
) {
1491 if (HeaderSize
!= NULL
) {
1492 CopyLen
= MIN (*HeaderSize
, RxData
->DataLength
);
1493 CopyMem (HeaderPtr
, RxData
->FragmentTable
[0].FragmentBuffer
, CopyLen
);
1494 *HeaderSize
= CopyLen
;
1497 if (RxData
->DataLength
- CopyLen
> *BufferSize
) {
1499 Status
= EFI_BUFFER_TOO_SMALL
;
1502 *BufferSize
= RxData
->DataLength
- CopyLen
;
1503 CopyMem (BufferPtr
, (UINT8
*) RxData
->FragmentTable
[0].FragmentBuffer
+ CopyLen
, *BufferSize
);
1507 Status
= EFI_TIMEOUT
;
1511 // Recycle the RxData
1513 gBS
->SignalEvent (RxData
->RecycleSignal
);
1518 Udp4
->Cancel (Udp4
, &Token
);
1520 gBS
->CloseEvent (Token
.Event
);
1527 GC_NOTO: Add function description
1529 @param This GC_NOTO: add argument
1531 @param NewFilter GC_NOTO: add argument
1534 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1540 EfiPxeBcSetIpFilter (
1541 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1542 IN EFI_PXE_BASE_CODE_IP_FILTER
*NewFilter
1546 PXEBC_PRIVATE_DATA
*Private
;
1547 EFI_PXE_BASE_CODE_MODE
*Mode
;
1549 BOOLEAN PromiscuousNeed
;
1552 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL.\n"));
1553 return EFI_INVALID_PARAMETER
;
1556 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1557 Mode
= Private
->PxeBc
.Mode
;
1559 if (Private
== NULL
) {
1560 DEBUG ((EFI_D_ERROR
, "PXEBC_PRIVATE_DATA poiner == NULL.\n"));
1561 return EFI_INVALID_PARAMETER
;
1564 if (NewFilter
== NULL
) {
1565 DEBUG ((EFI_D_ERROR
, "IP Filter *NewFilter == NULL.\n"));
1566 return EFI_INVALID_PARAMETER
;
1569 if (!Mode
->Started
) {
1570 DEBUG ((EFI_D_ERROR
, "BC was not started.\n"));
1571 return EFI_NOT_STARTED
;
1574 PromiscuousNeed
= FALSE
;
1575 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1576 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter
->IpList
[Index
].v4
))) {
1578 // The IP is a broadcast address.
1580 DEBUG ((EFI_D_ERROR
, "There is broadcast address in NewFilter.\n"));
1581 return EFI_INVALID_PARAMETER
;
1583 if (Ip4IsUnicast (EFI_IP4 (NewFilter
->IpList
[Index
].v4
), 0) &&
1584 (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
)
1587 // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,
1588 // promiscuous mode is needed.
1590 PromiscuousNeed
= TRUE
;
1595 // Clear the UDP instance configuration, all joined groups will be left
1596 // during the operation.
1598 Private
->Udp4
->Configure (Private
->Udp4
, NULL
);
1599 Private
->Udp4CfgData
.AcceptPromiscuous
= FALSE
;
1600 Private
->Udp4CfgData
.AcceptBroadcast
= FALSE
;
1602 if (PromiscuousNeed
||
1603 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
||
1604 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
1607 // Configure the udp4 filter to receive all packages
1609 Private
->Udp4CfgData
.AcceptPromiscuous
= TRUE
;
1612 // Configure the UDP instance with the new configuration.
1614 Status
= Private
->Udp4
->Configure (Private
->Udp4
, &Private
->Udp4CfgData
);
1615 if (EFI_ERROR (Status
)) {
1621 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) {
1623 // Configure the udp4 filter to receive all broadcast packages
1625 Private
->Udp4CfgData
.AcceptBroadcast
= TRUE
;
1629 // Configure the UDP instance with the new configuration.
1631 Status
= Private
->Udp4
->Configure (Private
->Udp4
, &Private
->Udp4CfgData
);
1632 if (EFI_ERROR (Status
)) {
1636 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1638 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1639 if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter
->IpList
[Index
].v4
))) {
1641 // Join the mutilcast group
1643 Status
= Private
->Udp4
->Groups (Private
->Udp4
, TRUE
, &NewFilter
->IpList
[Index
].v4
);
1644 if (EFI_ERROR (Status
)) {
1654 // Save the new filter.
1656 CopyMem (&Mode
->IpFilter
, NewFilter
, sizeof (Mode
->IpFilter
));
1663 GC_NOTO: Add function description
1665 @param This GC_NOTO: add argument
1667 @param IpAddr GC_NOTO: add argument
1669 @param MacAddr GC_NOTO: add argument
1672 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1679 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1680 IN EFI_IP_ADDRESS
* IpAddr
,
1681 IN EFI_MAC_ADDRESS
* MacAddr OPTIONAL
1684 PXEBC_PRIVATE_DATA
*Private
;
1685 EFI_PXE_BASE_CODE_MODE
*Mode
;
1687 EFI_MAC_ADDRESS TempMacAddr
;
1689 if (This
== NULL
|| IpAddr
== NULL
) {
1690 return EFI_INVALID_PARAMETER
;
1693 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1694 Mode
= Private
->PxeBc
.Mode
;
1696 if (!Mode
->Started
) {
1697 return EFI_NOT_STARTED
;
1700 if (!Private
->AddressIsOk
|| Mode
->UsingIpv6
) {
1702 // We can't resolve the IP address if we don't have a local address now.
1703 // Don't have ARP for IPv6.
1705 return EFI_INVALID_PARAMETER
;
1708 Mode
->IcmpErrorReceived
= FALSE
;
1710 if (!Mode
->AutoArp
) {
1712 // If AutoArp is set false, check arp cache
1714 UpdateArpCache (This
);
1715 if (!FindInArpCache (Mode
, &IpAddr
->v4
, &TempMacAddr
)) {
1716 return EFI_DEVICE_ERROR
;
1719 Status
= Private
->Arp
->Request (Private
->Arp
, &IpAddr
->v4
, NULL
, &TempMacAddr
);
1720 if (EFI_ERROR (Status
)) {
1721 if (Status
== EFI_ICMP_ERROR
) {
1722 Mode
->IcmpErrorReceived
= TRUE
;
1728 if (MacAddr
!= NULL
) {
1729 CopyMem (MacAddr
, &TempMacAddr
, sizeof (EFI_MAC_ADDRESS
));
1738 GC_NOTO: Add function description
1740 @param This GC_NOTO: add argument
1742 @param NewAutoArp GC_NOTO: add argument
1744 @param NewSendGUID GC_NOTO: add argument
1746 @param NewTTL GC_NOTO: add argument
1748 @param NewToS GC_NOTO: add argument
1750 @param NewMakeCallback GC_NOTO: add argument
1753 @return GC_NOTO: add return values
1758 EfiPxeBcSetParameters (
1759 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1760 IN BOOLEAN
*NewAutoArp
, OPTIONAL
1761 IN BOOLEAN
*NewSendGUID
, OPTIONAL
1762 IN UINT8
*NewTTL
, OPTIONAL
1763 IN UINT8
*NewToS
, OPTIONAL
1764 IN BOOLEAN
*NewMakeCallback
// OPTIONAL
1767 PXEBC_PRIVATE_DATA
*Private
;
1768 EFI_PXE_BASE_CODE_MODE
*Mode
;
1771 Status
= EFI_SUCCESS
;
1774 Status
= EFI_INVALID_PARAMETER
;
1778 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1779 Mode
= Private
->PxeBc
.Mode
;
1781 if (NewSendGUID
!= NULL
&& *NewSendGUID
== TRUE
) {
1783 // FixMe, cann't locate SendGuid
1787 if (NewMakeCallback
!= NULL
&& *NewMakeCallback
== TRUE
) {
1789 Status
= gBS
->HandleProtocol (
1790 Private
->Controller
,
1791 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1792 (VOID
**) &Private
->PxeBcCallback
1794 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1796 Status
= EFI_INVALID_PARAMETER
;
1801 if (!Mode
->Started
) {
1802 Status
= EFI_NOT_STARTED
;
1806 if (NewMakeCallback
!= NULL
) {
1808 if (*NewMakeCallback
) {
1810 // Update the Callback protocol.
1812 Status
= gBS
->HandleProtocol (
1813 Private
->Controller
,
1814 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1815 (VOID
**) &Private
->PxeBcCallback
1818 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1819 Status
= EFI_INVALID_PARAMETER
;
1823 Private
->PxeBcCallback
= NULL
;
1826 Mode
->MakeCallbacks
= *NewMakeCallback
;
1829 if (NewAutoArp
!= NULL
) {
1830 Mode
->AutoArp
= *NewAutoArp
;
1833 if (NewSendGUID
!= NULL
) {
1834 Mode
->SendGUID
= *NewSendGUID
;
1837 if (NewTTL
!= NULL
) {
1838 Mode
->TTL
= *NewTTL
;
1841 if (NewToS
!= NULL
) {
1842 Mode
->ToS
= *NewToS
;
1851 GC_NOTO: Add function description
1853 @param This GC_NOTO: add argument
1855 @param NewStationIp GC_NOTO: add argument
1857 @param NewSubnetMask GC_NOTO: add argument
1860 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1862 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1864 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1866 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1868 @retval EFI_SUCCESS GC_NOTO: Add description for
1874 EfiPxeBcSetStationIP (
1875 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1876 IN EFI_IP_ADDRESS
* NewStationIp
, OPTIONAL
1877 IN EFI_IP_ADDRESS
* NewSubnetMask OPTIONAL
1880 PXEBC_PRIVATE_DATA
*Private
;
1881 EFI_PXE_BASE_CODE_MODE
*Mode
;
1882 EFI_ARP_CONFIG_DATA ArpConfigData
;
1885 return EFI_INVALID_PARAMETER
;
1888 if (NewStationIp
!= NULL
&& !Ip4IsUnicast (NTOHL (NewStationIp
->Addr
[0]), 0)) {
1889 return EFI_INVALID_PARAMETER
;
1892 if (NewSubnetMask
!= NULL
&& !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask
->Addr
[0]))) {
1893 return EFI_INVALID_PARAMETER
;
1896 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1897 Mode
= Private
->PxeBc
.Mode
;
1899 if (!Mode
->Started
) {
1900 return EFI_NOT_STARTED
;
1903 if (NewStationIp
!= NULL
) {
1904 Mode
->StationIp
= *NewStationIp
;
1905 Private
->StationIp
= *NewStationIp
;
1908 if (NewSubnetMask
!= NULL
) {
1909 Mode
->SubnetMask
= *NewSubnetMask
;
1910 Private
->SubnetMask
= *NewSubnetMask
;
1913 Private
->AddressIsOk
= TRUE
;
1915 if (!Mode
->UsingIpv6
) {
1917 // If in IPv4 mode, configure the corresponding ARP with this new
1918 // station IP address.
1920 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
1922 ArpConfigData
.SwAddressType
= 0x0800;
1923 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
1924 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
1926 Private
->Arp
->Configure (Private
->Arp
, NULL
);
1927 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
1930 // Update the route table.
1932 Mode
->RouteTableEntries
= 1;
1933 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
1934 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
1935 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
1943 GC_NOTO: Add function description
1945 @param This GC_NOTO: add argument
1947 @param NewDhcpDiscoverValid GC_NOTO: add argument
1949 @param NewDhcpAckReceived GC_NOTO: add argument
1951 @param NewProxyOfferReceived GC_NOTO: add argument
1953 @param NewPxeDiscoverValid GC_NOTO: add argument
1955 @param NewPxeReplyReceived GC_NOTO: add argument
1957 @param NewPxeBisReplyReceived GC_NOTO: add argument
1959 @param NewDhcpDiscover GC_NOTO: add argument
1961 @param NewDhcpAck GC_NOTO: add argument
1963 @param NewProxyOffer GC_NOTO: add argument
1965 @param NewPxeDiscover GC_NOTO: add argument
1967 @param NewPxeReply GC_NOTO: add argument
1969 @param NewPxeBisReply GC_NOTO: add argument
1972 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1974 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1976 @retval EFI_SUCCESS GC_NOTO: Add description for
1982 EfiPxeBcSetPackets (
1983 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1984 IN BOOLEAN
* NewDhcpDiscoverValid
, OPTIONAL
1985 IN BOOLEAN
* NewDhcpAckReceived
, OPTIONAL
1986 IN BOOLEAN
* NewProxyOfferReceived
, OPTIONAL
1987 IN BOOLEAN
* NewPxeDiscoverValid
, OPTIONAL
1988 IN BOOLEAN
* NewPxeReplyReceived
, OPTIONAL
1989 IN BOOLEAN
* NewPxeBisReplyReceived
, OPTIONAL
1990 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
1991 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
1992 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
1993 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
1994 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
1995 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
1998 PXEBC_PRIVATE_DATA
*Private
;
1999 EFI_PXE_BASE_CODE_MODE
*Mode
;
2002 return EFI_INVALID_PARAMETER
;
2005 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
2006 Mode
= Private
->PxeBc
.Mode
;
2008 if (!Mode
->Started
) {
2009 return EFI_NOT_STARTED
;
2012 Private
->FileSize
= 0;
2014 if (NewDhcpDiscoverValid
!= NULL
) {
2015 Mode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
2018 if (NewDhcpAckReceived
!= NULL
) {
2019 Mode
->DhcpAckReceived
= *NewDhcpAckReceived
;
2022 if (NewProxyOfferReceived
!= NULL
) {
2023 Mode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
2026 if (NewPxeDiscoverValid
!= NULL
) {
2027 Mode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
2030 if (NewPxeReplyReceived
!= NULL
) {
2031 Mode
->PxeReplyReceived
= *NewPxeReplyReceived
;
2034 if (NewPxeBisReplyReceived
!= NULL
) {
2035 Mode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
2038 if (NewDhcpDiscover
!= NULL
) {
2039 CopyMem (&Mode
->DhcpDiscover
, NewDhcpDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2042 if (NewDhcpAck
!= NULL
) {
2043 CopyMem (&Mode
->DhcpAck
, NewDhcpAck
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2046 if (NewProxyOffer
!= NULL
) {
2047 CopyMem (&Mode
->ProxyOffer
, NewProxyOffer
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2050 if (NewPxeDiscover
!= NULL
) {
2051 CopyMem (&Mode
->PxeDiscover
, NewPxeDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2054 if (NewPxeReply
!= NULL
) {
2055 CopyMem (&Mode
->PxeReply
, NewPxeReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2058 if (NewPxeBisReply
!= NULL
) {
2059 CopyMem (&Mode
->PxeBisReply
, NewPxeBisReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2065 EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate
= {
2066 EFI_PXE_BASE_CODE_PROTOCOL_REVISION
,
2074 EfiPxeBcSetIpFilter
,
2076 EfiPxeBcSetParameters
,
2077 EfiPxeBcSetStationIP
,
2084 GC_NOTO: Add function description
2086 @param This GC_NOTO: add argument
2088 @param Function GC_NOTO: add argument
2090 @param Received GC_NOTO: add argument
2092 @param PacketLength GC_NOTO: add argument
2094 @param PacketPtr GC_NOTO: add argument
2097 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT GC_NOTO: Add description for
2099 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2101 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2103 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2105 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2109 EFI_PXE_BASE_CODE_CALLBACK_STATUS
2111 EfiPxeLoadFileCallback (
2112 IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL
* This
,
2113 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
2114 IN BOOLEAN Received
,
2115 IN UINT32 PacketLength
,
2116 IN EFI_PXE_BASE_CODE_PACKET
* PacketPtr OPTIONAL
2123 // Catch Ctrl-C or ESC to abort.
2125 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2127 if (!EFI_ERROR (Status
)) {
2129 if (Key
.ScanCode
== SCAN_ESC
|| Key
.UnicodeChar
== (0x1F & 'c')) {
2131 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT
;
2135 // No print if receive packet
2138 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2141 // Print only for three functions
2145 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP
:
2147 // Print only for open MTFTP packets, not every MTFTP packets
2149 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2150 if (PacketPtr
->Raw
[0x1C] != 0x00 || PacketPtr
->Raw
[0x1D] != 0x01) {
2151 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2156 case EFI_PXE_BASE_CODE_FUNCTION_DHCP
:
2157 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
:
2161 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2164 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2166 // Print '.' when transmit a packet
2172 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2175 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate
= {
2176 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION
,
2177 EfiPxeLoadFileCallback
2182 GC_NOTO: Add function description
2184 @param Private GC_NOTO: add argument
2186 @param BufferSize GC_NOTO: add argument
2188 @param Buffer GC_NOTO: add argument
2191 @return GC_NOTO: add return values
2196 IN PXEBC_PRIVATE_DATA
*Private
,
2197 IN OUT UINT64
*BufferSize
,
2201 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2202 EFI_PXE_BASE_CODE_MODE
*Mode
;
2208 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
2211 PxeBc
= &Private
->PxeBc
;
2213 Type
= EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
;
2214 Layer
= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
;
2219 Status
= PxeBc
->Dhcp (PxeBc
, TRUE
);
2220 if (EFI_ERROR (Status
)) {
2225 // Select a boot server
2227 Status
= PxeBcSelectBootPrompt (Private
);
2229 if (Status
== EFI_SUCCESS
) {
2230 Status
= PxeBcSelectBootMenu (Private
, &Type
, TRUE
);
2231 } else if (Status
== EFI_TIMEOUT
) {
2232 Status
= PxeBcSelectBootMenu (Private
, &Type
, FALSE
);
2235 if (!EFI_ERROR (Status
)) {
2237 if (Type
== EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
) {
2239 // Local boot(PXE bootstrap server) need abort
2244 UseBis
= (BOOLEAN
) (Mode
->BisSupported
&& Mode
->BisDetected
);
2245 Status
= PxeBc
->Discover (PxeBc
, Type
, &Layer
, UseBis
, NULL
);
2246 if (EFI_ERROR (Status
)) {
2255 // Get bootfile name and (m)tftp server ip addresss
2257 if (Mode
->PxeReplyReceived
) {
2258 Packet
= &Private
->PxeReply
;
2259 } else if (Mode
->ProxyOfferReceived
) {
2260 Packet
= &Private
->ProxyOffer
;
2262 Packet
= &Private
->Dhcp4Ack
;
2265 CopyMem (&Private
->ServerIp
, &Packet
->Packet
.Offer
.Dhcp4
.Header
.ServerAddr
, sizeof (EFI_IPv4_ADDRESS
));
2266 if (Private
->ServerIp
.Addr
[0] == 0) {
2268 // next server ip address is zero, use option 54 instead
2272 Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_SERVER_ID
]->Data
,
2273 sizeof (EFI_IPv4_ADDRESS
)
2277 ASSERT (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
);
2282 Private
->BootFileName
= (CHAR8
*) (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
]->Data
);
2284 if (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
] != NULL
) {
2286 // Already have the bootfile length option, compute the file size
2288 CopyMem (&Value
, Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
]->Data
, sizeof (Value
));
2289 Value
= NTOHS (Value
);
2290 *BufferSize
= 512 * Value
;
2291 Status
= EFI_BUFFER_TOO_SMALL
;
2294 // Get the bootfile size from tftp
2296 Status
= PxeBc
->Mtftp (
2298 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
,
2304 (UINT8
*) Private
->BootFileName
,
2310 Private
->FileSize
= (UINTN
) *BufferSize
;
2317 GC_NOTO: Add function description
2319 @param This GC_NOTO: add argument
2321 @param FilePath GC_NOTO: add argument
2323 @param BootPolicy GC_NOTO: add argument
2325 @param BufferSize GC_NOTO: add argument
2327 @param Buffer GC_NOTO: add argument
2330 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
2332 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
2339 IN EFI_LOAD_FILE_PROTOCOL
* This
,
2340 IN EFI_DEVICE_PATH_PROTOCOL
* FilePath
,
2341 IN BOOLEAN BootPolicy
,
2342 IN OUT UINTN
*BufferSize
,
2343 IN VOID
*Buffer OPTIONAL
2346 PXEBC_PRIVATE_DATA
*Private
;
2347 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2348 BOOLEAN NewMakeCallback
;
2353 Private
= PXEBC_PRIVATE_DATA_FROM_LOADFILE (This
);
2354 PxeBc
= &Private
->PxeBc
;
2355 NewMakeCallback
= FALSE
;
2357 Status
= EFI_DEVICE_ERROR
;
2360 if (This
== NULL
|| BufferSize
== NULL
) {
2362 return EFI_INVALID_PARAMETER
;
2366 // Only support BootPolicy
2369 return EFI_UNSUPPORTED
;
2372 Status
= PxeBc
->Start (PxeBc
, FALSE
);
2373 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
2377 Status
= gBS
->HandleProtocol (
2378 Private
->Controller
,
2379 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2380 (VOID
**) &Private
->PxeBcCallback
2382 if (Status
== EFI_UNSUPPORTED
) {
2384 CopyMem (&Private
->LoadFileCallback
, &mPxeBcCallBackTemplate
, sizeof (Private
->LoadFileCallback
));
2386 Status
= gBS
->InstallProtocolInterface (
2387 &Private
->Controller
,
2388 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2389 EFI_NATIVE_INTERFACE
,
2390 &Private
->LoadFileCallback
2393 NewMakeCallback
= (BOOLEAN
) (Status
== EFI_SUCCESS
);
2395 Status
= PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2396 if (EFI_ERROR (Status
)) {
2397 PxeBc
->Stop (PxeBc
);
2402 if (Private
->FileSize
== 0) {
2404 Status
= DiscoverBootFile (Private
, &TmpBufSize
, Buffer
);
2406 if (sizeof (UINTN
) < sizeof (UINT64
) && (TmpBufSize
> 0xFFFFFFFF)) {
2407 Status
= EFI_DEVICE_ERROR
;
2409 *BufferSize
= (UINTN
) TmpBufSize
;
2411 } else if (Buffer
== NULL
) {
2412 *BufferSize
= Private
->FileSize
;
2413 Status
= EFI_BUFFER_TOO_SMALL
;
2416 // Download the file.
2418 TmpBufSize
= (UINT64
) (*BufferSize
);
2419 Status
= PxeBc
->Mtftp (
2421 EFI_PXE_BASE_CODE_TFTP_READ_FILE
,
2427 (UINT8
*) Private
->BootFileName
,
2433 // If we added a callback protocol, now is the time to remove it.
2435 if (NewMakeCallback
) {
2437 NewMakeCallback
= FALSE
;
2439 PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2441 gBS
->UninstallProtocolInterface (
2442 Private
->Controller
,
2443 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2444 &Private
->LoadFileCallback
2448 // Check download status
2455 case EFI_BUFFER_TOO_SMALL
:
2456 if (Buffer
!= NULL
) {
2457 AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
2463 case EFI_DEVICE_ERROR
:
2464 AsciiPrint ("PXE-E07: Network device error.\n");
2467 case EFI_OUT_OF_RESOURCES
:
2468 AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
2472 AsciiPrint ("PXE-E12: Could not detect network connection.\n");
2475 case EFI_NO_RESPONSE
:
2476 AsciiPrint ("PXE-E16: No offer received.\n");
2480 AsciiPrint ("PXE-E18: Server response timeout.\n");
2484 AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
2487 case EFI_ICMP_ERROR
:
2488 AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
2491 case EFI_TFTP_ERROR
:
2492 AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
2496 AsciiPrint ("PXE-E99: Unexpected network error.\n");
2500 PxeBc
->Stop (PxeBc
);
2505 EFI_LOAD_FILE_PROTOCOL mLoadFileProtocolTemplate
= { EfiPxeLoadFile
};