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
37 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
40 PXEBC_PRIVATE_DATA
*Private
;
41 EFI_PXE_BASE_CODE_MODE
*Mode
;
45 EFI_ARP_FIND_DATA
*Entries
;
48 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
49 Mode
= Private
->PxeBc
.Mode
;
51 Status
= Private
->Arp
->Find (Private
->Arp
, TRUE
, NULL
, &EntryLength
, &EntryCount
, &Entries
, TRUE
);
52 if (EFI_ERROR (Status
)) {
56 Mode
->ArpCacheEntries
= MIN (EntryCount
, EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES
);
57 for (Index
= 0; Index
< Mode
->ArpCacheEntries
; Index
++) {
58 CopyMem (&Mode
->ArpCache
[Index
].IpAddr
, Entries
+ 1, Entries
->SwAddressLength
);
59 CopyMem (&Mode
->ArpCache
[Index
].MacAddr
, (UINT8
*)(Entries
+ 1) + Entries
->SwAddressLength
, Entries
->HwAddressLength
);
61 // Slip to the next FindData.
63 Entries
= (EFI_ARP_FIND_DATA
*)((UINT8
*)Entries
+ EntryLength
);
70 Timeout routine to catch arp cache.
72 @param Event Pointer to EFI_PXE_BC_PROTOCOL
73 @param Context Context of the timer event
78 ArpCacheUpdateTimeout (
83 UpdateArpCache ((EFI_PXE_BASE_CODE_PROTOCOL
*) Context
);
87 Timeout routine to catch arp cache.
89 @param Event Pointer to EFI_PXE_BC_PROTOCOL
95 EFI_PXE_BASE_CODE_MODE
*PxeBcMode
,
96 EFI_IPv4_ADDRESS
*Ip4Addr
,
97 EFI_MAC_ADDRESS
*MacAddress
102 for (Index
= 0; Index
< PxeBcMode
->ArpCacheEntries
; Index
++) {
103 if (EFI_IP4_EQUAL (&PxeBcMode
->ArpCache
[Index
].IpAddr
.v4
, Ip4Addr
)) {
104 CopyMem (MacAddress
, &PxeBcMode
->ArpCache
[Index
].MacAddr
, sizeof (EFI_MAC_ADDRESS
));
113 Notify function for the ICMP receive token, used to process
114 the received ICMP packets.
116 @param Context The context passed in by the event notifier.
123 IcmpErrorListenHandlerDpc (
128 EFI_IP4_RECEIVE_DATA
*RxData
;
129 EFI_IP4_PROTOCOL
*Ip4
;
130 PXEBC_PRIVATE_DATA
*Private
;
131 EFI_PXE_BASE_CODE_MODE
*Mode
;
134 UINT8
*CopiedPointer
;
136 Private
= (PXEBC_PRIVATE_DATA
*) Context
;
137 Mode
= &Private
->Mode
;
138 Status
= Private
->IcmpErrorRcvToken
.Status
;
139 RxData
= Private
->IcmpErrorRcvToken
.Packet
.RxData
;
142 if (EFI_ABORTED
== Status
) {
144 // The reception is actively aborted by the consumer, directly return.
149 if ((EFI_SUCCESS
!= Status
) || (NULL
== RxData
)) {
151 // Only process the normal packets and the icmp error packets, if RxData is NULL
152 // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
153 // this should be a bug of the low layer (IP).
158 if ((EFI_IP4 (RxData
->Header
->SourceAddress
) != 0) &&
159 !Ip4IsUnicast (EFI_NTOHL (RxData
->Header
->SourceAddress
), 0)) {
161 // The source address is not zero and it's not a unicast IP address, discard it.
166 if (!EFI_IP4_EQUAL (&RxData
->Header
->DestinationAddress
, &Mode
->StationIp
.v4
)) {
168 // The dest address is not equal to Station Ip address, discard it.
174 // Constructor ICMP error packet
177 CopiedPointer
= (UINT8
*) &Mode
->IcmpError
;
179 for (Index
= 0; Index
< RxData
->FragmentCount
; Index
++) {
180 CopiedLen
+= RxData
->FragmentTable
[Index
].FragmentLength
;
181 if (CopiedLen
<= sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
)) {
182 CopyMem (CopiedPointer
, RxData
->FragmentTable
[Index
].FragmentBuffer
, RxData
->FragmentTable
[Index
].FragmentLength
);
184 CopyMem (CopiedPointer
, RxData
->FragmentTable
[Index
].FragmentBuffer
, CopiedLen
- sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
));
186 CopiedPointer
+= CopiedLen
;
192 gBS
->SignalEvent (RxData
->RecycleSignal
);
195 Ip4
->Receive (Ip4
, &(Private
->IcmpErrorRcvToken
));
199 Request IcmpErrorListenHandlerDpc as a DPC at TPL_CALLBACK
201 @param Event The event signaled.
202 @param Context The context passed in by the event notifier.
209 IcmpErrorListenHandler (
215 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
217 NetLibQueueDpc (TPL_CALLBACK
, IcmpErrorListenHandlerDpc
, Context
);
221 GC_NOTO: Add function description
223 @param This GC_NOTO: add argument
225 @param UseIpv6 GC_NOTO: add argument
228 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
230 @retval EFI_ALREADY_STARTED GC_NOTO: Add description for
232 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
234 @retval EFI_SUCCESS GC_NOTO: Add description for
241 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
245 PXEBC_PRIVATE_DATA
*Private
;
246 EFI_PXE_BASE_CODE_MODE
*Mode
;
250 return EFI_INVALID_PARAMETER
;
253 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
254 Mode
= Private
->PxeBc
.Mode
;
257 return EFI_ALREADY_STARTED
;
262 // IPv6 is not supported now.
264 return EFI_UNSUPPORTED
;
268 // Configure the udp4 instance to let it receive data
270 Status
= Private
->Udp4Read
->Configure (Private
->Udp4Read
, &Private
->Udp4CfgData
);
271 if (EFI_ERROR (Status
)) {
275 Private
->AddressIsOk
= FALSE
;
277 ZeroMem (Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
279 Mode
->Started
= TRUE
;
280 Mode
->TTL
= DEFAULT_TTL
;
281 Mode
->ToS
= DEFAULT_ToS
;
282 Mode
->AutoArp
= TRUE
;
285 // Create the event for Arp Cache checking.
287 Status
= gBS
->CreateEvent (
288 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
290 ArpCacheUpdateTimeout
,
292 &Private
->GetArpCacheEvent
294 if (EFI_ERROR (Status
)) {
299 // Start the timeout timer event.
301 Status
= gBS
->SetTimer (
302 Private
->GetArpCacheEvent
,
307 if (EFI_ERROR (Status
)) {
312 // Create ICMP error receiving event
314 Status
= gBS
->CreateEvent (
317 IcmpErrorListenHandler
,
319 &(Private
->IcmpErrorRcvToken
.Event
)
321 if (EFI_ERROR (Status
)) {
325 Status
= Private
->Ip4
->Configure (Private
->Ip4
, &Private
->Ip4ConfigData
);
326 if (EFI_ERROR (Status
)) {
331 // start to listen incoming packet
333 Status
= Private
->Ip4
->Receive (Private
->Ip4
, &Private
->IcmpErrorRcvToken
);
334 if (!EFI_ERROR (Status
)) {
339 Private
->Ip4
->Configure (Private
->Ip4
, NULL
);
341 if (Private
->IcmpErrorRcvToken
.Event
!= NULL
) {
342 gBS
->CloseEvent (Private
->IcmpErrorRcvToken
.Event
);
345 if (Private
->GetArpCacheEvent
!= NULL
) {
346 gBS
->SetTimer (Private
->GetArpCacheEvent
, TimerCancel
, 0);
347 gBS
->CloseEvent (Private
->GetArpCacheEvent
);
350 Mode
->Started
= FALSE
;
353 Mode
->AutoArp
= FALSE
;
360 GC_NOTO: Add function description
362 @param This GC_NOTO: add argument
365 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
367 @retval EFI_NOT_STARTED GC_NOTO: Add description for
369 @retval EFI_SUCCESS GC_NOTO: Add description for
376 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
379 PXEBC_PRIVATE_DATA
*Private
;
380 EFI_PXE_BASE_CODE_MODE
*Mode
;
383 return EFI_INVALID_PARAMETER
;
386 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
387 Mode
= Private
->PxeBc
.Mode
;
389 if (!Mode
->Started
) {
390 return EFI_NOT_STARTED
;
393 Private
->Ip4
->Cancel (Private
->Ip4
, NULL
);
395 // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's
398 NetLibDispatchDpc ();
400 Private
->Ip4
->Configure (Private
->Ip4
, NULL
);
403 // Close the ICMP error receiving event.
405 gBS
->CloseEvent (Private
->IcmpErrorRcvToken
.Event
);
408 // Cancel the TimeoutEvent timer.
410 gBS
->SetTimer (Private
->GetArpCacheEvent
, TimerCancel
, 0);
413 // Close the TimeoutEvent event.
415 gBS
->CloseEvent (Private
->GetArpCacheEvent
);
417 Mode
->Started
= FALSE
;
419 Private
->CurrentUdpSrcPort
= 0;
420 Private
->Udp4Write
->Configure (Private
->Udp4Write
, NULL
);
421 Private
->Udp4Read
->Configure (Private
->Udp4Read
, NULL
);
423 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
424 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
426 Private
->FileSize
= 0;
433 GC_NOTO: Add function description
435 @param This GC_NOTO: add argument
437 @param SortOffers GC_NOTO: add argument
440 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
442 @retval EFI_NOT_STARTED GC_NOTO: Add description for
449 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
450 IN BOOLEAN SortOffers
453 PXEBC_PRIVATE_DATA
*Private
;
454 EFI_PXE_BASE_CODE_MODE
*Mode
;
455 EFI_DHCP4_PROTOCOL
*Dhcp4
;
456 EFI_DHCP4_CONFIG_DATA Dhcp4CfgData
;
457 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
458 EFI_DHCP4_PACKET_OPTION
*OptList
[PXEBC_DHCP4_MAX_OPTION_NUM
];
460 UINT32 DiscoverTimeout
;
463 EFI_ARP_CONFIG_DATA ArpConfigData
;
466 return EFI_INVALID_PARAMETER
;
469 Status
= EFI_SUCCESS
;
470 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
471 Mode
= Private
->PxeBc
.Mode
;
472 Dhcp4
= Private
->Dhcp4
;
473 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
474 Private
->SortOffers
= SortOffers
;
476 if (!Mode
->Started
) {
477 return EFI_NOT_STARTED
;
480 Mode
->IcmpErrorReceived
= FALSE
;
483 // Initialize the DHCP options and build the option list
485 OptCount
= PxeBcBuildDhcpOptions (Private
, OptList
, TRUE
);
488 // Set the DHCP4 config data.
490 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
491 Dhcp4CfgData
.OptionCount
= OptCount
;
492 Dhcp4CfgData
.OptionList
= OptList
;
493 Dhcp4CfgData
.Dhcp4Callback
= PxeBcDhcpCallBack
;
494 Dhcp4CfgData
.CallbackContext
= Private
;
495 Dhcp4CfgData
.DiscoverTryCount
= 1;
496 Dhcp4CfgData
.DiscoverTimeout
= &DiscoverTimeout
;
498 for (Index
= 0; Index
< PXEBC_DHCP4_DISCOVER_RETRIES
; Index
++) {
500 // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.
502 DiscoverTimeout
= (PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT
<< Index
);
504 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
505 if (EFI_ERROR (Status
)) {
509 // Zero those arrays to record the varies numbers of DHCP OFFERS.
511 Private
->GotProxyOffer
= FALSE
;
512 Private
->NumOffers
= 0;
513 Private
->BootpIndex
= 0;
514 ZeroMem (Private
->ServerCount
, sizeof (Private
->ServerCount
));
515 ZeroMem (Private
->ProxyIndex
, sizeof (Private
->ProxyIndex
));
517 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
518 if (EFI_ERROR (Status
)) {
519 if (Status
== EFI_TIMEOUT
) {
521 // If no response is received or all received offers don't match
522 // the PXE boot requirements, EFI_TIMEOUT will be returned.
526 if (Status
== EFI_ICMP_ERROR
) {
527 Mode
->IcmpErrorReceived
= TRUE
;
530 // Other error status means the DHCP really fails.
535 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
536 if (EFI_ERROR (Status
)) {
540 ASSERT (Dhcp4Mode
.State
== Dhcp4Bound
);
542 CopyMem (&Private
->StationIp
, &Dhcp4Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
543 CopyMem (&Private
->SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
544 CopyMem (&Private
->GatewayIp
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
547 // Check the selected offer to see whether BINL is required, if no or BINL is
548 // finished, set the various Mode members.
550 Status
= PxeBcCheckSelectedOffer (Private
);
551 if (!EFI_ERROR (Status
)) {
556 if (EFI_ERROR (Status
)) {
558 Dhcp4
->Configure (Dhcp4
, NULL
);
561 // Remove the previously configured option list and callback function
563 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
564 Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
566 Private
->AddressIsOk
= TRUE
;
568 if (!Mode
->UsingIpv6
) {
570 // If in IPv4 mode, configure the corresponding ARP with this new
571 // station IP address.
573 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
575 ArpConfigData
.SwAddressType
= 0x0800;
576 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
577 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
579 Private
->Arp
->Configure (Private
->Arp
, NULL
);
580 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
583 // Updated the route table. Fill the first entry.
585 Mode
->RouteTableEntries
= 1;
586 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
587 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
588 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
591 // Create the default route entry if there is a default router.
593 if (Private
->GatewayIp
.Addr
[0] != 0) {
594 Mode
->RouteTableEntries
= 2;
595 Mode
->RouteTable
[1].IpAddr
.Addr
[0] = 0;
596 Mode
->RouteTable
[1].SubnetMask
.Addr
[0] = 0;
597 Mode
->RouteTable
[1].GwAddr
.Addr
[0] = Private
->GatewayIp
.Addr
[0];
607 GC_NOTO: Add function description
609 @param This GC_NOTO: add argument
611 @param Type GC_NOTO: add argument
613 @param Layer GC_NOTO: add argument
615 @param UseBis GC_NOTO: add argument
617 @param Info GC_NOTO: add argument
620 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
622 @retval EFI_NOT_STARTED GC_NOTO: Add description for
624 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
626 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
628 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
630 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
637 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
641 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*Info OPTIONAL
644 PXEBC_PRIVATE_DATA
*Private
;
645 EFI_PXE_BASE_CODE_MODE
*Mode
;
646 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
647 EFI_PXE_BASE_CODE_SRVLIST
*SrvList
;
648 EFI_PXE_BASE_CODE_SRVLIST DefaultSrvList
;
649 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
650 PXEBC_VENDOR_OPTION
*VendorOpt
;
653 PXEBC_BOOT_SVR_ENTRY
*BootSvrEntry
;
656 return EFI_INVALID_PARAMETER
;
659 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
660 Mode
= Private
->PxeBc
.Mode
;
663 Status
= EFI_DEVICE_ERROR
;
664 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
666 if (!Private
->AddressIsOk
) {
667 return EFI_INVALID_PARAMETER
;
670 if (!Mode
->Started
) {
671 return EFI_NOT_STARTED
;
674 Mode
->IcmpErrorReceived
= FALSE
;
677 // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
678 // use the previous setting;
679 // If info isn't offered,
680 // use the cached DhcpAck and ProxyOffer packets.
682 if (*Layer
!= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
) {
684 if (!Mode
->PxeDiscoverValid
|| !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
686 return EFI_INVALID_PARAMETER
;
689 DefaultInfo
.IpCnt
= 1;
690 DefaultInfo
.UseUCast
= TRUE
;
692 DefaultSrvList
.Type
= Type
;
693 DefaultSrvList
.AcceptAnyResponse
= FALSE
;
694 DefaultSrvList
.IpAddr
.Addr
[0] = Private
->ServerIp
.Addr
[0];
696 SrvList
= &DefaultSrvList
;
698 } else if (Info
== NULL
) {
700 // Create info by the cached packet before
702 Packet
= (Mode
->ProxyOfferReceived
) ? &Private
->ProxyOffer
: &Private
->Dhcp4Ack
;
703 VendorOpt
= &Packet
->PxeVendorOption
;
705 if (!Mode
->DhcpAckReceived
|| !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt
->BitMap
)) {
707 // Address is not acquired or no discovery options.
709 return EFI_INVALID_PARAMETER
;
712 DefaultInfo
.UseMCast
= (BOOLEAN
)!IS_DISABLE_MCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
713 DefaultInfo
.UseBCast
= (BOOLEAN
)!IS_DISABLE_BCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
714 DefaultInfo
.MustUseList
= (BOOLEAN
) IS_ENABLE_USE_SERVER_LIST (VendorOpt
->DiscoverCtrl
);
715 DefaultInfo
.UseUCast
= DefaultInfo
.MustUseList
;
717 if (DefaultInfo
.UseMCast
) {
719 // Get the multicast discover ip address from vendor option.
721 CopyMem (&DefaultInfo
.ServerMCastIp
.Addr
, &VendorOpt
->DiscoverMcastIp
, sizeof (EFI_IPv4_ADDRESS
));
724 DefaultInfo
.IpCnt
= 0;
726 if (DefaultInfo
.MustUseList
) {
727 BootSvrEntry
= VendorOpt
->BootSvr
;
728 Status
= EFI_INVALID_PARAMETER
;
730 while (((UINT8
) (BootSvrEntry
- VendorOpt
->BootSvr
)) < VendorOpt
->BootSvrLen
) {
732 if (BootSvrEntry
->Type
== HTONS (Type
)) {
733 Status
= EFI_SUCCESS
;
737 BootSvrEntry
= GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry
);
740 if (EFI_ERROR (Status
)) {
744 DefaultInfo
.IpCnt
= BootSvrEntry
->IpCnt
;
750 SrvList
= Info
->SrvList
;
752 if (!SrvList
[0].AcceptAnyResponse
) {
754 for (Index
= 1; Index
< Info
->IpCnt
; Index
++) {
755 if (SrvList
[Index
].AcceptAnyResponse
) {
760 if (Index
!= Info
->IpCnt
) {
761 return EFI_INVALID_PARAMETER
;
766 if ((!Info
->UseUCast
&& !Info
->UseBCast
&& !Info
->UseMCast
) || (Info
->MustUseList
&& Info
->IpCnt
== 0)) {
768 return EFI_INVALID_PARAMETER
;
771 // Execute discover by UniCast/BroadCast/MultiCast
773 if (Info
->UseUCast
) {
775 for (Index
= 0; Index
< Info
->IpCnt
; Index
++) {
777 if (BootSvrEntry
== NULL
) {
778 Private
->ServerIp
.Addr
[0] = SrvList
[Index
].IpAddr
.Addr
[0];
780 CopyMem (&Private
->ServerIp
, &BootSvrEntry
->IpAddr
[Index
], sizeof (EFI_IPv4_ADDRESS
));
783 Status
= PxeBcDiscvBootService (
788 &SrvList
[Index
].IpAddr
,
792 &Private
->PxeReply
.Packet
.Ack
796 } else if (Info
->UseMCast
) {
798 Status
= PxeBcDiscvBootService (
803 &Info
->ServerMCastIp
,
807 &Private
->PxeReply
.Packet
.Ack
810 } else if (Info
->UseBCast
) {
812 Status
= PxeBcDiscvBootService (
821 &Private
->PxeReply
.Packet
.Ack
825 if (EFI_ERROR (Status
) || !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
826 if (Status
== EFI_ICMP_ERROR
) {
827 Mode
->IcmpErrorReceived
= TRUE
;
829 Status
= EFI_DEVICE_ERROR
;
832 PxeBcParseCachedDhcpPacket (&Private
->PxeReply
);
835 if (Mode
->PxeBisReplyReceived
) {
836 CopyMem (&Private
->ServerIp
, &Mode
->PxeReply
.Dhcpv4
.BootpSiAddr
, sizeof (EFI_IPv4_ADDRESS
));
844 GC_NOTO: Add function description
846 @param This GC_NOTO: add argument
848 @param Operation GC_NOTO: add argument
850 @param BufferPtr GC_NOTO: add argument
852 @param Overwrite GC_NOTO: add argument
854 @param BufferSize GC_NOTO: add argument
856 @param BlockSize GC_NOTO: add argument
858 @param ServerIp GC_NOTO: add argument
860 @param Filename GC_NOTO: add argument
862 @param Info GC_NOTO: add argument
864 @param DontUseBuffer GC_NOTO: add argument
867 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
874 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
875 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
876 IN OUT VOID
*BufferPtr
,
877 IN BOOLEAN Overwrite
,
878 IN OUT UINT64
*BufferSize
,
879 IN UINTN
*BlockSize OPTIONAL
,
880 IN EFI_IP_ADDRESS
*ServerIp
,
882 IN EFI_PXE_BASE_CODE_MTFTP_INFO
*Info OPTIONAL
,
883 IN BOOLEAN DontUseBuffer
886 PXEBC_PRIVATE_DATA
*Private
;
887 EFI_MTFTP4_CONFIG_DATA Mtftp4Config
;
889 EFI_PXE_BASE_CODE_MODE
*Mode
;
890 EFI_MAC_ADDRESS TempMacAddr
;
892 if ((This
== NULL
) ||
893 (Filename
== NULL
) ||
894 (BufferSize
== NULL
) ||
895 ((ServerIp
== NULL
) || !Ip4IsUnicast (NTOHL (ServerIp
->Addr
[0]), 0)) ||
896 ((BufferPtr
== NULL
) && DontUseBuffer
) ||
897 ((BlockSize
!= NULL
) && (*BlockSize
< 512))) {
899 return EFI_INVALID_PARAMETER
;
902 Status
= EFI_DEVICE_ERROR
;
903 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
904 Mode
= &Private
->Mode
;
906 if (!Mode
->AutoArp
) {
908 // If AutoArp is set false, check arp cache
910 UpdateArpCache (This
);
911 if (!FindInArpCache (Mode
, &ServerIp
->v4
, &TempMacAddr
)) {
912 return EFI_DEVICE_ERROR
;
916 Mode
->TftpErrorReceived
= FALSE
;
917 Mode
->IcmpErrorReceived
= FALSE
;
919 Mtftp4Config
.UseDefaultSetting
= FALSE
;
920 Mtftp4Config
.TimeoutValue
= PXEBC_MTFTP_TIMEOUT
;
921 Mtftp4Config
.TryCount
= PXEBC_MTFTP_RETRIES
;
923 CopyMem (&Mtftp4Config
.StationIp
, &Private
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
924 CopyMem (&Mtftp4Config
.SubnetMask
, &Private
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
925 CopyMem (&Mtftp4Config
.GatewayIp
, &Private
->GatewayIp
, sizeof (EFI_IPv4_ADDRESS
));
926 CopyMem (&Mtftp4Config
.ServerIp
, ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
930 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
:
932 Status
= PxeBcTftpGetFileSize (
940 if (!EFI_ERROR (Status
)) {
941 Status
= EFI_BUFFER_TOO_SMALL
;
946 case EFI_PXE_BASE_CODE_TFTP_READ_FILE
:
948 Status
= PxeBcTftpReadFile (
960 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
:
962 Status
= PxeBcTftpWriteFile (
974 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY
:
976 Status
= PxeBcTftpReadDirectory (
988 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE
:
989 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE
:
990 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY
:
991 Status
= EFI_UNSUPPORTED
;
996 Status
= EFI_INVALID_PARAMETER
;
1000 if (Status
== EFI_ICMP_ERROR
) {
1001 Mode
->IcmpErrorReceived
= TRUE
;
1009 GC_NOTO: Add function description
1011 @param This GC_NOTO: add argument
1013 @param OpFlags GC_NOTO: add argument
1015 @param DestIp GC_NOTO: add argument
1017 @param DestPort GC_NOTO: add argument
1019 @param GatewayIp GC_NOTO: add argument
1021 @param SrcIp GC_NOTO: add argument
1023 @param SrcPort GC_NOTO: add argument
1025 @param HeaderSize GC_NOTO: add argument
1027 @param HeaderPtr GC_NOTO: add argument
1029 @param BufferSize GC_NOTO: add argument
1031 @param BufferPtr GC_NOTO: add argument
1034 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1036 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1038 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1040 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1042 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1049 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1051 IN EFI_IP_ADDRESS
*DestIp
,
1052 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
,
1053 IN EFI_IP_ADDRESS
*GatewayIp OPTIONAL
,
1054 IN EFI_IP_ADDRESS
*SrcIp OPTIONAL
,
1055 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort OPTIONAL
,
1056 IN UINTN
*HeaderSize OPTIONAL
,
1057 IN VOID
*HeaderPtr OPTIONAL
,
1058 IN UINTN
*BufferSize
,
1062 PXEBC_PRIVATE_DATA
*Private
;
1063 EFI_UDP4_PROTOCOL
*Udp4
;
1064 EFI_UDP4_COMPLETION_TOKEN Token
;
1065 EFI_UDP4_TRANSMIT_DATA
*Udp4TxData
;
1068 EFI_UDP4_SESSION_DATA Udp4Session
;
1071 EFI_PXE_BASE_CODE_MODE
*Mode
;
1072 EFI_MAC_ADDRESS TempMacAddr
;
1076 if ((This
== NULL
) || (DestIp
== NULL
) || (DestPort
== NULL
)) {
1077 return EFI_INVALID_PARAMETER
;
1080 if ((GatewayIp
!= NULL
) && !Ip4IsUnicast (NTOHL (GatewayIp
->Addr
[0]), 0)) {
1082 // Gateway is provided but it's not a unicast IP address.
1084 return EFI_INVALID_PARAMETER
;
1087 if ((HeaderSize
!= NULL
) && ((*HeaderSize
== 0) || (HeaderPtr
== NULL
))) {
1089 // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
1092 return EFI_INVALID_PARAMETER
;
1095 if ((BufferSize
== NULL
) || ((*BufferSize
!= 0) && (BufferPtr
== NULL
))) {
1096 return EFI_INVALID_PARAMETER
;
1099 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1100 Udp4
= Private
->Udp4Write
;
1101 Mode
= &Private
->Mode
;
1102 if (!Mode
->Started
) {
1103 return EFI_NOT_STARTED
;
1106 if (!Private
->AddressIsOk
&& (SrcIp
== NULL
)) {
1107 return EFI_INVALID_PARAMETER
;
1110 if (!Mode
->AutoArp
) {
1112 // If AutoArp is set false, check arp cache
1114 UpdateArpCache (This
);
1115 if (!FindInArpCache (Mode
, &DestIp
->v4
, &TempMacAddr
)) {
1116 return EFI_DEVICE_ERROR
;
1120 Mode
->IcmpErrorReceived
= FALSE
;
1122 if ((Private
->CurrentUdpSrcPort
== 0) ||
1123 ((SrcPort
!= NULL
) && (*SrcPort
!= Private
->CurrentUdpSrcPort
))) {
1125 // Port is changed, (re)configure the Udp4Write instance
1127 if (SrcPort
!= NULL
) {
1128 Private
->CurrentUdpSrcPort
= *SrcPort
;
1131 Status
= PxeBcConfigureUdpWriteInstance (
1133 &Private
->StationIp
.v4
,
1134 &Private
->SubnetMask
.v4
,
1135 &Private
->GatewayIp
.v4
,
1136 &Private
->CurrentUdpSrcPort
1138 if (EFI_ERROR (Status
)) {
1139 Private
->CurrentUdpSrcPort
= 0;
1140 return EFI_INVALID_PARAMETER
;
1144 ZeroMem (&Token
, sizeof (EFI_UDP4_COMPLETION_TOKEN
));
1145 ZeroMem (&Udp4Session
, sizeof (EFI_UDP4_SESSION_DATA
));
1147 CopyMem (&Udp4Session
.DestinationAddress
, DestIp
, sizeof (EFI_IPv4_ADDRESS
));
1148 Udp4Session
.DestinationPort
= *DestPort
;
1149 if (SrcIp
!= NULL
) {
1150 CopyMem (&Udp4Session
.SourceAddress
, SrcIp
, sizeof (EFI_IPv4_ADDRESS
));
1152 if (SrcPort
!= NULL
) {
1153 Udp4Session
.SourcePort
= *SrcPort
;
1156 FragCount
= (HeaderSize
!= NULL
) ? 2 : 1;
1157 Udp4TxData
= (EFI_UDP4_TRANSMIT_DATA
*) AllocateZeroPool (sizeof (EFI_UDP4_TRANSMIT_DATA
) + (FragCount
- 1) * sizeof (EFI_UDP4_FRAGMENT_DATA
));
1158 if (Udp4TxData
== NULL
) {
1159 return EFI_OUT_OF_RESOURCES
;
1162 Udp4TxData
->FragmentCount
= FragCount
;
1163 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentLength
= (UINT32
) *BufferSize
;
1164 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentBuffer
= BufferPtr
;
1165 DataLength
= (UINT32
) *BufferSize
;
1167 if (FragCount
== 2) {
1169 Udp4TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) *HeaderSize
;
1170 Udp4TxData
->FragmentTable
[0].FragmentBuffer
= HeaderPtr
;
1171 DataLength
+= (UINT32
) *HeaderSize
;
1174 if (GatewayIp
!= NULL
) {
1175 Udp4TxData
->GatewayAddress
= (EFI_IPv4_ADDRESS
*) GatewayIp
;
1177 Udp4TxData
->UdpSessionData
= &Udp4Session
;
1178 Udp4TxData
->DataLength
= DataLength
;
1179 Token
.Packet
.TxData
= Udp4TxData
;
1181 Status
= gBS
->CreateEvent (
1188 if (EFI_ERROR (Status
)) {
1192 Status
= Udp4
->Transmit (Udp4
, &Token
);
1193 if (EFI_ERROR (Status
)) {
1194 if (Status
== EFI_ICMP_ERROR
) {
1195 Mode
->IcmpErrorReceived
= TRUE
;
1205 Status
= Token
.Status
;
1209 if (Token
.Event
!= NULL
) {
1210 gBS
->CloseEvent (Token
.Event
);
1213 gBS
->FreePool (Udp4TxData
);
1219 Validate IP packages by IP filter settings
1221 @param PxeBcMode Pointer to EFI_PXEBC_MODE
1223 @param Session Received UDP session
1225 @retval TRUE The UDP package matches IP filters
1227 @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)) || ((HeaderSize
!= NULL
) && (HeaderPtr
== NULL
))) {
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
->Udp4Read
;
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
;
1380 Status
= Udp4
->Receive (Udp4
, &Token
);
1381 if (EFI_ERROR (Status
)) {
1382 if (Status
== EFI_ICMP_ERROR
) {
1383 Mode
->IcmpErrorReceived
= TRUE
;
1391 Status
= EFI_TIMEOUT
;
1395 // check whether this packet matches the filters
1397 if (EFI_ERROR (Token
.Status
)){
1401 RxData
= Token
.Packet
.RxData
;
1402 Session
= &RxData
->UdpSession
;
1406 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
) {
1408 // Check UDP package by IP filter settings
1410 if (CheckIpByFilter (Mode
, Session
)) {
1419 // Match the destination ip of the received udp dgram
1421 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
) {
1424 if (DestIp
!= NULL
) {
1425 CopyMem (DestIp
, &Session
->DestinationAddress
, sizeof (EFI_IPv4_ADDRESS
));
1428 if (DestIp
!= NULL
) {
1429 if (EFI_IP4_EQUAL (DestIp
, &Session
->DestinationAddress
)) {
1433 if (EFI_IP4_EQUAL (&Private
->StationIp
, &Session
->DestinationAddress
)) {
1442 // Match the destination port of the received udp dgram
1444 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) {
1446 if (DestPort
!= NULL
) {
1447 *DestPort
= Session
->DestinationPort
;
1451 if (*DestPort
!= Session
->DestinationPort
) {
1459 // Match the source ip of the received udp dgram
1461 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) {
1463 if (SrcIp
!= NULL
) {
1464 CopyMem (SrcIp
, &Session
->SourceAddress
, sizeof (EFI_IPv4_ADDRESS
));
1468 if (!EFI_IP4_EQUAL (SrcIp
, &Session
->SourceAddress
)) {
1476 // Match the source port of the received udp dgram
1478 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
1480 if (SrcPort
!= NULL
) {
1481 *SrcPort
= Session
->SourcePort
;
1485 if (*SrcPort
!= Session
->SourcePort
) {
1495 if (HeaderSize
!= NULL
) {
1496 CopyLen
= MIN (*HeaderSize
, RxData
->DataLength
);
1497 CopyMem (HeaderPtr
, RxData
->FragmentTable
[0].FragmentBuffer
, CopyLen
);
1498 *HeaderSize
= CopyLen
;
1501 if (RxData
->DataLength
- CopyLen
> *BufferSize
) {
1503 Status
= EFI_BUFFER_TOO_SMALL
;
1506 *BufferSize
= RxData
->DataLength
- CopyLen
;
1507 CopyMem (BufferPtr
, (UINT8
*) RxData
->FragmentTable
[0].FragmentBuffer
+ CopyLen
, *BufferSize
);
1511 Status
= EFI_TIMEOUT
;
1515 // Recycle the RxData
1517 gBS
->SignalEvent (RxData
->RecycleSignal
);
1526 Udp4
->Cancel (Udp4
, &Token
);
1528 gBS
->CloseEvent (Token
.Event
);
1535 GC_NOTO: Add function description
1537 @param This GC_NOTO: add argument
1539 @param NewFilter GC_NOTO: add argument
1542 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1548 EfiPxeBcSetIpFilter (
1549 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1550 IN EFI_PXE_BASE_CODE_IP_FILTER
*NewFilter
1554 PXEBC_PRIVATE_DATA
*Private
;
1555 EFI_PXE_BASE_CODE_MODE
*Mode
;
1557 BOOLEAN PromiscuousNeed
;
1560 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL.\n"));
1561 return EFI_INVALID_PARAMETER
;
1564 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1565 Mode
= Private
->PxeBc
.Mode
;
1567 if (Private
== NULL
) {
1568 DEBUG ((EFI_D_ERROR
, "PXEBC_PRIVATE_DATA poiner == NULL.\n"));
1569 return EFI_INVALID_PARAMETER
;
1572 if (NewFilter
== NULL
) {
1573 DEBUG ((EFI_D_ERROR
, "IP Filter *NewFilter == NULL.\n"));
1574 return EFI_INVALID_PARAMETER
;
1577 if (!Mode
->Started
) {
1578 DEBUG ((EFI_D_ERROR
, "BC was not started.\n"));
1579 return EFI_NOT_STARTED
;
1582 PromiscuousNeed
= FALSE
;
1583 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1584 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter
->IpList
[Index
].v4
))) {
1586 // The IP is a broadcast address.
1588 DEBUG ((EFI_D_ERROR
, "There is broadcast address in NewFilter.\n"));
1589 return EFI_INVALID_PARAMETER
;
1591 if (Ip4IsUnicast (EFI_IP4 (NewFilter
->IpList
[Index
].v4
), 0) &&
1592 (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
)
1595 // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,
1596 // promiscuous mode is needed.
1598 PromiscuousNeed
= TRUE
;
1603 // Clear the UDP instance configuration, all joined groups will be left
1604 // during the operation.
1606 Private
->Udp4Read
->Configure (Private
->Udp4Read
, NULL
);
1607 Private
->Udp4CfgData
.AcceptPromiscuous
= FALSE
;
1608 Private
->Udp4CfgData
.AcceptBroadcast
= FALSE
;
1610 if (PromiscuousNeed
||
1611 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
||
1612 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
1615 // Configure the udp4 filter to receive all packages
1617 Private
->Udp4CfgData
.AcceptPromiscuous
= TRUE
;
1620 // Configure the UDP instance with the new configuration.
1622 Status
= Private
->Udp4Read
->Configure (Private
->Udp4Read
, &Private
->Udp4CfgData
);
1623 if (EFI_ERROR (Status
)) {
1629 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) {
1631 // Configure the udp4 filter to receive all broadcast packages
1633 Private
->Udp4CfgData
.AcceptBroadcast
= TRUE
;
1637 // Configure the UDP instance with the new configuration.
1639 Status
= Private
->Udp4Read
->Configure (Private
->Udp4Read
, &Private
->Udp4CfgData
);
1640 if (EFI_ERROR (Status
)) {
1644 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1646 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1647 if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter
->IpList
[Index
].v4
))) {
1649 // Join the mutilcast group
1651 Status
= Private
->Udp4Read
->Groups (Private
->Udp4Read
, TRUE
, &NewFilter
->IpList
[Index
].v4
);
1652 if (EFI_ERROR (Status
)) {
1662 // Save the new filter.
1664 CopyMem (&Mode
->IpFilter
, NewFilter
, sizeof (Mode
->IpFilter
));
1671 GC_NOTO: Add function description
1673 @param This GC_NOTO: add argument
1675 @param IpAddr GC_NOTO: add argument
1677 @param MacAddr GC_NOTO: add argument
1680 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1687 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1688 IN EFI_IP_ADDRESS
* IpAddr
,
1689 IN EFI_MAC_ADDRESS
* MacAddr OPTIONAL
1692 PXEBC_PRIVATE_DATA
*Private
;
1693 EFI_PXE_BASE_CODE_MODE
*Mode
;
1695 EFI_MAC_ADDRESS TempMacAddr
;
1697 if (This
== NULL
|| IpAddr
== NULL
) {
1698 return EFI_INVALID_PARAMETER
;
1701 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1702 Mode
= Private
->PxeBc
.Mode
;
1704 if (!Mode
->Started
) {
1705 return EFI_NOT_STARTED
;
1708 if (!Private
->AddressIsOk
|| Mode
->UsingIpv6
) {
1710 // We can't resolve the IP address if we don't have a local address now.
1711 // Don't have ARP for IPv6.
1713 return EFI_INVALID_PARAMETER
;
1716 Mode
->IcmpErrorReceived
= FALSE
;
1718 if (!Mode
->AutoArp
) {
1720 // If AutoArp is set false, check arp cache
1722 UpdateArpCache (This
);
1723 if (!FindInArpCache (Mode
, &IpAddr
->v4
, &TempMacAddr
)) {
1724 return EFI_DEVICE_ERROR
;
1727 Status
= Private
->Arp
->Request (Private
->Arp
, &IpAddr
->v4
, NULL
, &TempMacAddr
);
1728 if (EFI_ERROR (Status
)) {
1729 if (Status
== EFI_ICMP_ERROR
) {
1730 Mode
->IcmpErrorReceived
= TRUE
;
1736 if (MacAddr
!= NULL
) {
1737 CopyMem (MacAddr
, &TempMacAddr
, sizeof (EFI_MAC_ADDRESS
));
1746 GC_NOTO: Add function description
1748 @param This GC_NOTO: add argument
1750 @param NewAutoArp GC_NOTO: add argument
1752 @param NewSendGUID GC_NOTO: add argument
1754 @param NewTTL GC_NOTO: add argument
1756 @param NewToS GC_NOTO: add argument
1758 @param NewMakeCallback GC_NOTO: add argument
1761 @return GC_NOTO: add return values
1766 EfiPxeBcSetParameters (
1767 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1768 IN BOOLEAN
*NewAutoArp
, OPTIONAL
1769 IN BOOLEAN
*NewSendGUID
, OPTIONAL
1770 IN UINT8
*NewTTL
, OPTIONAL
1771 IN UINT8
*NewToS
, OPTIONAL
1772 IN BOOLEAN
*NewMakeCallback
// OPTIONAL
1775 PXEBC_PRIVATE_DATA
*Private
;
1776 EFI_PXE_BASE_CODE_MODE
*Mode
;
1779 Status
= EFI_SUCCESS
;
1782 Status
= EFI_INVALID_PARAMETER
;
1786 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1787 Mode
= Private
->PxeBc
.Mode
;
1789 if (NewSendGUID
!= NULL
&& *NewSendGUID
== TRUE
) {
1791 // FixMe, cann't locate SendGuid
1795 if (NewMakeCallback
!= NULL
&& *NewMakeCallback
== TRUE
) {
1797 Status
= gBS
->HandleProtocol (
1798 Private
->Controller
,
1799 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1800 (VOID
**) &Private
->PxeBcCallback
1802 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1804 Status
= EFI_INVALID_PARAMETER
;
1809 if (!Mode
->Started
) {
1810 Status
= EFI_NOT_STARTED
;
1814 if (NewMakeCallback
!= NULL
) {
1816 if (*NewMakeCallback
) {
1818 // Update the Callback protocol.
1820 Status
= gBS
->HandleProtocol (
1821 Private
->Controller
,
1822 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1823 (VOID
**) &Private
->PxeBcCallback
1826 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1827 Status
= EFI_INVALID_PARAMETER
;
1831 Private
->PxeBcCallback
= NULL
;
1834 Mode
->MakeCallbacks
= *NewMakeCallback
;
1837 if (NewAutoArp
!= NULL
) {
1838 Mode
->AutoArp
= *NewAutoArp
;
1841 if (NewSendGUID
!= NULL
) {
1842 Mode
->SendGUID
= *NewSendGUID
;
1845 if (NewTTL
!= NULL
) {
1846 Mode
->TTL
= *NewTTL
;
1849 if (NewToS
!= NULL
) {
1850 Mode
->ToS
= *NewToS
;
1859 GC_NOTO: Add function description
1861 @param This GC_NOTO: add argument
1863 @param NewStationIp GC_NOTO: add argument
1865 @param NewSubnetMask GC_NOTO: add argument
1868 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1870 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1872 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1874 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1876 @retval EFI_SUCCESS GC_NOTO: Add description for
1882 EfiPxeBcSetStationIP (
1883 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1884 IN EFI_IP_ADDRESS
* NewStationIp
, OPTIONAL
1885 IN EFI_IP_ADDRESS
* NewSubnetMask OPTIONAL
1888 PXEBC_PRIVATE_DATA
*Private
;
1889 EFI_PXE_BASE_CODE_MODE
*Mode
;
1890 EFI_ARP_CONFIG_DATA ArpConfigData
;
1893 return EFI_INVALID_PARAMETER
;
1896 if (NewStationIp
!= NULL
&& !Ip4IsUnicast (NTOHL (NewStationIp
->Addr
[0]), 0)) {
1897 return EFI_INVALID_PARAMETER
;
1900 if (NewSubnetMask
!= NULL
&& !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask
->Addr
[0]))) {
1901 return EFI_INVALID_PARAMETER
;
1904 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1905 Mode
= Private
->PxeBc
.Mode
;
1907 if (!Mode
->Started
) {
1908 return EFI_NOT_STARTED
;
1911 if (NewStationIp
!= NULL
) {
1912 CopyMem (&Mode
->StationIp
, NewStationIp
, sizeof (EFI_IP_ADDRESS
));
1913 CopyMem (&Private
->StationIp
, NewStationIp
, sizeof (EFI_IP_ADDRESS
));
1916 if (NewSubnetMask
!= NULL
) {
1917 CopyMem (&Mode
->SubnetMask
, NewSubnetMask
, sizeof (EFI_IP_ADDRESS
));
1918 CopyMem (&Private
->SubnetMask
,NewSubnetMask
, sizeof (EFI_IP_ADDRESS
));
1921 Private
->AddressIsOk
= TRUE
;
1923 if (!Mode
->UsingIpv6
) {
1925 // If in IPv4 mode, configure the corresponding ARP with this new
1926 // station IP address.
1928 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
1930 ArpConfigData
.SwAddressType
= 0x0800;
1931 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
1932 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
1934 Private
->Arp
->Configure (Private
->Arp
, NULL
);
1935 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
1938 // Update the route table.
1940 Mode
->RouteTableEntries
= 1;
1941 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
1942 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
1943 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
1951 GC_NOTO: Add function description
1953 @param This GC_NOTO: add argument
1955 @param NewDhcpDiscoverValid GC_NOTO: add argument
1957 @param NewDhcpAckReceived GC_NOTO: add argument
1959 @param NewProxyOfferReceived GC_NOTO: add argument
1961 @param NewPxeDiscoverValid GC_NOTO: add argument
1963 @param NewPxeReplyReceived GC_NOTO: add argument
1965 @param NewPxeBisReplyReceived GC_NOTO: add argument
1967 @param NewDhcpDiscover GC_NOTO: add argument
1969 @param NewDhcpAck GC_NOTO: add argument
1971 @param NewProxyOffer GC_NOTO: add argument
1973 @param NewPxeDiscover GC_NOTO: add argument
1975 @param NewPxeReply GC_NOTO: add argument
1977 @param NewPxeBisReply GC_NOTO: add argument
1980 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1982 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1984 @retval EFI_SUCCESS GC_NOTO: Add description for
1990 EfiPxeBcSetPackets (
1991 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1992 IN BOOLEAN
* NewDhcpDiscoverValid
, OPTIONAL
1993 IN BOOLEAN
* NewDhcpAckReceived
, OPTIONAL
1994 IN BOOLEAN
* NewProxyOfferReceived
, OPTIONAL
1995 IN BOOLEAN
* NewPxeDiscoverValid
, OPTIONAL
1996 IN BOOLEAN
* NewPxeReplyReceived
, OPTIONAL
1997 IN BOOLEAN
* NewPxeBisReplyReceived
, OPTIONAL
1998 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
1999 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
2000 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
2001 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
2002 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
2003 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
2006 PXEBC_PRIVATE_DATA
*Private
;
2007 EFI_PXE_BASE_CODE_MODE
*Mode
;
2010 return EFI_INVALID_PARAMETER
;
2013 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
2014 Mode
= Private
->PxeBc
.Mode
;
2016 if (!Mode
->Started
) {
2017 return EFI_NOT_STARTED
;
2020 Private
->FileSize
= 0;
2022 if (NewDhcpDiscoverValid
!= NULL
) {
2023 Mode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
2026 if (NewDhcpAckReceived
!= NULL
) {
2027 Mode
->DhcpAckReceived
= *NewDhcpAckReceived
;
2030 if (NewProxyOfferReceived
!= NULL
) {
2031 Mode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
2034 if (NewPxeDiscoverValid
!= NULL
) {
2035 Mode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
2038 if (NewPxeReplyReceived
!= NULL
) {
2039 Mode
->PxeReplyReceived
= *NewPxeReplyReceived
;
2042 if (NewPxeBisReplyReceived
!= NULL
) {
2043 Mode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
2046 if (NewDhcpDiscover
!= NULL
) {
2047 CopyMem (&Mode
->DhcpDiscover
, NewDhcpDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2050 if (NewDhcpAck
!= NULL
) {
2051 CopyMem (&Mode
->DhcpAck
, NewDhcpAck
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2054 if (NewProxyOffer
!= NULL
) {
2055 CopyMem (&Mode
->ProxyOffer
, NewProxyOffer
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2058 if (NewPxeDiscover
!= NULL
) {
2059 CopyMem (&Mode
->PxeDiscover
, NewPxeDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2062 if (NewPxeReply
!= NULL
) {
2063 CopyMem (&Mode
->PxeReply
, NewPxeReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2066 if (NewPxeBisReply
!= NULL
) {
2067 CopyMem (&Mode
->PxeBisReply
, NewPxeBisReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2073 EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate
= {
2074 EFI_PXE_BASE_CODE_PROTOCOL_REVISION
,
2082 EfiPxeBcSetIpFilter
,
2084 EfiPxeBcSetParameters
,
2085 EfiPxeBcSetStationIP
,
2092 GC_NOTO: Add function description
2094 @param This GC_NOTO: add argument
2096 @param Function GC_NOTO: add argument
2098 @param Received GC_NOTO: add argument
2100 @param PacketLength GC_NOTO: add argument
2102 @param PacketPtr GC_NOTO: add argument
2105 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT GC_NOTO: Add description for
2107 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2109 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2111 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2113 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2117 EFI_PXE_BASE_CODE_CALLBACK_STATUS
2119 EfiPxeLoadFileCallback (
2120 IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL
* This
,
2121 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
2122 IN BOOLEAN Received
,
2123 IN UINT32 PacketLength
,
2124 IN EFI_PXE_BASE_CODE_PACKET
* PacketPtr OPTIONAL
2131 // Catch Ctrl-C or ESC to abort.
2133 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2135 if (!EFI_ERROR (Status
)) {
2137 if (Key
.ScanCode
== SCAN_ESC
|| Key
.UnicodeChar
== (0x1F & 'c')) {
2139 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT
;
2143 // No print if receive packet
2146 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2149 // Print only for three functions
2153 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP
:
2155 // Print only for open MTFTP packets, not every MTFTP packets
2157 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2158 if (PacketPtr
->Raw
[0x1C] != 0x00 || PacketPtr
->Raw
[0x1D] != 0x01) {
2159 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2164 case EFI_PXE_BASE_CODE_FUNCTION_DHCP
:
2165 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
:
2169 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2172 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2174 // Print '.' when transmit a packet
2180 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2183 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate
= {
2184 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION
,
2185 EfiPxeLoadFileCallback
2190 GC_NOTO: Add function description
2192 @param Private GC_NOTO: add argument
2194 @param BufferSize GC_NOTO: add argument
2196 @param Buffer GC_NOTO: add argument
2199 @return GC_NOTO: add return values
2204 IN PXEBC_PRIVATE_DATA
*Private
,
2205 IN OUT UINT64
*BufferSize
,
2209 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2210 EFI_PXE_BASE_CODE_MODE
*Mode
;
2216 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
2219 PxeBc
= &Private
->PxeBc
;
2221 Type
= EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
;
2222 Layer
= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
;
2227 Status
= PxeBc
->Dhcp (PxeBc
, TRUE
);
2228 if (EFI_ERROR (Status
)) {
2233 // Select a boot server
2235 Status
= PxeBcSelectBootPrompt (Private
);
2237 if (Status
== EFI_SUCCESS
) {
2238 Status
= PxeBcSelectBootMenu (Private
, &Type
, TRUE
);
2239 } else if (Status
== EFI_TIMEOUT
) {
2240 Status
= PxeBcSelectBootMenu (Private
, &Type
, FALSE
);
2243 if (!EFI_ERROR (Status
)) {
2245 if (Type
== EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
) {
2247 // Local boot(PXE bootstrap server) need abort
2252 UseBis
= (BOOLEAN
) (Mode
->BisSupported
&& Mode
->BisDetected
);
2253 Status
= PxeBc
->Discover (PxeBc
, Type
, &Layer
, UseBis
, NULL
);
2254 if (EFI_ERROR (Status
)) {
2263 // Get bootfile name and (m)tftp server ip addresss
2265 if (Mode
->PxeReplyReceived
) {
2266 Packet
= &Private
->PxeReply
;
2267 } else if (Mode
->ProxyOfferReceived
) {
2268 Packet
= &Private
->ProxyOffer
;
2270 Packet
= &Private
->Dhcp4Ack
;
2273 CopyMem (&Private
->ServerIp
, &Packet
->Packet
.Offer
.Dhcp4
.Header
.ServerAddr
, sizeof (EFI_IPv4_ADDRESS
));
2274 if (Private
->ServerIp
.Addr
[0] == 0) {
2276 // next server ip address is zero, use option 54 instead
2280 Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_SERVER_ID
]->Data
,
2281 sizeof (EFI_IPv4_ADDRESS
)
2285 ASSERT (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
);
2290 Private
->BootFileName
= (CHAR8
*) (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
]->Data
);
2292 if (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
] != NULL
) {
2294 // Already have the bootfile length option, compute the file size
2296 CopyMem (&Value
, Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
]->Data
, sizeof (Value
));
2297 Value
= NTOHS (Value
);
2298 *BufferSize
= 512 * Value
;
2299 Status
= EFI_BUFFER_TOO_SMALL
;
2302 // Get the bootfile size from tftp
2304 Status
= PxeBc
->Mtftp (
2306 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
,
2312 (UINT8
*) Private
->BootFileName
,
2318 Private
->FileSize
= (UINTN
) *BufferSize
;
2325 GC_NOTO: Add function description
2327 @param This GC_NOTO: add argument
2329 @param FilePath GC_NOTO: add argument
2331 @param BootPolicy GC_NOTO: add argument
2333 @param BufferSize GC_NOTO: add argument
2335 @param Buffer GC_NOTO: add argument
2338 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
2340 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
2347 IN EFI_LOAD_FILE_PROTOCOL
* This
,
2348 IN EFI_DEVICE_PATH_PROTOCOL
* FilePath
,
2349 IN BOOLEAN BootPolicy
,
2350 IN OUT UINTN
*BufferSize
,
2351 IN VOID
*Buffer OPTIONAL
2354 PXEBC_PRIVATE_DATA
*Private
;
2355 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2356 BOOLEAN NewMakeCallback
;
2361 Private
= PXEBC_PRIVATE_DATA_FROM_LOADFILE (This
);
2362 PxeBc
= &Private
->PxeBc
;
2363 NewMakeCallback
= FALSE
;
2365 Status
= EFI_DEVICE_ERROR
;
2367 if (This
== NULL
|| BufferSize
== NULL
) {
2369 return EFI_INVALID_PARAMETER
;
2373 // Only support BootPolicy
2376 return EFI_UNSUPPORTED
;
2379 Status
= PxeBc
->Start (PxeBc
, FALSE
);
2380 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
2384 Status
= gBS
->HandleProtocol (
2385 Private
->Controller
,
2386 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2387 (VOID
**) &Private
->PxeBcCallback
2389 if (Status
== EFI_UNSUPPORTED
) {
2391 CopyMem (&Private
->LoadFileCallback
, &mPxeBcCallBackTemplate
, sizeof (Private
->LoadFileCallback
));
2393 Status
= gBS
->InstallProtocolInterface (
2394 &Private
->Controller
,
2395 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2396 EFI_NATIVE_INTERFACE
,
2397 &Private
->LoadFileCallback
2400 NewMakeCallback
= (BOOLEAN
) (Status
== EFI_SUCCESS
);
2402 Status
= PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2403 if (EFI_ERROR (Status
)) {
2404 PxeBc
->Stop (PxeBc
);
2409 if (Private
->FileSize
== 0) {
2411 Status
= DiscoverBootFile (Private
, &TmpBufSize
, Buffer
);
2413 if (sizeof (UINTN
) < sizeof (UINT64
) && (TmpBufSize
> 0xFFFFFFFF)) {
2414 Status
= EFI_DEVICE_ERROR
;
2416 *BufferSize
= (UINTN
) TmpBufSize
;
2418 } else if (Buffer
== NULL
) {
2419 *BufferSize
= Private
->FileSize
;
2420 Status
= EFI_BUFFER_TOO_SMALL
;
2423 // Download the file.
2425 TmpBufSize
= (UINT64
) (*BufferSize
);
2426 Status
= PxeBc
->Mtftp (
2428 EFI_PXE_BASE_CODE_TFTP_READ_FILE
,
2434 (UINT8
*) Private
->BootFileName
,
2440 // If we added a callback protocol, now is the time to remove it.
2442 if (NewMakeCallback
) {
2444 NewMakeCallback
= FALSE
;
2446 PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2448 gBS
->UninstallProtocolInterface (
2449 Private
->Controller
,
2450 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2451 &Private
->LoadFileCallback
2456 // Check download status
2458 if (Status
== EFI_SUCCESS
) {
2461 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
2462 if (Buffer
!= NULL
) {
2463 AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
2468 } else if (Status
== EFI_DEVICE_ERROR
) {
2469 AsciiPrint ("PXE-E07: Network device error.\n");
2471 } else if (Status
== EFI_OUT_OF_RESOURCES
) {
2472 AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
2474 } else if (Status
== EFI_NO_MEDIA
) {
2475 AsciiPrint ("PXE-E12: Could not detect network connection.\n");
2477 } else if (Status
== EFI_NO_RESPONSE
) {
2478 AsciiPrint ("PXE-E16: No offer received.\n");
2480 } else if (Status
== EFI_TIMEOUT
) {
2481 AsciiPrint ("PXE-E18: Server response timeout.\n");
2483 } else if (Status
== EFI_ABORTED
) {
2484 AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
2486 } else if (Status
== EFI_ICMP_ERROR
) {
2487 AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
2489 } else if (Status
== EFI_TFTP_ERROR
) {
2490 AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
2493 AsciiPrint ("PXE-E99: Unexpected network error.\n");
2496 PxeBc
->Stop (PxeBc
);
2501 EFI_LOAD_FILE_PROTOCOL mLoadFileProtocolTemplate
= { EfiPxeLoadFile
};