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
;
255 return EFI_INVALID_PARAMETER
;
258 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
259 Mode
= Private
->PxeBc
.Mode
;
262 return EFI_ALREADY_STARTED
;
267 // IPv6 is not supported now.
269 return EFI_UNSUPPORTED
;
273 // Configure the udp4 instance to let it receive data
275 Status
= Private
->Udp4Read
->Configure (Private
->Udp4Read
, &Private
->Udp4CfgData
);
276 if (EFI_ERROR (Status
)) {
280 Private
->AddressIsOk
= FALSE
;
282 ZeroMem (Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
284 Mode
->Started
= TRUE
;
285 Mode
->TTL
= DEFAULT_TTL
;
286 Mode
->ToS
= DEFAULT_ToS
;
287 Mode
->AutoArp
= TRUE
;
290 // Create the event for Arp Cache checking.
292 Status
= gBS
->CreateEvent (
293 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
295 ArpCacheUpdateTimeout
,
297 &Private
->GetArpCacheEvent
299 if (EFI_ERROR (Status
)) {
304 // Start the timeout timer event.
306 Status
= gBS
->SetTimer (
307 Private
->GetArpCacheEvent
,
312 if (EFI_ERROR (Status
)) {
317 // Create ICMP error receiving event
319 Status
= gBS
->CreateEvent (
322 IcmpErrorListenHandler
,
324 &(Private
->IcmpErrorRcvToken
.Event
)
326 if (EFI_ERROR (Status
)) {
330 Status
= Private
->Ip4
->Configure (Private
->Ip4
, &Private
->Ip4ConfigData
);
331 if (EFI_ERROR (Status
)) {
336 // start to listen incoming packet
338 Status
= Private
->Ip4
->Receive (Private
->Ip4
, &Private
->IcmpErrorRcvToken
);
339 if (!EFI_ERROR (Status
)) {
344 Private
->Ip4
->Configure (Private
->Ip4
, NULL
);
346 if (Private
->IcmpErrorRcvToken
.Event
!= NULL
) {
347 gBS
->CloseEvent (Private
->IcmpErrorRcvToken
.Event
);
350 if (Private
->GetArpCacheEvent
!= NULL
) {
351 gBS
->SetTimer (Private
->GetArpCacheEvent
, TimerCancel
, 0);
352 gBS
->CloseEvent (Private
->GetArpCacheEvent
);
355 Mode
->Started
= FALSE
;
358 Mode
->AutoArp
= FALSE
;
365 GC_NOTO: Add function description
367 @param This GC_NOTO: add argument
370 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
372 @retval EFI_NOT_STARTED GC_NOTO: Add description for
374 @retval EFI_SUCCESS GC_NOTO: Add description for
381 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
384 PXEBC_PRIVATE_DATA
*Private
;
385 EFI_PXE_BASE_CODE_MODE
*Mode
;
388 return EFI_INVALID_PARAMETER
;
391 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
392 Mode
= Private
->PxeBc
.Mode
;
394 if (!Mode
->Started
) {
395 return EFI_NOT_STARTED
;
398 Private
->Ip4
->Cancel (Private
->Ip4
, NULL
);
400 // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's
403 NetLibDispatchDpc ();
405 Private
->Ip4
->Configure (Private
->Ip4
, NULL
);
408 // Close the ICMP error receiving event.
410 gBS
->CloseEvent (Private
->IcmpErrorRcvToken
.Event
);
413 // Cancel the TimeoutEvent timer.
415 gBS
->SetTimer (Private
->GetArpCacheEvent
, TimerCancel
, 0);
418 // Close the TimeoutEvent event.
420 gBS
->CloseEvent (Private
->GetArpCacheEvent
);
422 Mode
->Started
= FALSE
;
424 Private
->CurrentUdpSrcPort
= 0;
425 Private
->Udp4Write
->Configure (Private
->Udp4Write
, NULL
);
426 Private
->Udp4Read
->Configure (Private
->Udp4Read
, NULL
);
428 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
429 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
431 Private
->FileSize
= 0;
438 GC_NOTO: Add function description
440 @param This GC_NOTO: add argument
442 @param SortOffers GC_NOTO: add argument
445 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
447 @retval EFI_NOT_STARTED GC_NOTO: Add description for
454 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
455 IN BOOLEAN SortOffers
458 PXEBC_PRIVATE_DATA
*Private
;
459 EFI_PXE_BASE_CODE_MODE
*Mode
;
460 EFI_DHCP4_PROTOCOL
*Dhcp4
;
461 EFI_DHCP4_CONFIG_DATA Dhcp4CfgData
;
462 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
463 EFI_DHCP4_PACKET_OPTION
*OptList
[PXEBC_DHCP4_MAX_OPTION_NUM
];
465 UINT32 DiscoverTimeout
;
468 EFI_ARP_CONFIG_DATA ArpConfigData
;
471 return EFI_INVALID_PARAMETER
;
474 Status
= EFI_SUCCESS
;
475 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
476 Mode
= Private
->PxeBc
.Mode
;
477 Dhcp4
= Private
->Dhcp4
;
478 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
479 Private
->SortOffers
= SortOffers
;
481 if (!Mode
->Started
) {
482 return EFI_NOT_STARTED
;
485 Mode
->IcmpErrorReceived
= FALSE
;
488 // Initialize the DHCP options and build the option list
490 OptCount
= PxeBcBuildDhcpOptions (Private
, OptList
, TRUE
);
493 // Set the DHCP4 config data.
495 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
496 Dhcp4CfgData
.OptionCount
= OptCount
;
497 Dhcp4CfgData
.OptionList
= OptList
;
498 Dhcp4CfgData
.Dhcp4Callback
= PxeBcDhcpCallBack
;
499 Dhcp4CfgData
.CallbackContext
= Private
;
500 Dhcp4CfgData
.DiscoverTryCount
= 1;
501 Dhcp4CfgData
.DiscoverTimeout
= &DiscoverTimeout
;
503 for (Index
= 0; Index
< PXEBC_DHCP4_DISCOVER_RETRIES
; Index
++) {
505 // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.
507 DiscoverTimeout
= (PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT
<< Index
);
509 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
510 if (EFI_ERROR (Status
)) {
514 // Zero those arrays to record the varies numbers of DHCP OFFERS.
516 Private
->NumOffers
= 0;
517 Private
->BootpIndex
= 0;
518 ZeroMem (Private
->ServerCount
, sizeof (Private
->ServerCount
));
519 ZeroMem (Private
->ProxyIndex
, sizeof (Private
->ProxyIndex
));
521 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
522 if (EFI_ERROR (Status
)) {
523 if (Status
== EFI_TIMEOUT
) {
525 // If no response is received or all received offers don't match
526 // the PXE boot requirements, EFI_TIMEOUT will be returned.
530 if (Status
== EFI_ICMP_ERROR
) {
531 Mode
->IcmpErrorReceived
= TRUE
;
534 // Other error status means the DHCP really fails.
539 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
540 if (EFI_ERROR (Status
)) {
544 ASSERT (Dhcp4Mode
.State
== Dhcp4Bound
);
546 CopyMem (&Private
->StationIp
, &Dhcp4Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
547 CopyMem (&Private
->SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
548 CopyMem (&Private
->GatewayIp
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
551 // Check the selected offer to see whether BINL is required, if no or BINL is
552 // finished, set the various Mode members.
554 Status
= PxeBcCheckSelectedOffer (Private
);
555 if (!EFI_ERROR (Status
)) {
560 if (EFI_ERROR (Status
)) {
562 Dhcp4
->Configure (Dhcp4
, NULL
);
565 // Remove the previously configured option list and callback function
567 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
568 Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
570 Private
->AddressIsOk
= TRUE
;
572 if (!Mode
->UsingIpv6
) {
574 // If in IPv4 mode, configure the corresponding ARP with this new
575 // station IP address.
577 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
579 ArpConfigData
.SwAddressType
= 0x0800;
580 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
581 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
583 Private
->Arp
->Configure (Private
->Arp
, NULL
);
584 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
587 // Updated the route table. Fill the first entry.
589 Mode
->RouteTableEntries
= 1;
590 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
591 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
592 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
595 // Create the default route entry if there is a default router.
597 if (Private
->GatewayIp
.Addr
[0] != 0) {
598 Mode
->RouteTableEntries
= 2;
599 Mode
->RouteTable
[1].IpAddr
.Addr
[0] = 0;
600 Mode
->RouteTable
[1].SubnetMask
.Addr
[0] = 0;
601 Mode
->RouteTable
[1].GwAddr
.Addr
[0] = Private
->GatewayIp
.Addr
[0];
611 GC_NOTO: Add function description
613 @param This GC_NOTO: add argument
615 @param Type GC_NOTO: add argument
617 @param Layer GC_NOTO: add argument
619 @param UseBis GC_NOTO: add argument
621 @param Info GC_NOTO: add argument
624 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
626 @retval EFI_NOT_STARTED 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
632 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
634 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
641 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
645 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*Info OPTIONAL
648 PXEBC_PRIVATE_DATA
*Private
;
649 EFI_PXE_BASE_CODE_MODE
*Mode
;
650 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
651 EFI_PXE_BASE_CODE_SRVLIST
*SrvList
;
652 EFI_PXE_BASE_CODE_SRVLIST DefaultSrvList
;
653 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
654 PXEBC_VENDOR_OPTION
*VendorOpt
;
657 PXEBC_BOOT_SVR_ENTRY
*BootSvrEntry
;
660 return EFI_INVALID_PARAMETER
;
663 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
664 Mode
= Private
->PxeBc
.Mode
;
667 Status
= EFI_DEVICE_ERROR
;
668 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
670 if (!Private
->AddressIsOk
) {
671 return EFI_INVALID_PARAMETER
;
674 if (!Mode
->Started
) {
675 return EFI_NOT_STARTED
;
678 Mode
->IcmpErrorReceived
= FALSE
;
681 // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
682 // use the previous setting;
683 // If info isn't offered,
684 // use the cached DhcpAck and ProxyOffer packets.
686 if (*Layer
!= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
) {
688 if (!Mode
->PxeDiscoverValid
|| !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
690 return EFI_INVALID_PARAMETER
;
693 DefaultInfo
.IpCnt
= 1;
694 DefaultInfo
.UseUCast
= TRUE
;
696 DefaultSrvList
.Type
= Type
;
697 DefaultSrvList
.AcceptAnyResponse
= FALSE
;
698 DefaultSrvList
.IpAddr
.Addr
[0] = Private
->ServerIp
.Addr
[0];
700 SrvList
= &DefaultSrvList
;
702 } else if (Info
== NULL
) {
704 // Create info by the cached packet before
706 Packet
= (Mode
->ProxyOfferReceived
) ? &Private
->ProxyOffer
: &Private
->Dhcp4Ack
;
707 VendorOpt
= &Packet
->PxeVendorOption
;
709 if (!Mode
->DhcpAckReceived
|| !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt
->BitMap
)) {
711 // Address is not acquired or no discovery options.
713 return EFI_INVALID_PARAMETER
;
716 DefaultInfo
.UseMCast
= (BOOLEAN
)!IS_DISABLE_MCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
717 DefaultInfo
.UseBCast
= (BOOLEAN
)!IS_DISABLE_BCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
718 DefaultInfo
.MustUseList
= (BOOLEAN
) IS_ENABLE_USE_SERVER_LIST (VendorOpt
->DiscoverCtrl
);
719 DefaultInfo
.UseUCast
= DefaultInfo
.MustUseList
;
721 if (DefaultInfo
.UseMCast
) {
723 // Get the multicast discover ip address from vendor option.
725 CopyMem (&DefaultInfo
.ServerMCastIp
.Addr
, &VendorOpt
->DiscoverMcastIp
, sizeof (EFI_IPv4_ADDRESS
));
728 DefaultInfo
.IpCnt
= 0;
730 if (DefaultInfo
.MustUseList
) {
731 BootSvrEntry
= VendorOpt
->BootSvr
;
732 Status
= EFI_INVALID_PARAMETER
;
734 while (((UINT8
) (BootSvrEntry
- VendorOpt
->BootSvr
)) < VendorOpt
->BootSvrLen
) {
736 if (BootSvrEntry
->Type
== HTONS (Type
)) {
737 Status
= EFI_SUCCESS
;
741 BootSvrEntry
= GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry
);
744 if (EFI_ERROR (Status
)) {
748 DefaultInfo
.IpCnt
= BootSvrEntry
->IpCnt
;
754 SrvList
= Info
->SrvList
;
756 if (!SrvList
[0].AcceptAnyResponse
) {
758 for (Index
= 1; Index
< Info
->IpCnt
; Index
++) {
759 if (SrvList
[Index
].AcceptAnyResponse
) {
764 if (Index
!= Info
->IpCnt
) {
765 return EFI_INVALID_PARAMETER
;
770 if ((!Info
->UseUCast
&& !Info
->UseBCast
&& !Info
->UseMCast
) || (Info
->MustUseList
&& Info
->IpCnt
== 0)) {
772 return EFI_INVALID_PARAMETER
;
775 // Execute discover by UniCast/BroadCast/MultiCast
777 if (Info
->UseUCast
) {
779 for (Index
= 0; Index
< Info
->IpCnt
; Index
++) {
781 if (BootSvrEntry
== NULL
) {
782 Private
->ServerIp
.Addr
[0] = SrvList
[Index
].IpAddr
.Addr
[0];
784 CopyMem (&Private
->ServerIp
, &BootSvrEntry
->IpAddr
[Index
], sizeof (EFI_IPv4_ADDRESS
));
787 Status
= PxeBcDiscvBootService (
792 &SrvList
[Index
].IpAddr
,
796 &Private
->PxeReply
.Packet
.Ack
800 } else if (Info
->UseMCast
) {
802 Status
= PxeBcDiscvBootService (
807 &Info
->ServerMCastIp
,
811 &Private
->PxeReply
.Packet
.Ack
814 } else if (Info
->UseBCast
) {
816 Status
= PxeBcDiscvBootService (
825 &Private
->PxeReply
.Packet
.Ack
829 if (EFI_ERROR (Status
) || !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
830 if (Status
== EFI_ICMP_ERROR
) {
831 Mode
->IcmpErrorReceived
= TRUE
;
833 Status
= EFI_DEVICE_ERROR
;
836 PxeBcParseCachedDhcpPacket (&Private
->PxeReply
);
839 if (Mode
->PxeBisReplyReceived
) {
840 CopyMem (&Private
->ServerIp
, &Mode
->PxeReply
.Dhcpv4
.BootpSiAddr
, sizeof (EFI_IPv4_ADDRESS
));
848 GC_NOTO: Add function description
850 @param This GC_NOTO: add argument
852 @param Operation GC_NOTO: add argument
854 @param BufferPtr GC_NOTO: add argument
856 @param Overwrite GC_NOTO: add argument
858 @param BufferSize GC_NOTO: add argument
860 @param BlockSize GC_NOTO: add argument
862 @param ServerIp GC_NOTO: add argument
864 @param Filename GC_NOTO: add argument
866 @param Info GC_NOTO: add argument
868 @param DontUseBuffer GC_NOTO: add argument
871 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
878 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
879 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
880 IN OUT VOID
*BufferPtr
,
881 IN BOOLEAN Overwrite
,
882 IN OUT UINT64
*BufferSize
,
883 IN UINTN
*BlockSize OPTIONAL
,
884 IN EFI_IP_ADDRESS
*ServerIp
,
886 IN EFI_PXE_BASE_CODE_MTFTP_INFO
*Info OPTIONAL
,
887 IN BOOLEAN DontUseBuffer
890 PXEBC_PRIVATE_DATA
*Private
;
891 EFI_MTFTP4_CONFIG_DATA Mtftp4Config
;
893 EFI_PXE_BASE_CODE_MODE
*Mode
;
894 EFI_MAC_ADDRESS TempMacAddr
;
896 if ((This
== NULL
) ||
897 (Filename
== NULL
) ||
898 (BufferSize
== NULL
) ||
899 ((ServerIp
== NULL
) || !Ip4IsUnicast (NTOHL (ServerIp
->Addr
[0]), 0)) ||
900 ((BufferPtr
== NULL
) && DontUseBuffer
) ||
901 ((BlockSize
!= NULL
) && (*BlockSize
< 512))) {
903 return EFI_INVALID_PARAMETER
;
906 Status
= EFI_DEVICE_ERROR
;
907 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
908 Mode
= &Private
->Mode
;
910 if (!Mode
->AutoArp
) {
912 // If AutoArp is set false, check arp cache
914 UpdateArpCache (This
);
915 if (!FindInArpCache (Mode
, &ServerIp
->v4
, &TempMacAddr
)) {
916 return EFI_DEVICE_ERROR
;
920 Mode
->TftpErrorReceived
= FALSE
;
921 Mode
->IcmpErrorReceived
= FALSE
;
923 Mtftp4Config
.UseDefaultSetting
= FALSE
;
924 Mtftp4Config
.TimeoutValue
= PXEBC_MTFTP_TIMEOUT
;
925 Mtftp4Config
.TryCount
= PXEBC_MTFTP_RETRIES
;
927 CopyMem (&Mtftp4Config
.StationIp
, &Private
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
928 CopyMem (&Mtftp4Config
.SubnetMask
, &Private
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
929 CopyMem (&Mtftp4Config
.GatewayIp
, &Private
->GatewayIp
, sizeof (EFI_IPv4_ADDRESS
));
930 CopyMem (&Mtftp4Config
.ServerIp
, ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
934 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
:
936 Status
= PxeBcTftpGetFileSize (
944 if (!EFI_ERROR (Status
)) {
945 Status
= EFI_BUFFER_TOO_SMALL
;
950 case EFI_PXE_BASE_CODE_TFTP_READ_FILE
:
952 Status
= PxeBcTftpReadFile (
964 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
:
966 Status
= PxeBcTftpWriteFile (
978 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY
:
980 Status
= PxeBcTftpReadDirectory (
992 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE
:
993 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE
:
994 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY
:
995 Status
= EFI_UNSUPPORTED
;
1000 Status
= EFI_INVALID_PARAMETER
;
1004 if (Status
== EFI_ICMP_ERROR
) {
1005 Mode
->IcmpErrorReceived
= TRUE
;
1013 GC_NOTO: Add function description
1015 @param This GC_NOTO: add argument
1017 @param OpFlags GC_NOTO: add argument
1019 @param DestIp GC_NOTO: add argument
1021 @param DestPort GC_NOTO: add argument
1023 @param GatewayIp GC_NOTO: add argument
1025 @param SrcIp GC_NOTO: add argument
1027 @param SrcPort GC_NOTO: add argument
1029 @param HeaderSize GC_NOTO: add argument
1031 @param HeaderPtr GC_NOTO: add argument
1033 @param BufferSize GC_NOTO: add argument
1035 @param BufferPtr GC_NOTO: add argument
1038 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1040 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1042 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1044 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1046 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1053 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1055 IN EFI_IP_ADDRESS
*DestIp
,
1056 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
,
1057 IN EFI_IP_ADDRESS
*GatewayIp OPTIONAL
,
1058 IN EFI_IP_ADDRESS
*SrcIp OPTIONAL
,
1059 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort OPTIONAL
,
1060 IN UINTN
*HeaderSize OPTIONAL
,
1061 IN VOID
*HeaderPtr OPTIONAL
,
1062 IN UINTN
*BufferSize
,
1066 PXEBC_PRIVATE_DATA
*Private
;
1067 EFI_UDP4_PROTOCOL
*Udp4
;
1068 EFI_UDP4_COMPLETION_TOKEN Token
;
1069 EFI_UDP4_TRANSMIT_DATA
*Udp4TxData
;
1072 EFI_UDP4_SESSION_DATA Udp4Session
;
1075 EFI_PXE_BASE_CODE_MODE
*Mode
;
1076 EFI_MAC_ADDRESS TempMacAddr
;
1080 if ((This
== NULL
) || (DestIp
== NULL
) || (DestPort
== NULL
)) {
1081 return EFI_INVALID_PARAMETER
;
1084 if ((GatewayIp
!= NULL
) && !Ip4IsUnicast (NTOHL (GatewayIp
->Addr
[0]), 0)) {
1086 // Gateway is provided but it's not a unicast IP address.
1088 return EFI_INVALID_PARAMETER
;
1091 if ((HeaderSize
!= NULL
) && ((*HeaderSize
== 0) || (HeaderPtr
== NULL
))) {
1093 // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
1096 return EFI_INVALID_PARAMETER
;
1099 if ((BufferSize
== NULL
) || ((*BufferSize
!= 0) && (BufferPtr
== NULL
))) {
1100 return EFI_INVALID_PARAMETER
;
1103 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1104 Udp4
= Private
->Udp4Write
;
1105 Mode
= &Private
->Mode
;
1106 if (!Mode
->Started
) {
1107 return EFI_NOT_STARTED
;
1110 if (!Private
->AddressIsOk
&& (SrcIp
== NULL
)) {
1111 return EFI_INVALID_PARAMETER
;
1114 if (!Mode
->AutoArp
) {
1116 // If AutoArp is set false, check arp cache
1118 UpdateArpCache (This
);
1119 if (!FindInArpCache (Mode
, &DestIp
->v4
, &TempMacAddr
)) {
1120 return EFI_DEVICE_ERROR
;
1124 Mode
->IcmpErrorReceived
= FALSE
;
1126 if ((Private
->CurrentUdpSrcPort
== 0) ||
1127 ((SrcPort
!= NULL
) && (*SrcPort
!= Private
->CurrentUdpSrcPort
))) {
1129 // Port is changed, (re)configure the Udp4Write instance
1131 if (SrcPort
!= NULL
) {
1132 Private
->CurrentUdpSrcPort
= *SrcPort
;
1135 Status
= PxeBcConfigureUdpWriteInstance (
1137 &Private
->StationIp
.v4
,
1138 &Private
->SubnetMask
.v4
,
1139 &Private
->GatewayIp
.v4
,
1140 &Private
->CurrentUdpSrcPort
1142 if (EFI_ERROR (Status
)) {
1143 Private
->CurrentUdpSrcPort
= 0;
1144 return EFI_INVALID_PARAMETER
;
1148 ZeroMem (&Token
, sizeof (EFI_UDP4_COMPLETION_TOKEN
));
1149 ZeroMem (&Udp4Session
, sizeof (EFI_UDP4_SESSION_DATA
));
1151 CopyMem (&Udp4Session
.DestinationAddress
, DestIp
, sizeof (EFI_IPv4_ADDRESS
));
1152 Udp4Session
.DestinationPort
= *DestPort
;
1153 if (SrcIp
!= NULL
) {
1154 CopyMem (&Udp4Session
.SourceAddress
, SrcIp
, sizeof (EFI_IPv4_ADDRESS
));
1156 if (SrcPort
!= NULL
) {
1157 Udp4Session
.SourcePort
= *SrcPort
;
1160 FragCount
= (HeaderSize
!= NULL
) ? 2 : 1;
1161 Udp4TxData
= (EFI_UDP4_TRANSMIT_DATA
*) AllocatePool (sizeof (EFI_UDP4_TRANSMIT_DATA
) + (FragCount
- 1) * sizeof (EFI_UDP4_FRAGMENT_DATA
));
1162 if (Udp4TxData
== NULL
) {
1163 return EFI_OUT_OF_RESOURCES
;
1166 Udp4TxData
->FragmentCount
= FragCount
;
1167 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentLength
= (UINT32
) *BufferSize
;
1168 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentBuffer
= BufferPtr
;
1169 DataLength
= (UINT32
) *BufferSize
;
1171 if (FragCount
== 2) {
1173 Udp4TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) *HeaderSize
;
1174 Udp4TxData
->FragmentTable
[0].FragmentBuffer
= HeaderPtr
;
1175 DataLength
+= (UINT32
) *HeaderSize
;
1178 if (GatewayIp
!= NULL
) {
1179 Udp4TxData
->GatewayAddress
= (EFI_IPv4_ADDRESS
*) GatewayIp
;
1181 Udp4TxData
->UdpSessionData
= &Udp4Session
;
1182 Udp4TxData
->DataLength
= DataLength
;
1183 Token
.Packet
.TxData
= Udp4TxData
;
1185 Status
= gBS
->CreateEvent (
1192 if (EFI_ERROR (Status
)) {
1196 Status
= Udp4
->Transmit (Udp4
, &Token
);
1197 if (EFI_ERROR (Status
)) {
1198 if (Status
== EFI_ICMP_ERROR
) {
1199 Mode
->IcmpErrorReceived
= TRUE
;
1209 Status
= Token
.Status
;
1213 if (Token
.Event
!= NULL
) {
1214 gBS
->CloseEvent (Token
.Event
);
1217 gBS
->FreePool (Udp4TxData
);
1223 Validate IP packages by IP filter settings
1225 @param PxeBcMode Pointer to EFI_PXEBC_MODE
1227 @param Session Received UDP session
1229 @retval TRUE The UDP package matches IP filters
1231 @retval FLASE The UDP package doesn't matches IP filters
1237 EFI_PXE_BASE_CODE_MODE
*PxeBcMode
,
1238 EFI_UDP4_SESSION_DATA
*Session
1242 EFI_IPv4_ADDRESS Ip4Address
;
1243 EFI_IPv4_ADDRESS DestIp4Address
;
1245 if (PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1249 CopyMem (&DestIp4Address
, &Session
->DestinationAddress
, sizeof (DestIp4Address
));
1250 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) &&
1251 IP4_IS_MULTICAST (EFI_NTOHL (DestIp4Address
))
1256 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) &&
1257 IP4_IS_LOCAL_BROADCAST (EFI_NTOHL (DestIp4Address
))
1262 CopyMem (&Ip4Address
, &PxeBcMode
->StationIp
.v4
, sizeof (Ip4Address
));
1263 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) &&
1264 EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)
1269 for (Index
= 0; Index
< PxeBcMode
->IpFilter
.IpCnt
; ++Index
) {
1270 CopyMem (&Ip4Address
, &PxeBcMode
->IpFilter
.IpList
[Index
].v4
, sizeof (Ip4Address
));
1271 if (EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)) {
1280 GC_NOTO: Add function description
1282 @param This GC_NOTO: add argument
1284 @param OpFlags GC_NOTO: add argument
1286 @param DestIp GC_NOTO: add argument
1288 @param DestPort GC_NOTO: add argument
1290 @param SrcIp GC_NOTO: add argument
1292 @param SrcPort GC_NOTO: add argument
1294 @param HeaderSize GC_NOTO: add argument
1296 @param HeaderPtr GC_NOTO: add argument
1298 @param BufferSize GC_NOTO: add argument
1300 @param BufferPtr GC_NOTO: add argument
1303 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1305 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1307 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1309 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1311 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1313 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1320 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1322 IN OUT EFI_IP_ADDRESS
*DestIp
, OPTIONAL
1323 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
, OPTIONAL
1324 IN OUT EFI_IP_ADDRESS
*SrcIp
, OPTIONAL
1325 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort
, OPTIONAL
1326 IN UINTN
*HeaderSize
, OPTIONAL
1327 IN VOID
*HeaderPtr
, OPTIONAL
1328 IN OUT UINTN
*BufferSize
,
1332 PXEBC_PRIVATE_DATA
*Private
;
1333 EFI_PXE_BASE_CODE_MODE
*Mode
;
1334 EFI_UDP4_PROTOCOL
*Udp4
;
1335 EFI_UDP4_COMPLETION_TOKEN Token
;
1336 EFI_UDP4_RECEIVE_DATA
*RxData
;
1337 EFI_UDP4_SESSION_DATA
*Session
;
1343 if (This
== NULL
|| DestIp
== NULL
|| DestPort
== NULL
) {
1344 return EFI_INVALID_PARAMETER
;
1347 if ((!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (DestPort
== NULL
)) ||
1348 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (SrcIp
== NULL
)) ||
1349 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && (SrcPort
== NULL
))) {
1350 return EFI_INVALID_PARAMETER
;
1353 if (((HeaderSize
!= NULL
) && (*HeaderSize
== 0)) || ((HeaderSize
!= NULL
) && (HeaderPtr
== NULL
))) {
1354 return EFI_INVALID_PARAMETER
;
1357 if ((BufferSize
== NULL
) || ((BufferPtr
== NULL
) && (*BufferSize
!= 0))) {
1358 return EFI_INVALID_PARAMETER
;
1361 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1362 Mode
= Private
->PxeBc
.Mode
;
1363 Udp4
= Private
->Udp4Read
;
1365 if (!Mode
->Started
) {
1366 return EFI_NOT_STARTED
;
1369 Mode
->IcmpErrorReceived
= FALSE
;
1371 Status
= gBS
->CreateEvent (
1378 if (EFI_ERROR (Status
)) {
1379 return EFI_OUT_OF_RESOURCES
;
1385 Status
= Udp4
->Receive (Udp4
, &Token
);
1386 if (EFI_ERROR (Status
)) {
1387 if (Status
== EFI_ICMP_ERROR
) {
1388 Mode
->IcmpErrorReceived
= TRUE
;
1396 Status
= EFI_TIMEOUT
;
1400 // check whether this packet matches the filters
1402 if (EFI_ERROR (Token
.Status
)){
1406 RxData
= Token
.Packet
.RxData
;
1407 Session
= &RxData
->UdpSession
;
1411 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
) {
1413 // Check UDP package by IP filter settings
1415 if (CheckIpByFilter (Mode
, Session
)) {
1424 // Match the destination ip of the received udp dgram
1426 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
) {
1429 if (DestIp
!= NULL
) {
1430 CopyMem (DestIp
, &Session
->DestinationAddress
, sizeof (EFI_IPv4_ADDRESS
));
1433 if (DestIp
!= NULL
) {
1434 if (EFI_IP4_EQUAL (DestIp
, &Session
->DestinationAddress
)) {
1438 if (EFI_IP4_EQUAL (&Private
->StationIp
, &Session
->DestinationAddress
)) {
1447 // Match the destination port of the received udp dgram
1449 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) {
1451 if (DestPort
!= NULL
) {
1452 *DestPort
= Session
->DestinationPort
;
1456 if (*DestPort
!= Session
->DestinationPort
) {
1464 // Match the source ip of the received udp dgram
1466 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) {
1468 if (SrcIp
!= NULL
) {
1469 CopyMem (SrcIp
, &Session
->SourceAddress
, sizeof (EFI_IPv4_ADDRESS
));
1473 if (!EFI_IP4_EQUAL (SrcIp
, &Session
->SourceAddress
)) {
1481 // Match the source port of the received udp dgram
1483 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
1485 if (SrcPort
!= NULL
) {
1486 *SrcPort
= Session
->SourcePort
;
1490 if (*SrcPort
!= Session
->SourcePort
) {
1500 if (HeaderSize
!= NULL
) {
1501 CopyLen
= MIN (*HeaderSize
, RxData
->DataLength
);
1502 CopyMem (HeaderPtr
, RxData
->FragmentTable
[0].FragmentBuffer
, CopyLen
);
1503 *HeaderSize
= CopyLen
;
1506 if (RxData
->DataLength
- CopyLen
> *BufferSize
) {
1508 Status
= EFI_BUFFER_TOO_SMALL
;
1511 *BufferSize
= RxData
->DataLength
- CopyLen
;
1512 CopyMem (BufferPtr
, (UINT8
*) RxData
->FragmentTable
[0].FragmentBuffer
+ CopyLen
, *BufferSize
);
1516 Status
= EFI_TIMEOUT
;
1520 // Recycle the RxData
1522 gBS
->SignalEvent (RxData
->RecycleSignal
);
1531 Udp4
->Cancel (Udp4
, &Token
);
1533 gBS
->CloseEvent (Token
.Event
);
1540 GC_NOTO: Add function description
1542 @param This GC_NOTO: add argument
1544 @param NewFilter GC_NOTO: add argument
1547 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1553 EfiPxeBcSetIpFilter (
1554 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1555 IN EFI_PXE_BASE_CODE_IP_FILTER
*NewFilter
1559 PXEBC_PRIVATE_DATA
*Private
;
1560 EFI_PXE_BASE_CODE_MODE
*Mode
;
1562 BOOLEAN PromiscuousNeed
;
1565 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL.\n"));
1566 return EFI_INVALID_PARAMETER
;
1569 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1570 Mode
= Private
->PxeBc
.Mode
;
1572 if (Private
== NULL
) {
1573 DEBUG ((EFI_D_ERROR
, "PXEBC_PRIVATE_DATA poiner == NULL.\n"));
1574 return EFI_INVALID_PARAMETER
;
1577 if (NewFilter
== NULL
) {
1578 DEBUG ((EFI_D_ERROR
, "IP Filter *NewFilter == NULL.\n"));
1579 return EFI_INVALID_PARAMETER
;
1582 if (!Mode
->Started
) {
1583 DEBUG ((EFI_D_ERROR
, "BC was not started.\n"));
1584 return EFI_NOT_STARTED
;
1587 PromiscuousNeed
= FALSE
;
1588 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1589 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter
->IpList
[Index
].v4
))) {
1591 // The IP is a broadcast address.
1593 DEBUG ((EFI_D_ERROR
, "There is broadcast address in NewFilter.\n"));
1594 return EFI_INVALID_PARAMETER
;
1596 if (Ip4IsUnicast (EFI_IP4 (NewFilter
->IpList
[Index
].v4
), 0) &&
1597 (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
)
1600 // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,
1601 // promiscuous mode is needed.
1603 PromiscuousNeed
= TRUE
;
1608 // Clear the UDP instance configuration, all joined groups will be left
1609 // during the operation.
1611 Private
->Udp4Read
->Configure (Private
->Udp4Read
, NULL
);
1612 Private
->Udp4CfgData
.AcceptPromiscuous
= FALSE
;
1613 Private
->Udp4CfgData
.AcceptBroadcast
= FALSE
;
1615 if (PromiscuousNeed
||
1616 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
||
1617 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
1620 // Configure the udp4 filter to receive all packages
1622 Private
->Udp4CfgData
.AcceptPromiscuous
= TRUE
;
1625 // Configure the UDP instance with the new configuration.
1627 Status
= Private
->Udp4Read
->Configure (Private
->Udp4Read
, &Private
->Udp4CfgData
);
1628 if (EFI_ERROR (Status
)) {
1634 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) {
1636 // Configure the udp4 filter to receive all broadcast packages
1638 Private
->Udp4CfgData
.AcceptBroadcast
= TRUE
;
1642 // Configure the UDP instance with the new configuration.
1644 Status
= Private
->Udp4Read
->Configure (Private
->Udp4Read
, &Private
->Udp4CfgData
);
1645 if (EFI_ERROR (Status
)) {
1649 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1651 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1652 if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter
->IpList
[Index
].v4
))) {
1654 // Join the mutilcast group
1656 Status
= Private
->Udp4Read
->Groups (Private
->Udp4Read
, TRUE
, &NewFilter
->IpList
[Index
].v4
);
1657 if (EFI_ERROR (Status
)) {
1667 // Save the new filter.
1669 CopyMem (&Mode
->IpFilter
, NewFilter
, sizeof (Mode
->IpFilter
));
1676 GC_NOTO: Add function description
1678 @param This GC_NOTO: add argument
1680 @param IpAddr GC_NOTO: add argument
1682 @param MacAddr GC_NOTO: add argument
1685 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1692 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1693 IN EFI_IP_ADDRESS
* IpAddr
,
1694 IN EFI_MAC_ADDRESS
* MacAddr OPTIONAL
1697 PXEBC_PRIVATE_DATA
*Private
;
1698 EFI_PXE_BASE_CODE_MODE
*Mode
;
1700 EFI_MAC_ADDRESS TempMacAddr
;
1702 if (This
== NULL
|| IpAddr
== NULL
) {
1703 return EFI_INVALID_PARAMETER
;
1706 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1707 Mode
= Private
->PxeBc
.Mode
;
1709 if (!Mode
->Started
) {
1710 return EFI_NOT_STARTED
;
1713 if (!Private
->AddressIsOk
|| Mode
->UsingIpv6
) {
1715 // We can't resolve the IP address if we don't have a local address now.
1716 // Don't have ARP for IPv6.
1718 return EFI_INVALID_PARAMETER
;
1721 Mode
->IcmpErrorReceived
= FALSE
;
1723 if (!Mode
->AutoArp
) {
1725 // If AutoArp is set false, check arp cache
1727 UpdateArpCache (This
);
1728 if (!FindInArpCache (Mode
, &IpAddr
->v4
, &TempMacAddr
)) {
1729 return EFI_DEVICE_ERROR
;
1732 Status
= Private
->Arp
->Request (Private
->Arp
, &IpAddr
->v4
, NULL
, &TempMacAddr
);
1733 if (EFI_ERROR (Status
)) {
1734 if (Status
== EFI_ICMP_ERROR
) {
1735 Mode
->IcmpErrorReceived
= TRUE
;
1741 if (MacAddr
!= NULL
) {
1742 CopyMem (MacAddr
, &TempMacAddr
, sizeof (EFI_MAC_ADDRESS
));
1751 GC_NOTO: Add function description
1753 @param This GC_NOTO: add argument
1755 @param NewAutoArp GC_NOTO: add argument
1757 @param NewSendGUID GC_NOTO: add argument
1759 @param NewTTL GC_NOTO: add argument
1761 @param NewToS GC_NOTO: add argument
1763 @param NewMakeCallback GC_NOTO: add argument
1766 @return GC_NOTO: add return values
1771 EfiPxeBcSetParameters (
1772 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1773 IN BOOLEAN
*NewAutoArp
, OPTIONAL
1774 IN BOOLEAN
*NewSendGUID
, OPTIONAL
1775 IN UINT8
*NewTTL
, OPTIONAL
1776 IN UINT8
*NewToS
, OPTIONAL
1777 IN BOOLEAN
*NewMakeCallback
// OPTIONAL
1780 PXEBC_PRIVATE_DATA
*Private
;
1781 EFI_PXE_BASE_CODE_MODE
*Mode
;
1784 Status
= EFI_SUCCESS
;
1787 Status
= EFI_INVALID_PARAMETER
;
1791 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1792 Mode
= Private
->PxeBc
.Mode
;
1794 if (NewSendGUID
!= NULL
&& *NewSendGUID
== TRUE
) {
1796 // FixMe, cann't locate SendGuid
1800 if (NewMakeCallback
!= NULL
&& *NewMakeCallback
== TRUE
) {
1802 Status
= gBS
->HandleProtocol (
1803 Private
->Controller
,
1804 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1805 (VOID
**) &Private
->PxeBcCallback
1807 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1809 Status
= EFI_INVALID_PARAMETER
;
1814 if (!Mode
->Started
) {
1815 Status
= EFI_NOT_STARTED
;
1819 if (NewMakeCallback
!= NULL
) {
1821 if (*NewMakeCallback
) {
1823 // Update the Callback protocol.
1825 Status
= gBS
->HandleProtocol (
1826 Private
->Controller
,
1827 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1828 (VOID
**) &Private
->PxeBcCallback
1831 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1832 Status
= EFI_INVALID_PARAMETER
;
1836 Private
->PxeBcCallback
= NULL
;
1839 Mode
->MakeCallbacks
= *NewMakeCallback
;
1842 if (NewAutoArp
!= NULL
) {
1843 Mode
->AutoArp
= *NewAutoArp
;
1846 if (NewSendGUID
!= NULL
) {
1847 Mode
->SendGUID
= *NewSendGUID
;
1850 if (NewTTL
!= NULL
) {
1851 Mode
->TTL
= *NewTTL
;
1854 if (NewToS
!= NULL
) {
1855 Mode
->ToS
= *NewToS
;
1864 GC_NOTO: Add function description
1866 @param This GC_NOTO: add argument
1868 @param NewStationIp GC_NOTO: add argument
1870 @param NewSubnetMask GC_NOTO: add argument
1873 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1875 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1877 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1879 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1881 @retval EFI_SUCCESS GC_NOTO: Add description for
1887 EfiPxeBcSetStationIP (
1888 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1889 IN EFI_IP_ADDRESS
* NewStationIp
, OPTIONAL
1890 IN EFI_IP_ADDRESS
* NewSubnetMask OPTIONAL
1893 PXEBC_PRIVATE_DATA
*Private
;
1894 EFI_PXE_BASE_CODE_MODE
*Mode
;
1895 EFI_ARP_CONFIG_DATA ArpConfigData
;
1898 return EFI_INVALID_PARAMETER
;
1901 if (NewStationIp
!= NULL
&& !Ip4IsUnicast (NTOHL (NewStationIp
->Addr
[0]), 0)) {
1902 return EFI_INVALID_PARAMETER
;
1905 if (NewSubnetMask
!= NULL
&& !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask
->Addr
[0]))) {
1906 return EFI_INVALID_PARAMETER
;
1909 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1910 Mode
= Private
->PxeBc
.Mode
;
1912 if (!Mode
->Started
) {
1913 return EFI_NOT_STARTED
;
1916 if (NewStationIp
!= NULL
) {
1917 Mode
->StationIp
= *NewStationIp
;
1918 Private
->StationIp
= *NewStationIp
;
1921 if (NewSubnetMask
!= NULL
) {
1922 Mode
->SubnetMask
= *NewSubnetMask
;
1923 Private
->SubnetMask
= *NewSubnetMask
;
1926 Private
->AddressIsOk
= TRUE
;
1928 if (!Mode
->UsingIpv6
) {
1930 // If in IPv4 mode, configure the corresponding ARP with this new
1931 // station IP address.
1933 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
1935 ArpConfigData
.SwAddressType
= 0x0800;
1936 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
1937 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
1939 Private
->Arp
->Configure (Private
->Arp
, NULL
);
1940 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
1943 // Update the route table.
1945 Mode
->RouteTableEntries
= 1;
1946 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
1947 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
1948 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
1956 GC_NOTO: Add function description
1958 @param This GC_NOTO: add argument
1960 @param NewDhcpDiscoverValid GC_NOTO: add argument
1962 @param NewDhcpAckReceived GC_NOTO: add argument
1964 @param NewProxyOfferReceived GC_NOTO: add argument
1966 @param NewPxeDiscoverValid GC_NOTO: add argument
1968 @param NewPxeReplyReceived GC_NOTO: add argument
1970 @param NewPxeBisReplyReceived GC_NOTO: add argument
1972 @param NewDhcpDiscover GC_NOTO: add argument
1974 @param NewDhcpAck GC_NOTO: add argument
1976 @param NewProxyOffer GC_NOTO: add argument
1978 @param NewPxeDiscover GC_NOTO: add argument
1980 @param NewPxeReply GC_NOTO: add argument
1982 @param NewPxeBisReply GC_NOTO: add argument
1985 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1987 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1989 @retval EFI_SUCCESS GC_NOTO: Add description for
1995 EfiPxeBcSetPackets (
1996 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1997 IN BOOLEAN
* NewDhcpDiscoverValid
, OPTIONAL
1998 IN BOOLEAN
* NewDhcpAckReceived
, OPTIONAL
1999 IN BOOLEAN
* NewProxyOfferReceived
, OPTIONAL
2000 IN BOOLEAN
* NewPxeDiscoverValid
, OPTIONAL
2001 IN BOOLEAN
* NewPxeReplyReceived
, OPTIONAL
2002 IN BOOLEAN
* NewPxeBisReplyReceived
, OPTIONAL
2003 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
2004 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
2005 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
2006 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
2007 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
2008 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
2011 PXEBC_PRIVATE_DATA
*Private
;
2012 EFI_PXE_BASE_CODE_MODE
*Mode
;
2015 return EFI_INVALID_PARAMETER
;
2018 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
2019 Mode
= Private
->PxeBc
.Mode
;
2021 if (!Mode
->Started
) {
2022 return EFI_NOT_STARTED
;
2025 Private
->FileSize
= 0;
2027 if (NewDhcpDiscoverValid
!= NULL
) {
2028 Mode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
2031 if (NewDhcpAckReceived
!= NULL
) {
2032 Mode
->DhcpAckReceived
= *NewDhcpAckReceived
;
2035 if (NewProxyOfferReceived
!= NULL
) {
2036 Mode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
2039 if (NewPxeDiscoverValid
!= NULL
) {
2040 Mode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
2043 if (NewPxeReplyReceived
!= NULL
) {
2044 Mode
->PxeReplyReceived
= *NewPxeReplyReceived
;
2047 if (NewPxeBisReplyReceived
!= NULL
) {
2048 Mode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
2051 if (NewDhcpDiscover
!= NULL
) {
2052 CopyMem (&Mode
->DhcpDiscover
, NewDhcpDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2055 if (NewDhcpAck
!= NULL
) {
2056 CopyMem (&Mode
->DhcpAck
, NewDhcpAck
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2059 if (NewProxyOffer
!= NULL
) {
2060 CopyMem (&Mode
->ProxyOffer
, NewProxyOffer
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2063 if (NewPxeDiscover
!= NULL
) {
2064 CopyMem (&Mode
->PxeDiscover
, NewPxeDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2067 if (NewPxeReply
!= NULL
) {
2068 CopyMem (&Mode
->PxeReply
, NewPxeReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2071 if (NewPxeBisReply
!= NULL
) {
2072 CopyMem (&Mode
->PxeBisReply
, NewPxeBisReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2078 EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate
= {
2079 EFI_PXE_BASE_CODE_PROTOCOL_REVISION
,
2087 EfiPxeBcSetIpFilter
,
2089 EfiPxeBcSetParameters
,
2090 EfiPxeBcSetStationIP
,
2097 GC_NOTO: Add function description
2099 @param This GC_NOTO: add argument
2101 @param Function GC_NOTO: add argument
2103 @param Received GC_NOTO: add argument
2105 @param PacketLength GC_NOTO: add argument
2107 @param PacketPtr GC_NOTO: add argument
2110 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT GC_NOTO: Add description for
2112 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2114 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2116 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2118 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2122 EFI_PXE_BASE_CODE_CALLBACK_STATUS
2124 EfiPxeLoadFileCallback (
2125 IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL
* This
,
2126 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
2127 IN BOOLEAN Received
,
2128 IN UINT32 PacketLength
,
2129 IN EFI_PXE_BASE_CODE_PACKET
* PacketPtr OPTIONAL
2136 // Catch Ctrl-C or ESC to abort.
2138 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2140 if (!EFI_ERROR (Status
)) {
2142 if (Key
.ScanCode
== SCAN_ESC
|| Key
.UnicodeChar
== (0x1F & 'c')) {
2144 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT
;
2148 // No print if receive packet
2151 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2154 // Print only for three functions
2158 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP
:
2160 // Print only for open MTFTP packets, not every MTFTP packets
2162 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2163 if (PacketPtr
->Raw
[0x1C] != 0x00 || PacketPtr
->Raw
[0x1D] != 0x01) {
2164 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2169 case EFI_PXE_BASE_CODE_FUNCTION_DHCP
:
2170 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
:
2174 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2177 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2179 // Print '.' when transmit a packet
2185 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2188 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate
= {
2189 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION
,
2190 EfiPxeLoadFileCallback
2195 GC_NOTO: Add function description
2197 @param Private GC_NOTO: add argument
2199 @param BufferSize GC_NOTO: add argument
2201 @param Buffer GC_NOTO: add argument
2204 @return GC_NOTO: add return values
2209 IN PXEBC_PRIVATE_DATA
*Private
,
2210 IN OUT UINT64
*BufferSize
,
2214 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2215 EFI_PXE_BASE_CODE_MODE
*Mode
;
2221 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
2224 PxeBc
= &Private
->PxeBc
;
2226 Type
= EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
;
2227 Layer
= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
;
2232 Status
= PxeBc
->Dhcp (PxeBc
, TRUE
);
2233 if (EFI_ERROR (Status
)) {
2238 // Select a boot server
2240 Status
= PxeBcSelectBootPrompt (Private
);
2242 if (Status
== EFI_SUCCESS
) {
2243 Status
= PxeBcSelectBootMenu (Private
, &Type
, TRUE
);
2244 } else if (Status
== EFI_TIMEOUT
) {
2245 Status
= PxeBcSelectBootMenu (Private
, &Type
, FALSE
);
2248 if (!EFI_ERROR (Status
)) {
2250 if (Type
== EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
) {
2252 // Local boot(PXE bootstrap server) need abort
2257 UseBis
= (BOOLEAN
) (Mode
->BisSupported
&& Mode
->BisDetected
);
2258 Status
= PxeBc
->Discover (PxeBc
, Type
, &Layer
, UseBis
, NULL
);
2259 if (EFI_ERROR (Status
)) {
2268 // Get bootfile name and (m)tftp server ip addresss
2270 if (Mode
->PxeReplyReceived
) {
2271 Packet
= &Private
->PxeReply
;
2272 } else if (Mode
->ProxyOfferReceived
) {
2273 Packet
= &Private
->ProxyOffer
;
2275 Packet
= &Private
->Dhcp4Ack
;
2278 CopyMem (&Private
->ServerIp
, &Packet
->Packet
.Offer
.Dhcp4
.Header
.ServerAddr
, sizeof (EFI_IPv4_ADDRESS
));
2279 if (Private
->ServerIp
.Addr
[0] == 0) {
2281 // next server ip address is zero, use option 54 instead
2285 Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_SERVER_ID
]->Data
,
2286 sizeof (EFI_IPv4_ADDRESS
)
2290 ASSERT (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
);
2295 Private
->BootFileName
= (CHAR8
*) (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
]->Data
);
2297 if (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
] != NULL
) {
2299 // Already have the bootfile length option, compute the file size
2301 CopyMem (&Value
, Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
]->Data
, sizeof (Value
));
2302 Value
= NTOHS (Value
);
2303 *BufferSize
= 512 * Value
;
2304 Status
= EFI_BUFFER_TOO_SMALL
;
2307 // Get the bootfile size from tftp
2309 Status
= PxeBc
->Mtftp (
2311 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
,
2317 (UINT8
*) Private
->BootFileName
,
2323 Private
->FileSize
= (UINTN
) *BufferSize
;
2330 GC_NOTO: Add function description
2332 @param This GC_NOTO: add argument
2334 @param FilePath GC_NOTO: add argument
2336 @param BootPolicy GC_NOTO: add argument
2338 @param BufferSize GC_NOTO: add argument
2340 @param Buffer GC_NOTO: add argument
2343 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
2345 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
2352 IN EFI_LOAD_FILE_PROTOCOL
* This
,
2353 IN EFI_DEVICE_PATH_PROTOCOL
* FilePath
,
2354 IN BOOLEAN BootPolicy
,
2355 IN OUT UINTN
*BufferSize
,
2356 IN VOID
*Buffer OPTIONAL
2359 PXEBC_PRIVATE_DATA
*Private
;
2360 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2361 BOOLEAN NewMakeCallback
;
2366 Private
= PXEBC_PRIVATE_DATA_FROM_LOADFILE (This
);
2367 PxeBc
= &Private
->PxeBc
;
2368 NewMakeCallback
= FALSE
;
2370 Status
= EFI_DEVICE_ERROR
;
2372 if (This
== NULL
|| BufferSize
== NULL
) {
2374 return EFI_INVALID_PARAMETER
;
2378 // Only support BootPolicy
2381 return EFI_UNSUPPORTED
;
2384 Status
= PxeBc
->Start (PxeBc
, FALSE
);
2385 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
2389 Status
= gBS
->HandleProtocol (
2390 Private
->Controller
,
2391 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2392 (VOID
**) &Private
->PxeBcCallback
2394 if (Status
== EFI_UNSUPPORTED
) {
2396 CopyMem (&Private
->LoadFileCallback
, &mPxeBcCallBackTemplate
, sizeof (Private
->LoadFileCallback
));
2398 Status
= gBS
->InstallProtocolInterface (
2399 &Private
->Controller
,
2400 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2401 EFI_NATIVE_INTERFACE
,
2402 &Private
->LoadFileCallback
2405 NewMakeCallback
= (BOOLEAN
) (Status
== EFI_SUCCESS
);
2407 Status
= PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2408 if (EFI_ERROR (Status
)) {
2409 PxeBc
->Stop (PxeBc
);
2414 if (Private
->FileSize
== 0) {
2416 Status
= DiscoverBootFile (Private
, &TmpBufSize
, Buffer
);
2418 if (sizeof (UINTN
) < sizeof (UINT64
) && (TmpBufSize
> 0xFFFFFFFF)) {
2419 Status
= EFI_DEVICE_ERROR
;
2421 *BufferSize
= (UINTN
) TmpBufSize
;
2423 } else if (Buffer
== NULL
) {
2424 *BufferSize
= Private
->FileSize
;
2425 Status
= EFI_BUFFER_TOO_SMALL
;
2428 // Download the file.
2430 TmpBufSize
= (UINT64
) (*BufferSize
);
2431 Status
= PxeBc
->Mtftp (
2433 EFI_PXE_BASE_CODE_TFTP_READ_FILE
,
2439 (UINT8
*) Private
->BootFileName
,
2445 // If we added a callback protocol, now is the time to remove it.
2447 if (NewMakeCallback
) {
2449 NewMakeCallback
= FALSE
;
2451 PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2453 gBS
->UninstallProtocolInterface (
2454 Private
->Controller
,
2455 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2456 &Private
->LoadFileCallback
2460 // Check download status
2467 case EFI_BUFFER_TOO_SMALL
:
2468 if (Buffer
!= NULL
) {
2469 AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
2475 case EFI_DEVICE_ERROR
:
2476 AsciiPrint ("PXE-E07: Network device error.\n");
2479 case EFI_OUT_OF_RESOURCES
:
2480 AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
2484 AsciiPrint ("PXE-E12: Could not detect network connection.\n");
2487 case EFI_NO_RESPONSE
:
2488 AsciiPrint ("PXE-E16: No offer received.\n");
2492 AsciiPrint ("PXE-E18: Server response timeout.\n");
2496 AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
2499 case EFI_ICMP_ERROR
:
2500 AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
2503 case EFI_TFTP_ERROR
:
2504 AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
2508 AsciiPrint ("PXE-E99: Unexpected network error.\n");
2512 PxeBc
->Stop (PxeBc
);
2517 EFI_LOAD_FILE_PROTOCOL mLoadFileProtocolTemplate
= { EfiPxeLoadFile
};