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
->Udp4
->Configure (Private
->Udp4
, &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
;
426 // Reset and leave joined groups
428 Private
->Udp4
->Groups (Private
->Udp4
, FALSE
, NULL
);
430 Private
->Udp4
->Configure (Private
->Udp4
, NULL
);
432 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
433 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
435 Private
->FileSize
= 0;
442 GC_NOTO: Add function description
444 @param This GC_NOTO: add argument
446 @param SortOffers GC_NOTO: add argument
449 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
451 @retval EFI_NOT_STARTED GC_NOTO: Add description for
458 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
459 IN BOOLEAN SortOffers
462 PXEBC_PRIVATE_DATA
*Private
;
463 EFI_PXE_BASE_CODE_MODE
*Mode
;
464 EFI_DHCP4_PROTOCOL
*Dhcp4
;
465 EFI_DHCP4_CONFIG_DATA Dhcp4CfgData
;
466 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
467 EFI_DHCP4_PACKET_OPTION
*OptList
[PXEBC_DHCP4_MAX_OPTION_NUM
];
469 UINT32 DiscoverTimeout
;
472 EFI_ARP_CONFIG_DATA ArpConfigData
;
475 return EFI_INVALID_PARAMETER
;
478 Status
= EFI_SUCCESS
;
479 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
480 Mode
= Private
->PxeBc
.Mode
;
481 Dhcp4
= Private
->Dhcp4
;
482 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
483 Private
->SortOffers
= SortOffers
;
485 if (!Mode
->Started
) {
486 return EFI_NOT_STARTED
;
489 Mode
->IcmpErrorReceived
= FALSE
;
492 // Initialize the DHCP options and build the option list
494 OptCount
= PxeBcBuildDhcpOptions (Private
, OptList
, TRUE
);
497 // Set the DHCP4 config data.
499 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
500 Dhcp4CfgData
.OptionCount
= OptCount
;
501 Dhcp4CfgData
.OptionList
= OptList
;
502 Dhcp4CfgData
.Dhcp4Callback
= PxeBcDhcpCallBack
;
503 Dhcp4CfgData
.CallbackContext
= Private
;
504 Dhcp4CfgData
.DiscoverTryCount
= 1;
505 Dhcp4CfgData
.DiscoverTimeout
= &DiscoverTimeout
;
507 for (Index
= 0; Index
< PXEBC_DHCP4_DISCOVER_RETRIES
; Index
++) {
509 // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.
511 DiscoverTimeout
= (PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT
<< Index
);
513 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
514 if (EFI_ERROR (Status
)) {
518 // Zero those arrays to record the varies numbers of DHCP OFFERS.
520 Private
->NumOffers
= 0;
521 Private
->BootpIndex
= 0;
522 ZeroMem (Private
->ServerCount
, sizeof (Private
->ServerCount
));
523 ZeroMem (Private
->ProxyIndex
, sizeof (Private
->ProxyIndex
));
525 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
526 if (EFI_ERROR (Status
)) {
527 if (Status
== EFI_TIMEOUT
) {
529 // If no response is received or all received offers don't match
530 // the PXE boot requirements, EFI_TIMEOUT will be returned.
534 if (Status
== EFI_ICMP_ERROR
) {
535 Mode
->IcmpErrorReceived
= TRUE
;
538 // Other error status means the DHCP really fails.
543 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
544 if (EFI_ERROR (Status
)) {
548 ASSERT (Dhcp4Mode
.State
== Dhcp4Bound
);
550 CopyMem (&Private
->StationIp
, &Dhcp4Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
551 CopyMem (&Private
->SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
552 CopyMem (&Private
->GatewayIp
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
555 // Check the selected offer to see whether BINL is required, if no or BINL is
556 // finished, set the various Mode members.
558 Status
= PxeBcCheckSelectedOffer (Private
);
559 if (!EFI_ERROR (Status
)) {
564 if (EFI_ERROR (Status
)) {
566 Dhcp4
->Configure (Dhcp4
, NULL
);
569 // Remove the previously configured option list and callback function
571 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
572 Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
574 Private
->AddressIsOk
= TRUE
;
576 if (!Mode
->UsingIpv6
) {
578 // If in IPv4 mode, configure the corresponding ARP with this new
579 // station IP address.
581 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
583 ArpConfigData
.SwAddressType
= 0x0800;
584 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
585 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
587 Private
->Arp
->Configure (Private
->Arp
, NULL
);
588 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
591 // Updated the route table. Fill the first entry.
593 Mode
->RouteTableEntries
= 1;
594 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
595 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
596 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
599 // Create the default route entry if there is a default router.
601 if (Private
->GatewayIp
.Addr
[0] != 0) {
602 Mode
->RouteTableEntries
= 2;
603 Mode
->RouteTable
[1].IpAddr
.Addr
[0] = 0;
604 Mode
->RouteTable
[1].SubnetMask
.Addr
[0] = 0;
605 Mode
->RouteTable
[1].GwAddr
.Addr
[0] = Private
->GatewayIp
.Addr
[0];
615 GC_NOTO: Add function description
617 @param This GC_NOTO: add argument
619 @param Type GC_NOTO: add argument
621 @param Layer GC_NOTO: add argument
623 @param UseBis GC_NOTO: add argument
625 @param Info GC_NOTO: add argument
628 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
630 @retval EFI_NOT_STARTED 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
636 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
638 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
645 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
649 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*Info OPTIONAL
652 PXEBC_PRIVATE_DATA
*Private
;
653 EFI_PXE_BASE_CODE_MODE
*Mode
;
654 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
655 EFI_PXE_BASE_CODE_SRVLIST
*SrvList
;
656 EFI_PXE_BASE_CODE_SRVLIST DefaultSrvList
;
657 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
658 PXEBC_VENDOR_OPTION
*VendorOpt
;
661 PXEBC_BOOT_SVR_ENTRY
*BootSvrEntry
;
664 return EFI_INVALID_PARAMETER
;
667 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
668 Mode
= Private
->PxeBc
.Mode
;
671 Status
= EFI_DEVICE_ERROR
;
672 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
674 if (!Private
->AddressIsOk
) {
675 return EFI_INVALID_PARAMETER
;
678 if (!Mode
->Started
) {
679 return EFI_NOT_STARTED
;
682 Mode
->IcmpErrorReceived
= FALSE
;
685 // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
686 // use the previous setting;
687 // If info isn't offered,
688 // use the cached DhcpAck and ProxyOffer packets.
690 if (*Layer
!= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
) {
692 if (!Mode
->PxeDiscoverValid
|| !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
694 return EFI_INVALID_PARAMETER
;
697 DefaultInfo
.IpCnt
= 1;
698 DefaultInfo
.UseUCast
= TRUE
;
700 DefaultSrvList
.Type
= Type
;
701 DefaultSrvList
.AcceptAnyResponse
= FALSE
;
702 DefaultSrvList
.IpAddr
.Addr
[0] = Private
->ServerIp
.Addr
[0];
704 SrvList
= &DefaultSrvList
;
706 } else if (Info
== NULL
) {
708 // Create info by the cached packet before
710 Packet
= (Mode
->ProxyOfferReceived
) ? &Private
->ProxyOffer
: &Private
->Dhcp4Ack
;
711 VendorOpt
= &Packet
->PxeVendorOption
;
713 if (!Mode
->DhcpAckReceived
|| !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt
->BitMap
)) {
715 // Address is not acquired or no discovery options.
717 return EFI_INVALID_PARAMETER
;
720 DefaultInfo
.UseMCast
= (BOOLEAN
)!IS_DISABLE_MCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
721 DefaultInfo
.UseBCast
= (BOOLEAN
)!IS_DISABLE_BCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
722 DefaultInfo
.MustUseList
= (BOOLEAN
) IS_ENABLE_USE_SERVER_LIST (VendorOpt
->DiscoverCtrl
);
723 DefaultInfo
.UseUCast
= DefaultInfo
.MustUseList
;
725 if (DefaultInfo
.UseMCast
) {
727 // Get the multicast discover ip address from vendor option.
729 CopyMem (&DefaultInfo
.ServerMCastIp
.Addr
, &VendorOpt
->DiscoverMcastIp
, sizeof (EFI_IPv4_ADDRESS
));
732 DefaultInfo
.IpCnt
= 0;
734 if (DefaultInfo
.MustUseList
) {
735 BootSvrEntry
= VendorOpt
->BootSvr
;
736 Status
= EFI_INVALID_PARAMETER
;
738 while (((UINT8
) (BootSvrEntry
- VendorOpt
->BootSvr
)) < VendorOpt
->BootSvrLen
) {
740 if (BootSvrEntry
->Type
== HTONS (Type
)) {
741 Status
= EFI_SUCCESS
;
745 BootSvrEntry
= GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry
);
748 if (EFI_ERROR (Status
)) {
752 DefaultInfo
.IpCnt
= BootSvrEntry
->IpCnt
;
758 SrvList
= Info
->SrvList
;
760 if (!SrvList
[0].AcceptAnyResponse
) {
762 for (Index
= 1; Index
< Info
->IpCnt
; Index
++) {
763 if (SrvList
[Index
].AcceptAnyResponse
) {
768 if (Index
!= Info
->IpCnt
) {
769 return EFI_INVALID_PARAMETER
;
774 if ((!Info
->UseUCast
&& !Info
->UseBCast
&& !Info
->UseMCast
) || (Info
->MustUseList
&& Info
->IpCnt
== 0)) {
776 return EFI_INVALID_PARAMETER
;
779 // Execute discover by UniCast/BroadCast/MultiCast
781 if (Info
->UseUCast
) {
783 for (Index
= 0; Index
< Info
->IpCnt
; Index
++) {
785 if (BootSvrEntry
== NULL
) {
786 Private
->ServerIp
.Addr
[0] = SrvList
[Index
].IpAddr
.Addr
[0];
788 CopyMem (&Private
->ServerIp
, &BootSvrEntry
->IpAddr
[Index
], sizeof (EFI_IPv4_ADDRESS
));
791 Status
= PxeBcDiscvBootService (
796 &SrvList
[Index
].IpAddr
,
800 &Private
->PxeReply
.Packet
.Ack
804 } else if (Info
->UseMCast
) {
806 Status
= PxeBcDiscvBootService (
811 &Info
->ServerMCastIp
,
815 &Private
->PxeReply
.Packet
.Ack
818 } else if (Info
->UseBCast
) {
820 Status
= PxeBcDiscvBootService (
829 &Private
->PxeReply
.Packet
.Ack
833 if (EFI_ERROR (Status
) || !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
834 if (Status
== EFI_ICMP_ERROR
) {
835 Mode
->IcmpErrorReceived
= TRUE
;
837 Status
= EFI_DEVICE_ERROR
;
840 PxeBcParseCachedDhcpPacket (&Private
->PxeReply
);
843 if (Mode
->PxeBisReplyReceived
) {
844 CopyMem (&Private
->ServerIp
, &Mode
->PxeReply
.Dhcpv4
.BootpSiAddr
, sizeof (EFI_IPv4_ADDRESS
));
852 GC_NOTO: Add function description
854 @param This GC_NOTO: add argument
856 @param Operation GC_NOTO: add argument
858 @param BufferPtr GC_NOTO: add argument
860 @param Overwrite GC_NOTO: add argument
862 @param BufferSize GC_NOTO: add argument
864 @param BlockSize GC_NOTO: add argument
866 @param ServerIp GC_NOTO: add argument
868 @param Filename GC_NOTO: add argument
870 @param Info GC_NOTO: add argument
872 @param DontUseBuffer GC_NOTO: add argument
875 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
882 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
883 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
884 IN OUT VOID
*BufferPtr
,
885 IN BOOLEAN Overwrite
,
886 IN OUT UINT64
*BufferSize
,
887 IN UINTN
*BlockSize OPTIONAL
,
888 IN EFI_IP_ADDRESS
*ServerIp
,
890 IN EFI_PXE_BASE_CODE_MTFTP_INFO
*Info OPTIONAL
,
891 IN BOOLEAN DontUseBuffer
894 PXEBC_PRIVATE_DATA
*Private
;
895 EFI_MTFTP4_CONFIG_DATA Mtftp4Config
;
897 EFI_PXE_BASE_CODE_MODE
*Mode
;
898 EFI_MAC_ADDRESS TempMacAddr
;
900 if ((This
== NULL
) ||
901 (Filename
== NULL
) ||
902 (BufferSize
== NULL
) ||
903 ((ServerIp
== NULL
) || !Ip4IsUnicast (NTOHL (ServerIp
->Addr
[0]), 0)) ||
904 ((BufferPtr
== NULL
) && DontUseBuffer
) ||
905 ((BlockSize
!= NULL
) && (*BlockSize
< 512))) {
907 return EFI_INVALID_PARAMETER
;
910 Status
= EFI_DEVICE_ERROR
;
911 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
912 Mode
= &Private
->Mode
;
914 if (!Mode
->AutoArp
) {
916 // If AutoArp is set false, check arp cache
918 UpdateArpCache (This
);
919 if (!FindInArpCache (Mode
, &ServerIp
->v4
, &TempMacAddr
)) {
920 return EFI_DEVICE_ERROR
;
924 Mode
->TftpErrorReceived
= FALSE
;
925 Mode
->IcmpErrorReceived
= FALSE
;
927 Mtftp4Config
.UseDefaultSetting
= FALSE
;
928 Mtftp4Config
.TimeoutValue
= PXEBC_MTFTP_TIMEOUT
;
929 Mtftp4Config
.TryCount
= PXEBC_MTFTP_RETRIES
;
931 CopyMem (&Mtftp4Config
.StationIp
, &Private
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
932 CopyMem (&Mtftp4Config
.SubnetMask
, &Private
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
933 CopyMem (&Mtftp4Config
.GatewayIp
, &Private
->GatewayIp
, sizeof (EFI_IPv4_ADDRESS
));
934 CopyMem (&Mtftp4Config
.ServerIp
, ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
938 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
:
940 Status
= PxeBcTftpGetFileSize (
948 if (!EFI_ERROR (Status
)) {
949 Status
= EFI_BUFFER_TOO_SMALL
;
954 case EFI_PXE_BASE_CODE_TFTP_READ_FILE
:
956 Status
= PxeBcTftpReadFile (
968 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
:
970 Status
= PxeBcTftpWriteFile (
982 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY
:
984 Status
= PxeBcTftpReadDirectory (
996 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE
:
997 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE
:
998 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY
:
999 Status
= EFI_UNSUPPORTED
;
1004 Status
= EFI_INVALID_PARAMETER
;
1008 if (Status
== EFI_ICMP_ERROR
) {
1009 Mode
->IcmpErrorReceived
= TRUE
;
1017 GC_NOTO: Add function description
1019 @param This GC_NOTO: add argument
1021 @param OpFlags GC_NOTO: add argument
1023 @param DestIp GC_NOTO: add argument
1025 @param DestPort GC_NOTO: add argument
1027 @param GatewayIp GC_NOTO: add argument
1029 @param SrcIp GC_NOTO: add argument
1031 @param SrcPort GC_NOTO: add argument
1033 @param HeaderSize GC_NOTO: add argument
1035 @param HeaderPtr GC_NOTO: add argument
1037 @param BufferSize GC_NOTO: add argument
1039 @param BufferPtr GC_NOTO: add argument
1042 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1044 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1046 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1048 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1050 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1057 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1059 IN EFI_IP_ADDRESS
*DestIp
,
1060 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
,
1061 IN EFI_IP_ADDRESS
*GatewayIp OPTIONAL
,
1062 IN EFI_IP_ADDRESS
*SrcIp OPTIONAL
,
1063 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort OPTIONAL
,
1064 IN UINTN
*HeaderSize OPTIONAL
,
1065 IN VOID
*HeaderPtr OPTIONAL
,
1066 IN UINTN
*BufferSize
,
1070 PXEBC_PRIVATE_DATA
*Private
;
1071 EFI_UDP4_PROTOCOL
*Udp4
;
1072 EFI_UDP4_COMPLETION_TOKEN Token
;
1073 EFI_UDP4_TRANSMIT_DATA
*Udp4TxData
;
1076 EFI_UDP4_SESSION_DATA Udp4Session
;
1079 UINT16 RandomSrcPort
;
1080 EFI_PXE_BASE_CODE_MODE
*Mode
;
1081 EFI_MAC_ADDRESS TempMacAddr
;
1085 if ((This
== NULL
) || (DestIp
== NULL
) || (DestPort
== NULL
)) {
1086 return EFI_INVALID_PARAMETER
;
1089 if ((GatewayIp
!= NULL
) && !Ip4IsUnicast (NTOHL (GatewayIp
->Addr
[0]), 0)) {
1091 // Gateway is provided but it's not a unicast IP address.
1093 return EFI_INVALID_PARAMETER
;
1096 if ((HeaderSize
!= NULL
) && ((*HeaderSize
== 0) || (HeaderPtr
== NULL
))) {
1098 // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
1101 return EFI_INVALID_PARAMETER
;
1104 if ((BufferSize
== NULL
) || ((*BufferSize
!= 0) && (BufferPtr
== NULL
))) {
1105 return EFI_INVALID_PARAMETER
;
1108 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1109 Udp4
= Private
->Udp4
;
1110 Mode
= &Private
->Mode
;
1112 if (!Private
->AddressIsOk
&& (SrcIp
== NULL
)) {
1113 return EFI_INVALID_PARAMETER
;
1116 if (!Mode
->AutoArp
) {
1118 // If AutoArp is set false, check arp cache
1120 UpdateArpCache (This
);
1121 if (!FindInArpCache (Mode
, &DestIp
->v4
, &TempMacAddr
)) {
1122 return EFI_DEVICE_ERROR
;
1126 Mode
->IcmpErrorReceived
= FALSE
;
1128 if (SrcIp
== NULL
) {
1129 SrcIp
= &Private
->StationIp
;
1131 if (GatewayIp
== NULL
) {
1132 GatewayIp
= &Private
->GatewayIp
;
1136 if ((SrcPort
== NULL
) || (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
)) {
1137 RandomSrcPort
= (UINT16
) (NET_RANDOM (NetRandomInitSeed ()) % 10000 + 1024);
1139 if (SrcPort
== NULL
) {
1141 SrcPort
= &RandomSrcPort
;
1144 *SrcPort
= RandomSrcPort
;
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 CopyMem (&Udp4Session
.SourceAddress
, SrcIp
, sizeof (EFI_IPv4_ADDRESS
));
1154 Udp4Session
.SourcePort
= *SrcPort
;
1156 FragCount
= (HeaderSize
!= NULL
) ? 2 : 1;
1157 Udp4TxData
= (EFI_UDP4_TRANSMIT_DATA
*) AllocatePool (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 Udp4TxData
->GatewayAddress
= (EFI_IPv4_ADDRESS
*) GatewayIp
;
1175 Udp4TxData
->UdpSessionData
= &Udp4Session
;
1176 Udp4TxData
->DataLength
= DataLength
;
1177 Token
.Packet
.TxData
= Udp4TxData
;
1179 Status
= gBS
->CreateEvent (
1186 if (EFI_ERROR (Status
)) {
1190 Status
= Udp4
->Transmit (Udp4
, &Token
);
1191 if (EFI_ERROR (Status
)) {
1192 if (Status
== EFI_ICMP_ERROR
) {
1193 Mode
->IcmpErrorReceived
= TRUE
;
1203 Status
= Token
.Status
;
1207 if (Token
.Event
!= NULL
) {
1208 gBS
->CloseEvent (Token
.Event
);
1211 gBS
->FreePool (Udp4TxData
);
1217 Validate IP packages by IP filter settings
1219 @param PxeBcMode Pointer to EFI_PXEBC_MODE
1221 @param Session Received UDP session
1223 @retval TRUE The UDP package matches IP filters
1225 @retval FLASE The UDP package doesn't matches IP filters
1231 EFI_PXE_BASE_CODE_MODE
*PxeBcMode
,
1232 EFI_UDP4_SESSION_DATA
*Session
1236 EFI_IPv4_ADDRESS Ip4Address
;
1237 EFI_IPv4_ADDRESS DestIp4Address
;
1239 if (PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1243 CopyMem (&DestIp4Address
, &Session
->DestinationAddress
, sizeof (DestIp4Address
));
1244 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) &&
1245 IP4_IS_MULTICAST (EFI_NTOHL (DestIp4Address
))
1250 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) &&
1251 IP4_IS_LOCAL_BROADCAST (EFI_NTOHL (DestIp4Address
))
1256 CopyMem (&Ip4Address
, &PxeBcMode
->StationIp
.v4
, sizeof (Ip4Address
));
1257 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) &&
1258 EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)
1263 for (Index
= 0; Index
< PxeBcMode
->IpFilter
.IpCnt
; ++Index
) {
1264 CopyMem (&Ip4Address
, &PxeBcMode
->IpFilter
.IpList
[Index
].v4
, sizeof (Ip4Address
));
1265 if (EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)) {
1274 GC_NOTO: Add function description
1276 @param This GC_NOTO: add argument
1278 @param OpFlags GC_NOTO: add argument
1280 @param DestIp GC_NOTO: add argument
1282 @param DestPort GC_NOTO: add argument
1284 @param SrcIp GC_NOTO: add argument
1286 @param SrcPort GC_NOTO: add argument
1288 @param HeaderSize GC_NOTO: add argument
1290 @param HeaderPtr GC_NOTO: add argument
1292 @param BufferSize GC_NOTO: add argument
1294 @param BufferPtr GC_NOTO: add argument
1297 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1299 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1301 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1303 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1305 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1307 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1314 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1316 IN OUT EFI_IP_ADDRESS
*DestIp
, OPTIONAL
1317 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
, OPTIONAL
1318 IN OUT EFI_IP_ADDRESS
*SrcIp
, OPTIONAL
1319 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort
, OPTIONAL
1320 IN UINTN
*HeaderSize
, OPTIONAL
1321 IN VOID
*HeaderPtr
, OPTIONAL
1322 IN OUT UINTN
*BufferSize
,
1326 PXEBC_PRIVATE_DATA
*Private
;
1327 EFI_PXE_BASE_CODE_MODE
*Mode
;
1328 EFI_UDP4_PROTOCOL
*Udp4
;
1329 EFI_UDP4_COMPLETION_TOKEN Token
;
1330 EFI_UDP4_RECEIVE_DATA
*RxData
;
1331 EFI_UDP4_SESSION_DATA
*Session
;
1337 if (This
== NULL
|| DestIp
== NULL
|| DestPort
== NULL
) {
1338 return EFI_INVALID_PARAMETER
;
1341 if ((!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (DestPort
== NULL
)) ||
1342 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (SrcIp
== NULL
)) ||
1343 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && (SrcPort
== NULL
))) {
1344 return EFI_INVALID_PARAMETER
;
1347 if (((HeaderSize
!= NULL
) && (*HeaderSize
== 0)) || ((HeaderPtr
== NULL
) && (*HeaderSize
!= 0))) {
1348 return EFI_INVALID_PARAMETER
;
1351 if ((BufferSize
== NULL
) || ((BufferPtr
== NULL
) && (*BufferSize
!= 0))) {
1352 return EFI_INVALID_PARAMETER
;
1355 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1356 Mode
= Private
->PxeBc
.Mode
;
1357 Udp4
= Private
->Udp4
;
1359 if (!Mode
->Started
) {
1360 return EFI_NOT_STARTED
;
1363 Mode
->IcmpErrorReceived
= FALSE
;
1365 Status
= gBS
->CreateEvent (
1372 if (EFI_ERROR (Status
)) {
1373 return EFI_OUT_OF_RESOURCES
;
1377 Status
= Udp4
->Receive (Udp4
, &Token
);
1378 if (EFI_ERROR (Status
)) {
1379 if (Status
== EFI_ICMP_ERROR
) {
1380 Mode
->IcmpErrorReceived
= TRUE
;
1388 Status
= EFI_TIMEOUT
;
1392 // check whether this packet matches the filters
1394 if (EFI_ERROR (Token
.Status
)){
1398 RxData
= Token
.Packet
.RxData
;
1399 Session
= &RxData
->UdpSession
;
1403 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
) {
1405 // Check UDP package by IP filter settings
1407 if (CheckIpByFilter (Mode
, Session
)) {
1414 // Match the destination ip of the received udp dgram
1416 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
) {
1419 if (DestIp
!= NULL
) {
1420 CopyMem (DestIp
, &Session
->DestinationAddress
, sizeof (EFI_IPv4_ADDRESS
));
1423 if (DestIp
!= NULL
) {
1424 if (EFI_IP4_EQUAL (DestIp
, &Session
->DestinationAddress
)) {
1428 if (EFI_IP4_EQUAL (&Private
->StationIp
, &Session
->DestinationAddress
)) {
1437 // Match the destination port of the received udp dgram
1439 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) {
1441 if (DestPort
!= NULL
) {
1442 *DestPort
= Session
->DestinationPort
;
1446 if (*DestPort
!= Session
->DestinationPort
) {
1454 // Match the source ip of the received udp dgram
1456 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) {
1458 if (SrcIp
!= NULL
) {
1459 CopyMem (SrcIp
, &Session
->SourceAddress
, sizeof (EFI_IPv4_ADDRESS
));
1463 if (!EFI_IP4_EQUAL (SrcIp
, &Session
->SourceAddress
)) {
1471 // Match the source port of the received udp dgram
1473 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
1475 if (SrcPort
!= NULL
) {
1476 *SrcPort
= Session
->SourcePort
;
1480 if (*SrcPort
!= Session
->SourcePort
) {
1490 if (HeaderSize
!= NULL
) {
1491 CopyLen
= MIN (*HeaderSize
, RxData
->DataLength
);
1492 CopyMem (HeaderPtr
, RxData
->FragmentTable
[0].FragmentBuffer
, CopyLen
);
1493 *HeaderSize
= CopyLen
;
1496 if (RxData
->DataLength
- CopyLen
> *BufferSize
) {
1498 Status
= EFI_BUFFER_TOO_SMALL
;
1501 *BufferSize
= RxData
->DataLength
- CopyLen
;
1502 CopyMem (BufferPtr
, (UINT8
*) RxData
->FragmentTable
[0].FragmentBuffer
+ CopyLen
, *BufferSize
);
1506 Status
= EFI_TIMEOUT
;
1510 // Recycle the RxData
1512 gBS
->SignalEvent (RxData
->RecycleSignal
);
1517 Udp4
->Cancel (Udp4
, &Token
);
1519 gBS
->CloseEvent (Token
.Event
);
1526 GC_NOTO: Add function description
1528 @param This GC_NOTO: add argument
1530 @param NewFilter GC_NOTO: add argument
1533 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1539 EfiPxeBcSetIpFilter (
1540 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1541 IN EFI_PXE_BASE_CODE_IP_FILTER
*NewFilter
1545 PXEBC_PRIVATE_DATA
*Private
;
1546 EFI_PXE_BASE_CODE_MODE
*Mode
;
1548 BOOLEAN PromiscuousNeed
;
1551 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL.\n"));
1552 return EFI_INVALID_PARAMETER
;
1555 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1556 Mode
= Private
->PxeBc
.Mode
;
1558 if (Private
== NULL
) {
1559 DEBUG ((EFI_D_ERROR
, "PXEBC_PRIVATE_DATA poiner == NULL.\n"));
1560 return EFI_INVALID_PARAMETER
;
1563 if (NewFilter
== NULL
) {
1564 DEBUG ((EFI_D_ERROR
, "IP Filter *NewFilter == NULL.\n"));
1565 return EFI_INVALID_PARAMETER
;
1568 if (!Mode
->Started
) {
1569 DEBUG ((EFI_D_ERROR
, "BC was not started.\n"));
1570 return EFI_NOT_STARTED
;
1573 PromiscuousNeed
= FALSE
;
1574 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1575 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter
->IpList
[Index
].v4
))) {
1577 // The IP is a broadcast address.
1579 DEBUG ((EFI_D_ERROR
, "There is broadcast address in NewFilter.\n"));
1580 return EFI_INVALID_PARAMETER
;
1582 if (Ip4IsUnicast (EFI_IP4 (NewFilter
->IpList
[Index
].v4
), 0) &&
1583 (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
)
1586 // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,
1587 // promiscuous mode is needed.
1589 PromiscuousNeed
= TRUE
;
1594 // Clear the UDP instance configuration, all joined groups will be left
1595 // during the operation.
1597 Private
->Udp4
->Configure (Private
->Udp4
, NULL
);
1598 Private
->Udp4CfgData
.AcceptPromiscuous
= FALSE
;
1599 Private
->Udp4CfgData
.AcceptBroadcast
= FALSE
;
1601 if (PromiscuousNeed
||
1602 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
||
1603 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
1606 // Configure the udp4 filter to receive all packages
1608 Private
->Udp4CfgData
.AcceptPromiscuous
= TRUE
;
1611 // Configure the UDP instance with the new configuration.
1613 Status
= Private
->Udp4
->Configure (Private
->Udp4
, &Private
->Udp4CfgData
);
1614 if (EFI_ERROR (Status
)) {
1620 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) {
1622 // Configure the udp4 filter to receive all broadcast packages
1624 Private
->Udp4CfgData
.AcceptBroadcast
= TRUE
;
1628 // Configure the UDP instance with the new configuration.
1630 Status
= Private
->Udp4
->Configure (Private
->Udp4
, &Private
->Udp4CfgData
);
1631 if (EFI_ERROR (Status
)) {
1635 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1637 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1638 if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter
->IpList
[Index
].v4
))) {
1640 // Join the mutilcast group
1642 Status
= Private
->Udp4
->Groups (Private
->Udp4
, TRUE
, &NewFilter
->IpList
[Index
].v4
);
1643 if (EFI_ERROR (Status
)) {
1653 // Save the new filter.
1655 CopyMem (&Mode
->IpFilter
, NewFilter
, sizeof (Mode
->IpFilter
));
1662 GC_NOTO: Add function description
1664 @param This GC_NOTO: add argument
1666 @param IpAddr GC_NOTO: add argument
1668 @param MacAddr GC_NOTO: add argument
1671 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1678 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1679 IN EFI_IP_ADDRESS
* IpAddr
,
1680 IN EFI_MAC_ADDRESS
* MacAddr OPTIONAL
1683 PXEBC_PRIVATE_DATA
*Private
;
1684 EFI_PXE_BASE_CODE_MODE
*Mode
;
1686 EFI_MAC_ADDRESS TempMacAddr
;
1688 if (This
== NULL
|| IpAddr
== NULL
) {
1689 return EFI_INVALID_PARAMETER
;
1692 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1693 Mode
= Private
->PxeBc
.Mode
;
1695 if (!Mode
->Started
) {
1696 return EFI_NOT_STARTED
;
1699 if (!Private
->AddressIsOk
|| Mode
->UsingIpv6
) {
1701 // We can't resolve the IP address if we don't have a local address now.
1702 // Don't have ARP for IPv6.
1704 return EFI_INVALID_PARAMETER
;
1707 Mode
->IcmpErrorReceived
= FALSE
;
1709 if (!Mode
->AutoArp
) {
1711 // If AutoArp is set false, check arp cache
1713 UpdateArpCache (This
);
1714 if (!FindInArpCache (Mode
, &IpAddr
->v4
, &TempMacAddr
)) {
1715 return EFI_DEVICE_ERROR
;
1718 Status
= Private
->Arp
->Request (Private
->Arp
, &IpAddr
->v4
, NULL
, &TempMacAddr
);
1719 if (EFI_ERROR (Status
)) {
1720 if (Status
== EFI_ICMP_ERROR
) {
1721 Mode
->IcmpErrorReceived
= TRUE
;
1727 if (MacAddr
!= NULL
) {
1728 CopyMem (MacAddr
, &TempMacAddr
, sizeof (EFI_MAC_ADDRESS
));
1737 GC_NOTO: Add function description
1739 @param This GC_NOTO: add argument
1741 @param NewAutoArp GC_NOTO: add argument
1743 @param NewSendGUID GC_NOTO: add argument
1745 @param NewTTL GC_NOTO: add argument
1747 @param NewToS GC_NOTO: add argument
1749 @param NewMakeCallback GC_NOTO: add argument
1752 @return GC_NOTO: add return values
1757 EfiPxeBcSetParameters (
1758 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1759 IN BOOLEAN
*NewAutoArp
, OPTIONAL
1760 IN BOOLEAN
*NewSendGUID
, OPTIONAL
1761 IN UINT8
*NewTTL
, OPTIONAL
1762 IN UINT8
*NewToS
, OPTIONAL
1763 IN BOOLEAN
*NewMakeCallback
// OPTIONAL
1766 PXEBC_PRIVATE_DATA
*Private
;
1767 EFI_PXE_BASE_CODE_MODE
*Mode
;
1770 Status
= EFI_SUCCESS
;
1773 Status
= EFI_INVALID_PARAMETER
;
1777 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1778 Mode
= Private
->PxeBc
.Mode
;
1780 if (NewSendGUID
!= NULL
&& *NewSendGUID
== TRUE
) {
1782 // FixMe, cann't locate SendGuid
1786 if (NewMakeCallback
!= NULL
&& *NewMakeCallback
== TRUE
) {
1788 Status
= gBS
->HandleProtocol (
1789 Private
->Controller
,
1790 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1791 (VOID
**) &Private
->PxeBcCallback
1793 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1795 Status
= EFI_INVALID_PARAMETER
;
1800 if (!Mode
->Started
) {
1801 Status
= EFI_NOT_STARTED
;
1805 if (NewMakeCallback
!= NULL
) {
1807 if (*NewMakeCallback
) {
1809 // Update the Callback protocol.
1811 Status
= gBS
->HandleProtocol (
1812 Private
->Controller
,
1813 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1814 (VOID
**) &Private
->PxeBcCallback
1817 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1818 Status
= EFI_INVALID_PARAMETER
;
1822 Private
->PxeBcCallback
= NULL
;
1825 Mode
->MakeCallbacks
= *NewMakeCallback
;
1828 if (NewAutoArp
!= NULL
) {
1829 Mode
->AutoArp
= *NewAutoArp
;
1832 if (NewSendGUID
!= NULL
) {
1833 Mode
->SendGUID
= *NewSendGUID
;
1836 if (NewTTL
!= NULL
) {
1837 Mode
->TTL
= *NewTTL
;
1840 if (NewToS
!= NULL
) {
1841 Mode
->ToS
= *NewToS
;
1850 GC_NOTO: Add function description
1852 @param This GC_NOTO: add argument
1854 @param NewStationIp GC_NOTO: add argument
1856 @param NewSubnetMask GC_NOTO: add argument
1859 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1861 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1863 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1865 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1867 @retval EFI_SUCCESS GC_NOTO: Add description for
1873 EfiPxeBcSetStationIP (
1874 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1875 IN EFI_IP_ADDRESS
* NewStationIp
, OPTIONAL
1876 IN EFI_IP_ADDRESS
* NewSubnetMask OPTIONAL
1879 PXEBC_PRIVATE_DATA
*Private
;
1880 EFI_PXE_BASE_CODE_MODE
*Mode
;
1881 EFI_ARP_CONFIG_DATA ArpConfigData
;
1884 return EFI_INVALID_PARAMETER
;
1887 if (NewStationIp
!= NULL
&& !Ip4IsUnicast (NTOHL (NewStationIp
->Addr
[0]), 0)) {
1888 return EFI_INVALID_PARAMETER
;
1891 if (NewSubnetMask
!= NULL
&& !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask
->Addr
[0]))) {
1892 return EFI_INVALID_PARAMETER
;
1895 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1896 Mode
= Private
->PxeBc
.Mode
;
1898 if (!Mode
->Started
) {
1899 return EFI_NOT_STARTED
;
1902 if (NewStationIp
!= NULL
) {
1903 Mode
->StationIp
= *NewStationIp
;
1904 Private
->StationIp
= *NewStationIp
;
1907 if (NewSubnetMask
!= NULL
) {
1908 Mode
->SubnetMask
= *NewSubnetMask
;
1909 Private
->SubnetMask
= *NewSubnetMask
;
1912 Private
->AddressIsOk
= TRUE
;
1914 if (!Mode
->UsingIpv6
) {
1916 // If in IPv4 mode, configure the corresponding ARP with this new
1917 // station IP address.
1919 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
1921 ArpConfigData
.SwAddressType
= 0x0800;
1922 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
1923 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
1925 Private
->Arp
->Configure (Private
->Arp
, NULL
);
1926 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
1929 // Update the route table.
1931 Mode
->RouteTableEntries
= 1;
1932 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
1933 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
1934 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
1942 GC_NOTO: Add function description
1944 @param This GC_NOTO: add argument
1946 @param NewDhcpDiscoverValid GC_NOTO: add argument
1948 @param NewDhcpAckReceived GC_NOTO: add argument
1950 @param NewProxyOfferReceived GC_NOTO: add argument
1952 @param NewPxeDiscoverValid GC_NOTO: add argument
1954 @param NewPxeReplyReceived GC_NOTO: add argument
1956 @param NewPxeBisReplyReceived GC_NOTO: add argument
1958 @param NewDhcpDiscover GC_NOTO: add argument
1960 @param NewDhcpAck GC_NOTO: add argument
1962 @param NewProxyOffer GC_NOTO: add argument
1964 @param NewPxeDiscover GC_NOTO: add argument
1966 @param NewPxeReply GC_NOTO: add argument
1968 @param NewPxeBisReply GC_NOTO: add argument
1971 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1973 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1975 @retval EFI_SUCCESS GC_NOTO: Add description for
1981 EfiPxeBcSetPackets (
1982 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1983 IN BOOLEAN
* NewDhcpDiscoverValid
, OPTIONAL
1984 IN BOOLEAN
* NewDhcpAckReceived
, OPTIONAL
1985 IN BOOLEAN
* NewProxyOfferReceived
, OPTIONAL
1986 IN BOOLEAN
* NewPxeDiscoverValid
, OPTIONAL
1987 IN BOOLEAN
* NewPxeReplyReceived
, OPTIONAL
1988 IN BOOLEAN
* NewPxeBisReplyReceived
, OPTIONAL
1989 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
1990 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
1991 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
1992 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
1993 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
1994 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
1997 PXEBC_PRIVATE_DATA
*Private
;
1998 EFI_PXE_BASE_CODE_MODE
*Mode
;
2001 return EFI_INVALID_PARAMETER
;
2004 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
2005 Mode
= Private
->PxeBc
.Mode
;
2007 if (!Mode
->Started
) {
2008 return EFI_NOT_STARTED
;
2011 Private
->FileSize
= 0;
2013 if (NewDhcpDiscoverValid
!= NULL
) {
2014 Mode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
2017 if (NewDhcpAckReceived
!= NULL
) {
2018 Mode
->DhcpAckReceived
= *NewDhcpAckReceived
;
2021 if (NewProxyOfferReceived
!= NULL
) {
2022 Mode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
2025 if (NewPxeDiscoverValid
!= NULL
) {
2026 Mode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
2029 if (NewPxeReplyReceived
!= NULL
) {
2030 Mode
->PxeReplyReceived
= *NewPxeReplyReceived
;
2033 if (NewPxeBisReplyReceived
!= NULL
) {
2034 Mode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
2037 if (NewDhcpDiscover
!= NULL
) {
2038 CopyMem (&Mode
->DhcpDiscover
, NewDhcpDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2041 if (NewDhcpAck
!= NULL
) {
2042 CopyMem (&Mode
->DhcpAck
, NewDhcpAck
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2045 if (NewProxyOffer
!= NULL
) {
2046 CopyMem (&Mode
->ProxyOffer
, NewProxyOffer
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2049 if (NewPxeDiscover
!= NULL
) {
2050 CopyMem (&Mode
->PxeDiscover
, NewPxeDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2053 if (NewPxeReply
!= NULL
) {
2054 CopyMem (&Mode
->PxeReply
, NewPxeReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2057 if (NewPxeBisReply
!= NULL
) {
2058 CopyMem (&Mode
->PxeBisReply
, NewPxeBisReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2064 EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate
= {
2065 EFI_PXE_BASE_CODE_PROTOCOL_REVISION
,
2073 EfiPxeBcSetIpFilter
,
2075 EfiPxeBcSetParameters
,
2076 EfiPxeBcSetStationIP
,
2083 GC_NOTO: Add function description
2085 @param This GC_NOTO: add argument
2087 @param Function GC_NOTO: add argument
2089 @param Received GC_NOTO: add argument
2091 @param PacketLength GC_NOTO: add argument
2093 @param PacketPtr GC_NOTO: add argument
2096 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT GC_NOTO: Add description for
2098 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2100 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2102 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2104 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2108 EFI_PXE_BASE_CODE_CALLBACK_STATUS
2110 EfiPxeLoadFileCallback (
2111 IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL
* This
,
2112 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
2113 IN BOOLEAN Received
,
2114 IN UINT32 PacketLength
,
2115 IN EFI_PXE_BASE_CODE_PACKET
* PacketPtr OPTIONAL
2122 // Catch Ctrl-C or ESC to abort.
2124 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2126 if (!EFI_ERROR (Status
)) {
2128 if (Key
.ScanCode
== SCAN_ESC
|| Key
.UnicodeChar
== (0x1F & 'c')) {
2130 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT
;
2134 // No print if receive packet
2137 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2140 // Print only for three functions
2144 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP
:
2146 // Print only for open MTFTP packets, not every MTFTP packets
2148 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2149 if (PacketPtr
->Raw
[0x1C] != 0x00 || PacketPtr
->Raw
[0x1D] != 0x01) {
2150 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2155 case EFI_PXE_BASE_CODE_FUNCTION_DHCP
:
2156 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
:
2160 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2163 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2165 // Print '.' when transmit a packet
2171 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2174 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate
= {
2175 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION
,
2176 EfiPxeLoadFileCallback
2181 GC_NOTO: Add function description
2183 @param Private GC_NOTO: add argument
2185 @param BufferSize GC_NOTO: add argument
2187 @param Buffer GC_NOTO: add argument
2190 @return GC_NOTO: add return values
2195 IN PXEBC_PRIVATE_DATA
*Private
,
2196 IN OUT UINT64
*BufferSize
,
2200 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2201 EFI_PXE_BASE_CODE_MODE
*Mode
;
2207 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
2210 PxeBc
= &Private
->PxeBc
;
2212 Type
= EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
;
2213 Layer
= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
;
2218 Status
= PxeBc
->Dhcp (PxeBc
, TRUE
);
2219 if (EFI_ERROR (Status
)) {
2224 // Select a boot server
2226 Status
= PxeBcSelectBootPrompt (Private
);
2228 if (Status
== EFI_SUCCESS
) {
2229 Status
= PxeBcSelectBootMenu (Private
, &Type
, TRUE
);
2230 } else if (Status
== EFI_TIMEOUT
) {
2231 Status
= PxeBcSelectBootMenu (Private
, &Type
, FALSE
);
2234 if (!EFI_ERROR (Status
)) {
2236 if (Type
== EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
) {
2238 // Local boot(PXE bootstrap server) need abort
2243 UseBis
= (BOOLEAN
) (Mode
->BisSupported
&& Mode
->BisDetected
);
2244 Status
= PxeBc
->Discover (PxeBc
, Type
, &Layer
, UseBis
, NULL
);
2245 if (EFI_ERROR (Status
)) {
2254 // Get bootfile name and (m)tftp server ip addresss
2256 if (Mode
->PxeReplyReceived
) {
2257 Packet
= &Private
->PxeReply
;
2258 } else if (Mode
->ProxyOfferReceived
) {
2259 Packet
= &Private
->ProxyOffer
;
2261 Packet
= &Private
->Dhcp4Ack
;
2264 CopyMem (&Private
->ServerIp
, &Packet
->Packet
.Offer
.Dhcp4
.Header
.ServerAddr
, sizeof (EFI_IPv4_ADDRESS
));
2265 if (Private
->ServerIp
.Addr
[0] == 0) {
2267 // next server ip address is zero, use option 54 instead
2271 Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_SERVER_ID
]->Data
,
2272 sizeof (EFI_IPv4_ADDRESS
)
2276 ASSERT (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
);
2281 Private
->BootFileName
= (CHAR8
*) (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
]->Data
);
2283 if (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
] != NULL
) {
2285 // Already have the bootfile length option, compute the file size
2287 CopyMem (&Value
, Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
]->Data
, sizeof (Value
));
2288 Value
= NTOHS (Value
);
2289 *BufferSize
= 512 * Value
;
2290 Status
= EFI_BUFFER_TOO_SMALL
;
2293 // Get the bootfile size from tftp
2295 Status
= PxeBc
->Mtftp (
2297 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
,
2303 (UINT8
*) Private
->BootFileName
,
2309 Private
->FileSize
= (UINTN
) *BufferSize
;
2316 GC_NOTO: Add function description
2318 @param This GC_NOTO: add argument
2320 @param FilePath GC_NOTO: add argument
2322 @param BootPolicy GC_NOTO: add argument
2324 @param BufferSize GC_NOTO: add argument
2326 @param Buffer GC_NOTO: add argument
2329 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
2331 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
2338 IN EFI_LOAD_FILE_PROTOCOL
* This
,
2339 IN EFI_DEVICE_PATH_PROTOCOL
* FilePath
,
2340 IN BOOLEAN BootPolicy
,
2341 IN OUT UINTN
*BufferSize
,
2342 IN VOID
*Buffer OPTIONAL
2345 PXEBC_PRIVATE_DATA
*Private
;
2346 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2347 BOOLEAN NewMakeCallback
;
2352 Private
= PXEBC_PRIVATE_DATA_FROM_LOADFILE (This
);
2353 PxeBc
= &Private
->PxeBc
;
2354 NewMakeCallback
= FALSE
;
2356 Status
= EFI_DEVICE_ERROR
;
2358 if (This
== NULL
|| BufferSize
== NULL
) {
2360 return EFI_INVALID_PARAMETER
;
2364 // Only support BootPolicy
2367 return EFI_UNSUPPORTED
;
2370 Status
= PxeBc
->Start (PxeBc
, FALSE
);
2371 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
2375 Status
= gBS
->HandleProtocol (
2376 Private
->Controller
,
2377 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2378 (VOID
**) &Private
->PxeBcCallback
2380 if (Status
== EFI_UNSUPPORTED
) {
2382 CopyMem (&Private
->LoadFileCallback
, &mPxeBcCallBackTemplate
, sizeof (Private
->LoadFileCallback
));
2384 Status
= gBS
->InstallProtocolInterface (
2385 &Private
->Controller
,
2386 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2387 EFI_NATIVE_INTERFACE
,
2388 &Private
->LoadFileCallback
2391 NewMakeCallback
= (BOOLEAN
) (Status
== EFI_SUCCESS
);
2393 Status
= PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2394 if (EFI_ERROR (Status
)) {
2395 PxeBc
->Stop (PxeBc
);
2400 if (Private
->FileSize
== 0) {
2402 Status
= DiscoverBootFile (Private
, &TmpBufSize
, Buffer
);
2404 if (sizeof (UINTN
) < sizeof (UINT64
) && (TmpBufSize
> 0xFFFFFFFF)) {
2405 Status
= EFI_DEVICE_ERROR
;
2407 *BufferSize
= (UINTN
) TmpBufSize
;
2409 } else if (Buffer
== NULL
) {
2410 *BufferSize
= Private
->FileSize
;
2411 Status
= EFI_BUFFER_TOO_SMALL
;
2414 // Download the file.
2416 TmpBufSize
= (UINT64
) (*BufferSize
);
2417 Status
= PxeBc
->Mtftp (
2419 EFI_PXE_BASE_CODE_TFTP_READ_FILE
,
2425 (UINT8
*) Private
->BootFileName
,
2431 // If we added a callback protocol, now is the time to remove it.
2433 if (NewMakeCallback
) {
2435 NewMakeCallback
= FALSE
;
2437 PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2439 gBS
->UninstallProtocolInterface (
2440 Private
->Controller
,
2441 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2442 &Private
->LoadFileCallback
2446 // Check download status
2453 case EFI_BUFFER_TOO_SMALL
:
2454 if (Buffer
!= NULL
) {
2455 AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
2461 case EFI_DEVICE_ERROR
:
2462 AsciiPrint ("PXE-E07: Network device error.\n");
2465 case EFI_OUT_OF_RESOURCES
:
2466 AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
2470 AsciiPrint ("PXE-E12: Could not detect network connection.\n");
2473 case EFI_NO_RESPONSE
:
2474 AsciiPrint ("PXE-E16: No offer received.\n");
2478 AsciiPrint ("PXE-E18: Server response timeout.\n");
2482 AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
2485 case EFI_ICMP_ERROR
:
2486 AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
2489 case EFI_TFTP_ERROR
:
2490 AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
2494 AsciiPrint ("PXE-E99: Unexpected network error.\n");
2498 PxeBc
->Stop (PxeBc
);
2503 EFI_LOAD_FILE_PROTOCOL mLoadFileProtocolTemplate
= { EfiPxeLoadFile
};