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
->GotProxyOffer
= FALSE
;
517 Private
->NumOffers
= 0;
518 Private
->BootpIndex
= 0;
519 ZeroMem (Private
->ServerCount
, sizeof (Private
->ServerCount
));
520 ZeroMem (Private
->ProxyIndex
, sizeof (Private
->ProxyIndex
));
522 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
523 if (EFI_ERROR (Status
)) {
524 if (Status
== EFI_TIMEOUT
) {
526 // If no response is received or all received offers don't match
527 // the PXE boot requirements, EFI_TIMEOUT will be returned.
531 if (Status
== EFI_ICMP_ERROR
) {
532 Mode
->IcmpErrorReceived
= TRUE
;
535 // Other error status means the DHCP really fails.
540 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
541 if (EFI_ERROR (Status
)) {
545 ASSERT (Dhcp4Mode
.State
== Dhcp4Bound
);
547 CopyMem (&Private
->StationIp
, &Dhcp4Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
548 CopyMem (&Private
->SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
549 CopyMem (&Private
->GatewayIp
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
552 // Check the selected offer to see whether BINL is required, if no or BINL is
553 // finished, set the various Mode members.
555 Status
= PxeBcCheckSelectedOffer (Private
);
556 if (!EFI_ERROR (Status
)) {
561 if (EFI_ERROR (Status
)) {
563 Dhcp4
->Configure (Dhcp4
, NULL
);
566 // Remove the previously configured option list and callback function
568 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
569 Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
571 Private
->AddressIsOk
= TRUE
;
573 if (!Mode
->UsingIpv6
) {
575 // If in IPv4 mode, configure the corresponding ARP with this new
576 // station IP address.
578 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
580 ArpConfigData
.SwAddressType
= 0x0800;
581 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
582 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
584 Private
->Arp
->Configure (Private
->Arp
, NULL
);
585 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
588 // Updated the route table. Fill the first entry.
590 Mode
->RouteTableEntries
= 1;
591 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
592 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
593 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
596 // Create the default route entry if there is a default router.
598 if (Private
->GatewayIp
.Addr
[0] != 0) {
599 Mode
->RouteTableEntries
= 2;
600 Mode
->RouteTable
[1].IpAddr
.Addr
[0] = 0;
601 Mode
->RouteTable
[1].SubnetMask
.Addr
[0] = 0;
602 Mode
->RouteTable
[1].GwAddr
.Addr
[0] = Private
->GatewayIp
.Addr
[0];
612 GC_NOTO: Add function description
614 @param This GC_NOTO: add argument
616 @param Type GC_NOTO: add argument
618 @param Layer GC_NOTO: add argument
620 @param UseBis GC_NOTO: add argument
622 @param Info GC_NOTO: add argument
625 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
627 @retval EFI_NOT_STARTED GC_NOTO: Add description for
629 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
631 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
633 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
635 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
642 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
646 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*Info OPTIONAL
649 PXEBC_PRIVATE_DATA
*Private
;
650 EFI_PXE_BASE_CODE_MODE
*Mode
;
651 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
652 EFI_PXE_BASE_CODE_SRVLIST
*SrvList
;
653 EFI_PXE_BASE_CODE_SRVLIST DefaultSrvList
;
654 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
655 PXEBC_VENDOR_OPTION
*VendorOpt
;
658 PXEBC_BOOT_SVR_ENTRY
*BootSvrEntry
;
661 return EFI_INVALID_PARAMETER
;
664 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
665 Mode
= Private
->PxeBc
.Mode
;
668 Status
= EFI_DEVICE_ERROR
;
669 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
671 if (!Private
->AddressIsOk
) {
672 return EFI_INVALID_PARAMETER
;
675 if (!Mode
->Started
) {
676 return EFI_NOT_STARTED
;
679 Mode
->IcmpErrorReceived
= FALSE
;
682 // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
683 // use the previous setting;
684 // If info isn't offered,
685 // use the cached DhcpAck and ProxyOffer packets.
687 if (*Layer
!= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
) {
689 if (!Mode
->PxeDiscoverValid
|| !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
691 return EFI_INVALID_PARAMETER
;
694 DefaultInfo
.IpCnt
= 1;
695 DefaultInfo
.UseUCast
= TRUE
;
697 DefaultSrvList
.Type
= Type
;
698 DefaultSrvList
.AcceptAnyResponse
= FALSE
;
699 DefaultSrvList
.IpAddr
.Addr
[0] = Private
->ServerIp
.Addr
[0];
701 SrvList
= &DefaultSrvList
;
703 } else if (Info
== NULL
) {
705 // Create info by the cached packet before
707 Packet
= (Mode
->ProxyOfferReceived
) ? &Private
->ProxyOffer
: &Private
->Dhcp4Ack
;
708 VendorOpt
= &Packet
->PxeVendorOption
;
710 if (!Mode
->DhcpAckReceived
|| !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt
->BitMap
)) {
712 // Address is not acquired or no discovery options.
714 return EFI_INVALID_PARAMETER
;
717 DefaultInfo
.UseMCast
= (BOOLEAN
)!IS_DISABLE_MCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
718 DefaultInfo
.UseBCast
= (BOOLEAN
)!IS_DISABLE_BCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
719 DefaultInfo
.MustUseList
= (BOOLEAN
) IS_ENABLE_USE_SERVER_LIST (VendorOpt
->DiscoverCtrl
);
720 DefaultInfo
.UseUCast
= DefaultInfo
.MustUseList
;
722 if (DefaultInfo
.UseMCast
) {
724 // Get the multicast discover ip address from vendor option.
726 CopyMem (&DefaultInfo
.ServerMCastIp
.Addr
, &VendorOpt
->DiscoverMcastIp
, sizeof (EFI_IPv4_ADDRESS
));
729 DefaultInfo
.IpCnt
= 0;
731 if (DefaultInfo
.MustUseList
) {
732 BootSvrEntry
= VendorOpt
->BootSvr
;
733 Status
= EFI_INVALID_PARAMETER
;
735 while (((UINT8
) (BootSvrEntry
- VendorOpt
->BootSvr
)) < VendorOpt
->BootSvrLen
) {
737 if (BootSvrEntry
->Type
== HTONS (Type
)) {
738 Status
= EFI_SUCCESS
;
742 BootSvrEntry
= GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry
);
745 if (EFI_ERROR (Status
)) {
749 DefaultInfo
.IpCnt
= BootSvrEntry
->IpCnt
;
755 SrvList
= Info
->SrvList
;
757 if (!SrvList
[0].AcceptAnyResponse
) {
759 for (Index
= 1; Index
< Info
->IpCnt
; Index
++) {
760 if (SrvList
[Index
].AcceptAnyResponse
) {
765 if (Index
!= Info
->IpCnt
) {
766 return EFI_INVALID_PARAMETER
;
771 if ((!Info
->UseUCast
&& !Info
->UseBCast
&& !Info
->UseMCast
) || (Info
->MustUseList
&& Info
->IpCnt
== 0)) {
773 return EFI_INVALID_PARAMETER
;
776 // Execute discover by UniCast/BroadCast/MultiCast
778 if (Info
->UseUCast
) {
780 for (Index
= 0; Index
< Info
->IpCnt
; Index
++) {
782 if (BootSvrEntry
== NULL
) {
783 Private
->ServerIp
.Addr
[0] = SrvList
[Index
].IpAddr
.Addr
[0];
785 CopyMem (&Private
->ServerIp
, &BootSvrEntry
->IpAddr
[Index
], sizeof (EFI_IPv4_ADDRESS
));
788 Status
= PxeBcDiscvBootService (
793 &SrvList
[Index
].IpAddr
,
797 &Private
->PxeReply
.Packet
.Ack
801 } else if (Info
->UseMCast
) {
803 Status
= PxeBcDiscvBootService (
808 &Info
->ServerMCastIp
,
812 &Private
->PxeReply
.Packet
.Ack
815 } else if (Info
->UseBCast
) {
817 Status
= PxeBcDiscvBootService (
826 &Private
->PxeReply
.Packet
.Ack
830 if (EFI_ERROR (Status
) || !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
831 if (Status
== EFI_ICMP_ERROR
) {
832 Mode
->IcmpErrorReceived
= TRUE
;
834 Status
= EFI_DEVICE_ERROR
;
837 PxeBcParseCachedDhcpPacket (&Private
->PxeReply
);
840 if (Mode
->PxeBisReplyReceived
) {
841 CopyMem (&Private
->ServerIp
, &Mode
->PxeReply
.Dhcpv4
.BootpSiAddr
, sizeof (EFI_IPv4_ADDRESS
));
849 GC_NOTO: Add function description
851 @param This GC_NOTO: add argument
853 @param Operation GC_NOTO: add argument
855 @param BufferPtr GC_NOTO: add argument
857 @param Overwrite GC_NOTO: add argument
859 @param BufferSize GC_NOTO: add argument
861 @param BlockSize GC_NOTO: add argument
863 @param ServerIp GC_NOTO: add argument
865 @param Filename GC_NOTO: add argument
867 @param Info GC_NOTO: add argument
869 @param DontUseBuffer GC_NOTO: add argument
872 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
879 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
880 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
881 IN OUT VOID
*BufferPtr
,
882 IN BOOLEAN Overwrite
,
883 IN OUT UINT64
*BufferSize
,
884 IN UINTN
*BlockSize OPTIONAL
,
885 IN EFI_IP_ADDRESS
*ServerIp
,
887 IN EFI_PXE_BASE_CODE_MTFTP_INFO
*Info OPTIONAL
,
888 IN BOOLEAN DontUseBuffer
891 PXEBC_PRIVATE_DATA
*Private
;
892 EFI_MTFTP4_CONFIG_DATA Mtftp4Config
;
894 EFI_PXE_BASE_CODE_MODE
*Mode
;
895 EFI_MAC_ADDRESS TempMacAddr
;
897 if ((This
== NULL
) ||
898 (Filename
== NULL
) ||
899 (BufferSize
== NULL
) ||
900 ((ServerIp
== NULL
) || !Ip4IsUnicast (NTOHL (ServerIp
->Addr
[0]), 0)) ||
901 ((BufferPtr
== NULL
) && DontUseBuffer
) ||
902 ((BlockSize
!= NULL
) && (*BlockSize
< 512))) {
904 return EFI_INVALID_PARAMETER
;
907 Status
= EFI_DEVICE_ERROR
;
908 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
909 Mode
= &Private
->Mode
;
911 if (!Mode
->AutoArp
) {
913 // If AutoArp is set false, check arp cache
915 UpdateArpCache (This
);
916 if (!FindInArpCache (Mode
, &ServerIp
->v4
, &TempMacAddr
)) {
917 return EFI_DEVICE_ERROR
;
921 Mode
->TftpErrorReceived
= FALSE
;
922 Mode
->IcmpErrorReceived
= FALSE
;
924 Mtftp4Config
.UseDefaultSetting
= FALSE
;
925 Mtftp4Config
.TimeoutValue
= PXEBC_MTFTP_TIMEOUT
;
926 Mtftp4Config
.TryCount
= PXEBC_MTFTP_RETRIES
;
928 CopyMem (&Mtftp4Config
.StationIp
, &Private
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
929 CopyMem (&Mtftp4Config
.SubnetMask
, &Private
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
930 CopyMem (&Mtftp4Config
.GatewayIp
, &Private
->GatewayIp
, sizeof (EFI_IPv4_ADDRESS
));
931 CopyMem (&Mtftp4Config
.ServerIp
, ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
935 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
:
937 Status
= PxeBcTftpGetFileSize (
945 if (!EFI_ERROR (Status
)) {
946 Status
= EFI_BUFFER_TOO_SMALL
;
951 case EFI_PXE_BASE_CODE_TFTP_READ_FILE
:
953 Status
= PxeBcTftpReadFile (
965 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
:
967 Status
= PxeBcTftpWriteFile (
979 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY
:
981 Status
= PxeBcTftpReadDirectory (
993 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE
:
994 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE
:
995 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY
:
996 Status
= EFI_UNSUPPORTED
;
1001 Status
= EFI_INVALID_PARAMETER
;
1005 if (Status
== EFI_ICMP_ERROR
) {
1006 Mode
->IcmpErrorReceived
= TRUE
;
1014 GC_NOTO: Add function description
1016 @param This GC_NOTO: add argument
1018 @param OpFlags GC_NOTO: add argument
1020 @param DestIp GC_NOTO: add argument
1022 @param DestPort GC_NOTO: add argument
1024 @param GatewayIp GC_NOTO: add argument
1026 @param SrcIp GC_NOTO: add argument
1028 @param SrcPort GC_NOTO: add argument
1030 @param HeaderSize GC_NOTO: add argument
1032 @param HeaderPtr GC_NOTO: add argument
1034 @param BufferSize GC_NOTO: add argument
1036 @param BufferPtr GC_NOTO: add argument
1039 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1041 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1043 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1045 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1047 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1054 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1056 IN EFI_IP_ADDRESS
*DestIp
,
1057 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
,
1058 IN EFI_IP_ADDRESS
*GatewayIp OPTIONAL
,
1059 IN EFI_IP_ADDRESS
*SrcIp OPTIONAL
,
1060 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort OPTIONAL
,
1061 IN UINTN
*HeaderSize OPTIONAL
,
1062 IN VOID
*HeaderPtr OPTIONAL
,
1063 IN UINTN
*BufferSize
,
1067 PXEBC_PRIVATE_DATA
*Private
;
1068 EFI_UDP4_PROTOCOL
*Udp4
;
1069 EFI_UDP4_COMPLETION_TOKEN Token
;
1070 EFI_UDP4_TRANSMIT_DATA
*Udp4TxData
;
1073 EFI_UDP4_SESSION_DATA Udp4Session
;
1076 EFI_PXE_BASE_CODE_MODE
*Mode
;
1077 EFI_MAC_ADDRESS TempMacAddr
;
1081 if ((This
== NULL
) || (DestIp
== NULL
) || (DestPort
== NULL
)) {
1082 return EFI_INVALID_PARAMETER
;
1085 if ((GatewayIp
!= NULL
) && !Ip4IsUnicast (NTOHL (GatewayIp
->Addr
[0]), 0)) {
1087 // Gateway is provided but it's not a unicast IP address.
1089 return EFI_INVALID_PARAMETER
;
1092 if ((HeaderSize
!= NULL
) && ((*HeaderSize
== 0) || (HeaderPtr
== NULL
))) {
1094 // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
1097 return EFI_INVALID_PARAMETER
;
1100 if ((BufferSize
== NULL
) || ((*BufferSize
!= 0) && (BufferPtr
== NULL
))) {
1101 return EFI_INVALID_PARAMETER
;
1104 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1105 Udp4
= Private
->Udp4Write
;
1106 Mode
= &Private
->Mode
;
1107 if (!Mode
->Started
) {
1108 return EFI_NOT_STARTED
;
1111 if (!Private
->AddressIsOk
&& (SrcIp
== NULL
)) {
1112 return EFI_INVALID_PARAMETER
;
1115 if (!Mode
->AutoArp
) {
1117 // If AutoArp is set false, check arp cache
1119 UpdateArpCache (This
);
1120 if (!FindInArpCache (Mode
, &DestIp
->v4
, &TempMacAddr
)) {
1121 return EFI_DEVICE_ERROR
;
1125 Mode
->IcmpErrorReceived
= FALSE
;
1127 if ((Private
->CurrentUdpSrcPort
== 0) ||
1128 ((SrcPort
!= NULL
) && (*SrcPort
!= Private
->CurrentUdpSrcPort
))) {
1130 // Port is changed, (re)configure the Udp4Write instance
1132 if (SrcPort
!= NULL
) {
1133 Private
->CurrentUdpSrcPort
= *SrcPort
;
1136 Status
= PxeBcConfigureUdpWriteInstance (
1138 &Private
->StationIp
.v4
,
1139 &Private
->SubnetMask
.v4
,
1140 &Private
->GatewayIp
.v4
,
1141 &Private
->CurrentUdpSrcPort
1143 if (EFI_ERROR (Status
)) {
1144 Private
->CurrentUdpSrcPort
= 0;
1145 return EFI_INVALID_PARAMETER
;
1149 ZeroMem (&Token
, sizeof (EFI_UDP4_COMPLETION_TOKEN
));
1150 ZeroMem (&Udp4Session
, sizeof (EFI_UDP4_SESSION_DATA
));
1152 CopyMem (&Udp4Session
.DestinationAddress
, DestIp
, sizeof (EFI_IPv4_ADDRESS
));
1153 Udp4Session
.DestinationPort
= *DestPort
;
1154 if (SrcIp
!= NULL
) {
1155 CopyMem (&Udp4Session
.SourceAddress
, SrcIp
, sizeof (EFI_IPv4_ADDRESS
));
1157 if (SrcPort
!= NULL
) {
1158 Udp4Session
.SourcePort
= *SrcPort
;
1161 FragCount
= (HeaderSize
!= NULL
) ? 2 : 1;
1162 Udp4TxData
= (EFI_UDP4_TRANSMIT_DATA
*) AllocateZeroPool (sizeof (EFI_UDP4_TRANSMIT_DATA
) + (FragCount
- 1) * sizeof (EFI_UDP4_FRAGMENT_DATA
));
1163 if (Udp4TxData
== NULL
) {
1164 return EFI_OUT_OF_RESOURCES
;
1167 Udp4TxData
->FragmentCount
= FragCount
;
1168 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentLength
= (UINT32
) *BufferSize
;
1169 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentBuffer
= BufferPtr
;
1170 DataLength
= (UINT32
) *BufferSize
;
1172 if (FragCount
== 2) {
1174 Udp4TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) *HeaderSize
;
1175 Udp4TxData
->FragmentTable
[0].FragmentBuffer
= HeaderPtr
;
1176 DataLength
+= (UINT32
) *HeaderSize
;
1179 if (GatewayIp
!= NULL
) {
1180 Udp4TxData
->GatewayAddress
= (EFI_IPv4_ADDRESS
*) GatewayIp
;
1182 Udp4TxData
->UdpSessionData
= &Udp4Session
;
1183 Udp4TxData
->DataLength
= DataLength
;
1184 Token
.Packet
.TxData
= Udp4TxData
;
1186 Status
= gBS
->CreateEvent (
1193 if (EFI_ERROR (Status
)) {
1197 Status
= Udp4
->Transmit (Udp4
, &Token
);
1198 if (EFI_ERROR (Status
)) {
1199 if (Status
== EFI_ICMP_ERROR
) {
1200 Mode
->IcmpErrorReceived
= TRUE
;
1210 Status
= Token
.Status
;
1214 if (Token
.Event
!= NULL
) {
1215 gBS
->CloseEvent (Token
.Event
);
1218 gBS
->FreePool (Udp4TxData
);
1224 Validate IP packages by IP filter settings
1226 @param PxeBcMode Pointer to EFI_PXEBC_MODE
1228 @param Session Received UDP session
1230 @retval TRUE The UDP package matches IP filters
1232 @retval FLASE The UDP package doesn't matches IP filters
1238 EFI_PXE_BASE_CODE_MODE
*PxeBcMode
,
1239 EFI_UDP4_SESSION_DATA
*Session
1243 EFI_IPv4_ADDRESS Ip4Address
;
1244 EFI_IPv4_ADDRESS DestIp4Address
;
1246 if (PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1250 CopyMem (&DestIp4Address
, &Session
->DestinationAddress
, sizeof (DestIp4Address
));
1251 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) &&
1252 IP4_IS_MULTICAST (EFI_NTOHL (DestIp4Address
))
1257 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) &&
1258 IP4_IS_LOCAL_BROADCAST (EFI_NTOHL (DestIp4Address
))
1263 CopyMem (&Ip4Address
, &PxeBcMode
->StationIp
.v4
, sizeof (Ip4Address
));
1264 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) &&
1265 EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)
1270 for (Index
= 0; Index
< PxeBcMode
->IpFilter
.IpCnt
; ++Index
) {
1271 CopyMem (&Ip4Address
, &PxeBcMode
->IpFilter
.IpList
[Index
].v4
, sizeof (Ip4Address
));
1272 if (EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)) {
1281 GC_NOTO: Add function description
1283 @param This GC_NOTO: add argument
1285 @param OpFlags GC_NOTO: add argument
1287 @param DestIp GC_NOTO: add argument
1289 @param DestPort GC_NOTO: add argument
1291 @param SrcIp GC_NOTO: add argument
1293 @param SrcPort GC_NOTO: add argument
1295 @param HeaderSize GC_NOTO: add argument
1297 @param HeaderPtr GC_NOTO: add argument
1299 @param BufferSize GC_NOTO: add argument
1301 @param BufferPtr GC_NOTO: add argument
1304 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1306 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1308 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1310 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1312 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1314 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
1321 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1323 IN OUT EFI_IP_ADDRESS
*DestIp
, OPTIONAL
1324 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
, OPTIONAL
1325 IN OUT EFI_IP_ADDRESS
*SrcIp
, OPTIONAL
1326 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort
, OPTIONAL
1327 IN UINTN
*HeaderSize
, OPTIONAL
1328 IN VOID
*HeaderPtr
, OPTIONAL
1329 IN OUT UINTN
*BufferSize
,
1333 PXEBC_PRIVATE_DATA
*Private
;
1334 EFI_PXE_BASE_CODE_MODE
*Mode
;
1335 EFI_UDP4_PROTOCOL
*Udp4
;
1336 EFI_UDP4_COMPLETION_TOKEN Token
;
1337 EFI_UDP4_RECEIVE_DATA
*RxData
;
1338 EFI_UDP4_SESSION_DATA
*Session
;
1344 if (This
== NULL
|| DestIp
== NULL
|| DestPort
== NULL
) {
1345 return EFI_INVALID_PARAMETER
;
1348 if ((!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (DestPort
== NULL
)) ||
1349 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (SrcIp
== NULL
)) ||
1350 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && (SrcPort
== NULL
))) {
1351 return EFI_INVALID_PARAMETER
;
1354 if (((HeaderSize
!= NULL
) && (*HeaderSize
== 0)) || ((HeaderSize
!= NULL
) && (HeaderPtr
== NULL
))) {
1355 return EFI_INVALID_PARAMETER
;
1358 if ((BufferSize
== NULL
) || ((BufferPtr
== NULL
) && (*BufferSize
!= 0))) {
1359 return EFI_INVALID_PARAMETER
;
1362 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1363 Mode
= Private
->PxeBc
.Mode
;
1364 Udp4
= Private
->Udp4Read
;
1366 if (!Mode
->Started
) {
1367 return EFI_NOT_STARTED
;
1370 Mode
->IcmpErrorReceived
= FALSE
;
1372 Status
= gBS
->CreateEvent (
1379 if (EFI_ERROR (Status
)) {
1380 return EFI_OUT_OF_RESOURCES
;
1386 Status
= Udp4
->Receive (Udp4
, &Token
);
1387 if (EFI_ERROR (Status
)) {
1388 if (Status
== EFI_ICMP_ERROR
) {
1389 Mode
->IcmpErrorReceived
= TRUE
;
1397 Status
= EFI_TIMEOUT
;
1401 // check whether this packet matches the filters
1403 if (EFI_ERROR (Token
.Status
)){
1407 RxData
= Token
.Packet
.RxData
;
1408 Session
= &RxData
->UdpSession
;
1412 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
) {
1414 // Check UDP package by IP filter settings
1416 if (CheckIpByFilter (Mode
, Session
)) {
1425 // Match the destination ip of the received udp dgram
1427 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
) {
1430 if (DestIp
!= NULL
) {
1431 CopyMem (DestIp
, &Session
->DestinationAddress
, sizeof (EFI_IPv4_ADDRESS
));
1434 if (DestIp
!= NULL
) {
1435 if (EFI_IP4_EQUAL (DestIp
, &Session
->DestinationAddress
)) {
1439 if (EFI_IP4_EQUAL (&Private
->StationIp
, &Session
->DestinationAddress
)) {
1448 // Match the destination port of the received udp dgram
1450 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) {
1452 if (DestPort
!= NULL
) {
1453 *DestPort
= Session
->DestinationPort
;
1457 if (*DestPort
!= Session
->DestinationPort
) {
1465 // Match the source ip of the received udp dgram
1467 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) {
1469 if (SrcIp
!= NULL
) {
1470 CopyMem (SrcIp
, &Session
->SourceAddress
, sizeof (EFI_IPv4_ADDRESS
));
1474 if (!EFI_IP4_EQUAL (SrcIp
, &Session
->SourceAddress
)) {
1482 // Match the source port of the received udp dgram
1484 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
1486 if (SrcPort
!= NULL
) {
1487 *SrcPort
= Session
->SourcePort
;
1491 if (*SrcPort
!= Session
->SourcePort
) {
1501 if (HeaderSize
!= NULL
) {
1502 CopyLen
= MIN (*HeaderSize
, RxData
->DataLength
);
1503 CopyMem (HeaderPtr
, RxData
->FragmentTable
[0].FragmentBuffer
, CopyLen
);
1504 *HeaderSize
= CopyLen
;
1507 if (RxData
->DataLength
- CopyLen
> *BufferSize
) {
1509 Status
= EFI_BUFFER_TOO_SMALL
;
1512 *BufferSize
= RxData
->DataLength
- CopyLen
;
1513 CopyMem (BufferPtr
, (UINT8
*) RxData
->FragmentTable
[0].FragmentBuffer
+ CopyLen
, *BufferSize
);
1517 Status
= EFI_TIMEOUT
;
1521 // Recycle the RxData
1523 gBS
->SignalEvent (RxData
->RecycleSignal
);
1532 Udp4
->Cancel (Udp4
, &Token
);
1534 gBS
->CloseEvent (Token
.Event
);
1541 GC_NOTO: Add function description
1543 @param This GC_NOTO: add argument
1545 @param NewFilter GC_NOTO: add argument
1548 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1554 EfiPxeBcSetIpFilter (
1555 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1556 IN EFI_PXE_BASE_CODE_IP_FILTER
*NewFilter
1560 PXEBC_PRIVATE_DATA
*Private
;
1561 EFI_PXE_BASE_CODE_MODE
*Mode
;
1563 BOOLEAN PromiscuousNeed
;
1566 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL.\n"));
1567 return EFI_INVALID_PARAMETER
;
1570 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1571 Mode
= Private
->PxeBc
.Mode
;
1573 if (Private
== NULL
) {
1574 DEBUG ((EFI_D_ERROR
, "PXEBC_PRIVATE_DATA poiner == NULL.\n"));
1575 return EFI_INVALID_PARAMETER
;
1578 if (NewFilter
== NULL
) {
1579 DEBUG ((EFI_D_ERROR
, "IP Filter *NewFilter == NULL.\n"));
1580 return EFI_INVALID_PARAMETER
;
1583 if (!Mode
->Started
) {
1584 DEBUG ((EFI_D_ERROR
, "BC was not started.\n"));
1585 return EFI_NOT_STARTED
;
1588 PromiscuousNeed
= FALSE
;
1589 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1590 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter
->IpList
[Index
].v4
))) {
1592 // The IP is a broadcast address.
1594 DEBUG ((EFI_D_ERROR
, "There is broadcast address in NewFilter.\n"));
1595 return EFI_INVALID_PARAMETER
;
1597 if (Ip4IsUnicast (EFI_IP4 (NewFilter
->IpList
[Index
].v4
), 0) &&
1598 (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
)
1601 // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,
1602 // promiscuous mode is needed.
1604 PromiscuousNeed
= TRUE
;
1609 // Clear the UDP instance configuration, all joined groups will be left
1610 // during the operation.
1612 Private
->Udp4Read
->Configure (Private
->Udp4Read
, NULL
);
1613 Private
->Udp4CfgData
.AcceptPromiscuous
= FALSE
;
1614 Private
->Udp4CfgData
.AcceptBroadcast
= FALSE
;
1616 if (PromiscuousNeed
||
1617 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
||
1618 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
1621 // Configure the udp4 filter to receive all packages
1623 Private
->Udp4CfgData
.AcceptPromiscuous
= TRUE
;
1626 // Configure the UDP instance with the new configuration.
1628 Status
= Private
->Udp4Read
->Configure (Private
->Udp4Read
, &Private
->Udp4CfgData
);
1629 if (EFI_ERROR (Status
)) {
1635 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) {
1637 // Configure the udp4 filter to receive all broadcast packages
1639 Private
->Udp4CfgData
.AcceptBroadcast
= TRUE
;
1643 // Configure the UDP instance with the new configuration.
1645 Status
= Private
->Udp4Read
->Configure (Private
->Udp4Read
, &Private
->Udp4CfgData
);
1646 if (EFI_ERROR (Status
)) {
1650 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1652 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1653 if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter
->IpList
[Index
].v4
))) {
1655 // Join the mutilcast group
1657 Status
= Private
->Udp4Read
->Groups (Private
->Udp4Read
, TRUE
, &NewFilter
->IpList
[Index
].v4
);
1658 if (EFI_ERROR (Status
)) {
1668 // Save the new filter.
1670 CopyMem (&Mode
->IpFilter
, NewFilter
, sizeof (Mode
->IpFilter
));
1677 GC_NOTO: Add function description
1679 @param This GC_NOTO: add argument
1681 @param IpAddr GC_NOTO: add argument
1683 @param MacAddr GC_NOTO: add argument
1686 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1693 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1694 IN EFI_IP_ADDRESS
* IpAddr
,
1695 IN EFI_MAC_ADDRESS
* MacAddr OPTIONAL
1698 PXEBC_PRIVATE_DATA
*Private
;
1699 EFI_PXE_BASE_CODE_MODE
*Mode
;
1701 EFI_MAC_ADDRESS TempMacAddr
;
1703 if (This
== NULL
|| IpAddr
== NULL
) {
1704 return EFI_INVALID_PARAMETER
;
1707 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1708 Mode
= Private
->PxeBc
.Mode
;
1710 if (!Mode
->Started
) {
1711 return EFI_NOT_STARTED
;
1714 if (!Private
->AddressIsOk
|| Mode
->UsingIpv6
) {
1716 // We can't resolve the IP address if we don't have a local address now.
1717 // Don't have ARP for IPv6.
1719 return EFI_INVALID_PARAMETER
;
1722 Mode
->IcmpErrorReceived
= FALSE
;
1724 if (!Mode
->AutoArp
) {
1726 // If AutoArp is set false, check arp cache
1728 UpdateArpCache (This
);
1729 if (!FindInArpCache (Mode
, &IpAddr
->v4
, &TempMacAddr
)) {
1730 return EFI_DEVICE_ERROR
;
1733 Status
= Private
->Arp
->Request (Private
->Arp
, &IpAddr
->v4
, NULL
, &TempMacAddr
);
1734 if (EFI_ERROR (Status
)) {
1735 if (Status
== EFI_ICMP_ERROR
) {
1736 Mode
->IcmpErrorReceived
= TRUE
;
1742 if (MacAddr
!= NULL
) {
1743 CopyMem (MacAddr
, &TempMacAddr
, sizeof (EFI_MAC_ADDRESS
));
1752 GC_NOTO: Add function description
1754 @param This GC_NOTO: add argument
1756 @param NewAutoArp GC_NOTO: add argument
1758 @param NewSendGUID GC_NOTO: add argument
1760 @param NewTTL GC_NOTO: add argument
1762 @param NewToS GC_NOTO: add argument
1764 @param NewMakeCallback GC_NOTO: add argument
1767 @return GC_NOTO: add return values
1772 EfiPxeBcSetParameters (
1773 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1774 IN BOOLEAN
*NewAutoArp
, OPTIONAL
1775 IN BOOLEAN
*NewSendGUID
, OPTIONAL
1776 IN UINT8
*NewTTL
, OPTIONAL
1777 IN UINT8
*NewToS
, OPTIONAL
1778 IN BOOLEAN
*NewMakeCallback
// OPTIONAL
1781 PXEBC_PRIVATE_DATA
*Private
;
1782 EFI_PXE_BASE_CODE_MODE
*Mode
;
1785 Status
= EFI_SUCCESS
;
1788 Status
= EFI_INVALID_PARAMETER
;
1792 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1793 Mode
= Private
->PxeBc
.Mode
;
1795 if (NewSendGUID
!= NULL
&& *NewSendGUID
== TRUE
) {
1797 // FixMe, cann't locate SendGuid
1801 if (NewMakeCallback
!= NULL
&& *NewMakeCallback
== TRUE
) {
1803 Status
= gBS
->HandleProtocol (
1804 Private
->Controller
,
1805 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1806 (VOID
**) &Private
->PxeBcCallback
1808 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1810 Status
= EFI_INVALID_PARAMETER
;
1815 if (!Mode
->Started
) {
1816 Status
= EFI_NOT_STARTED
;
1820 if (NewMakeCallback
!= NULL
) {
1822 if (*NewMakeCallback
) {
1824 // Update the Callback protocol.
1826 Status
= gBS
->HandleProtocol (
1827 Private
->Controller
,
1828 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1829 (VOID
**) &Private
->PxeBcCallback
1832 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1833 Status
= EFI_INVALID_PARAMETER
;
1837 Private
->PxeBcCallback
= NULL
;
1840 Mode
->MakeCallbacks
= *NewMakeCallback
;
1843 if (NewAutoArp
!= NULL
) {
1844 Mode
->AutoArp
= *NewAutoArp
;
1847 if (NewSendGUID
!= NULL
) {
1848 Mode
->SendGUID
= *NewSendGUID
;
1851 if (NewTTL
!= NULL
) {
1852 Mode
->TTL
= *NewTTL
;
1855 if (NewToS
!= NULL
) {
1856 Mode
->ToS
= *NewToS
;
1865 GC_NOTO: Add function description
1867 @param This GC_NOTO: add argument
1869 @param NewStationIp GC_NOTO: add argument
1871 @param NewSubnetMask GC_NOTO: add argument
1874 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1876 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1878 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1880 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1882 @retval EFI_SUCCESS GC_NOTO: Add description for
1888 EfiPxeBcSetStationIP (
1889 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1890 IN EFI_IP_ADDRESS
* NewStationIp
, OPTIONAL
1891 IN EFI_IP_ADDRESS
* NewSubnetMask OPTIONAL
1894 PXEBC_PRIVATE_DATA
*Private
;
1895 EFI_PXE_BASE_CODE_MODE
*Mode
;
1896 EFI_ARP_CONFIG_DATA ArpConfigData
;
1899 return EFI_INVALID_PARAMETER
;
1902 if (NewStationIp
!= NULL
&& !Ip4IsUnicast (NTOHL (NewStationIp
->Addr
[0]), 0)) {
1903 return EFI_INVALID_PARAMETER
;
1906 if (NewSubnetMask
!= NULL
&& !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask
->Addr
[0]))) {
1907 return EFI_INVALID_PARAMETER
;
1910 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1911 Mode
= Private
->PxeBc
.Mode
;
1913 if (!Mode
->Started
) {
1914 return EFI_NOT_STARTED
;
1917 if (NewStationIp
!= NULL
) {
1918 Mode
->StationIp
= *NewStationIp
;
1919 Private
->StationIp
= *NewStationIp
;
1922 if (NewSubnetMask
!= NULL
) {
1923 Mode
->SubnetMask
= *NewSubnetMask
;
1924 Private
->SubnetMask
= *NewSubnetMask
;
1927 Private
->AddressIsOk
= TRUE
;
1929 if (!Mode
->UsingIpv6
) {
1931 // If in IPv4 mode, configure the corresponding ARP with this new
1932 // station IP address.
1934 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
1936 ArpConfigData
.SwAddressType
= 0x0800;
1937 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
1938 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
1940 Private
->Arp
->Configure (Private
->Arp
, NULL
);
1941 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
1944 // Update the route table.
1946 Mode
->RouteTableEntries
= 1;
1947 Mode
->RouteTable
[0].IpAddr
.Addr
[0] = Private
->StationIp
.Addr
[0] & Private
->SubnetMask
.Addr
[0];
1948 Mode
->RouteTable
[0].SubnetMask
.Addr
[0] = Private
->SubnetMask
.Addr
[0];
1949 Mode
->RouteTable
[0].GwAddr
.Addr
[0] = 0;
1957 GC_NOTO: Add function description
1959 @param This GC_NOTO: add argument
1961 @param NewDhcpDiscoverValid GC_NOTO: add argument
1963 @param NewDhcpAckReceived GC_NOTO: add argument
1965 @param NewProxyOfferReceived GC_NOTO: add argument
1967 @param NewPxeDiscoverValid GC_NOTO: add argument
1969 @param NewPxeReplyReceived GC_NOTO: add argument
1971 @param NewPxeBisReplyReceived GC_NOTO: add argument
1973 @param NewDhcpDiscover GC_NOTO: add argument
1975 @param NewDhcpAck GC_NOTO: add argument
1977 @param NewProxyOffer GC_NOTO: add argument
1979 @param NewPxeDiscover GC_NOTO: add argument
1981 @param NewPxeReply GC_NOTO: add argument
1983 @param NewPxeBisReply GC_NOTO: add argument
1986 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1988 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1990 @retval EFI_SUCCESS GC_NOTO: Add description for
1996 EfiPxeBcSetPackets (
1997 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1998 IN BOOLEAN
* NewDhcpDiscoverValid
, OPTIONAL
1999 IN BOOLEAN
* NewDhcpAckReceived
, OPTIONAL
2000 IN BOOLEAN
* NewProxyOfferReceived
, OPTIONAL
2001 IN BOOLEAN
* NewPxeDiscoverValid
, OPTIONAL
2002 IN BOOLEAN
* NewPxeReplyReceived
, OPTIONAL
2003 IN BOOLEAN
* NewPxeBisReplyReceived
, OPTIONAL
2004 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
2005 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
2006 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
2007 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
2008 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
2009 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
2012 PXEBC_PRIVATE_DATA
*Private
;
2013 EFI_PXE_BASE_CODE_MODE
*Mode
;
2016 return EFI_INVALID_PARAMETER
;
2019 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
2020 Mode
= Private
->PxeBc
.Mode
;
2022 if (!Mode
->Started
) {
2023 return EFI_NOT_STARTED
;
2026 Private
->FileSize
= 0;
2028 if (NewDhcpDiscoverValid
!= NULL
) {
2029 Mode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
2032 if (NewDhcpAckReceived
!= NULL
) {
2033 Mode
->DhcpAckReceived
= *NewDhcpAckReceived
;
2036 if (NewProxyOfferReceived
!= NULL
) {
2037 Mode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
2040 if (NewPxeDiscoverValid
!= NULL
) {
2041 Mode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
2044 if (NewPxeReplyReceived
!= NULL
) {
2045 Mode
->PxeReplyReceived
= *NewPxeReplyReceived
;
2048 if (NewPxeBisReplyReceived
!= NULL
) {
2049 Mode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
2052 if (NewDhcpDiscover
!= NULL
) {
2053 CopyMem (&Mode
->DhcpDiscover
, NewDhcpDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2056 if (NewDhcpAck
!= NULL
) {
2057 CopyMem (&Mode
->DhcpAck
, NewDhcpAck
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2060 if (NewProxyOffer
!= NULL
) {
2061 CopyMem (&Mode
->ProxyOffer
, NewProxyOffer
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2064 if (NewPxeDiscover
!= NULL
) {
2065 CopyMem (&Mode
->PxeDiscover
, NewPxeDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2068 if (NewPxeReply
!= NULL
) {
2069 CopyMem (&Mode
->PxeReply
, NewPxeReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2072 if (NewPxeBisReply
!= NULL
) {
2073 CopyMem (&Mode
->PxeBisReply
, NewPxeBisReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
2079 EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate
= {
2080 EFI_PXE_BASE_CODE_PROTOCOL_REVISION
,
2088 EfiPxeBcSetIpFilter
,
2090 EfiPxeBcSetParameters
,
2091 EfiPxeBcSetStationIP
,
2098 GC_NOTO: Add function description
2100 @param This GC_NOTO: add argument
2102 @param Function GC_NOTO: add argument
2104 @param Received GC_NOTO: add argument
2106 @param PacketLength GC_NOTO: add argument
2108 @param PacketPtr GC_NOTO: add argument
2111 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT GC_NOTO: Add description for
2113 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2115 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2117 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2119 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
2123 EFI_PXE_BASE_CODE_CALLBACK_STATUS
2125 EfiPxeLoadFileCallback (
2126 IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL
* This
,
2127 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
2128 IN BOOLEAN Received
,
2129 IN UINT32 PacketLength
,
2130 IN EFI_PXE_BASE_CODE_PACKET
* PacketPtr OPTIONAL
2137 // Catch Ctrl-C or ESC to abort.
2139 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2141 if (!EFI_ERROR (Status
)) {
2143 if (Key
.ScanCode
== SCAN_ESC
|| Key
.UnicodeChar
== (0x1F & 'c')) {
2145 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT
;
2149 // No print if receive packet
2152 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2155 // Print only for three functions
2159 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP
:
2161 // Print only for open MTFTP packets, not every MTFTP packets
2163 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2164 if (PacketPtr
->Raw
[0x1C] != 0x00 || PacketPtr
->Raw
[0x1D] != 0x01) {
2165 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2170 case EFI_PXE_BASE_CODE_FUNCTION_DHCP
:
2171 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
:
2175 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2178 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
2180 // Print '.' when transmit a packet
2186 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
2189 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate
= {
2190 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION
,
2191 EfiPxeLoadFileCallback
2196 GC_NOTO: Add function description
2198 @param Private GC_NOTO: add argument
2200 @param BufferSize GC_NOTO: add argument
2202 @param Buffer GC_NOTO: add argument
2205 @return GC_NOTO: add return values
2210 IN PXEBC_PRIVATE_DATA
*Private
,
2211 IN OUT UINT64
*BufferSize
,
2215 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2216 EFI_PXE_BASE_CODE_MODE
*Mode
;
2222 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
2225 PxeBc
= &Private
->PxeBc
;
2227 Type
= EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
;
2228 Layer
= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
;
2233 Status
= PxeBc
->Dhcp (PxeBc
, TRUE
);
2234 if (EFI_ERROR (Status
)) {
2239 // Select a boot server
2241 Status
= PxeBcSelectBootPrompt (Private
);
2243 if (Status
== EFI_SUCCESS
) {
2244 Status
= PxeBcSelectBootMenu (Private
, &Type
, TRUE
);
2245 } else if (Status
== EFI_TIMEOUT
) {
2246 Status
= PxeBcSelectBootMenu (Private
, &Type
, FALSE
);
2249 if (!EFI_ERROR (Status
)) {
2251 if (Type
== EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
) {
2253 // Local boot(PXE bootstrap server) need abort
2258 UseBis
= (BOOLEAN
) (Mode
->BisSupported
&& Mode
->BisDetected
);
2259 Status
= PxeBc
->Discover (PxeBc
, Type
, &Layer
, UseBis
, NULL
);
2260 if (EFI_ERROR (Status
)) {
2269 // Get bootfile name and (m)tftp server ip addresss
2271 if (Mode
->PxeReplyReceived
) {
2272 Packet
= &Private
->PxeReply
;
2273 } else if (Mode
->ProxyOfferReceived
) {
2274 Packet
= &Private
->ProxyOffer
;
2276 Packet
= &Private
->Dhcp4Ack
;
2279 CopyMem (&Private
->ServerIp
, &Packet
->Packet
.Offer
.Dhcp4
.Header
.ServerAddr
, sizeof (EFI_IPv4_ADDRESS
));
2280 if (Private
->ServerIp
.Addr
[0] == 0) {
2282 // next server ip address is zero, use option 54 instead
2286 Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_SERVER_ID
]->Data
,
2287 sizeof (EFI_IPv4_ADDRESS
)
2291 ASSERT (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
);
2296 Private
->BootFileName
= (CHAR8
*) (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
]->Data
);
2298 if (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
] != NULL
) {
2300 // Already have the bootfile length option, compute the file size
2302 CopyMem (&Value
, Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
]->Data
, sizeof (Value
));
2303 Value
= NTOHS (Value
);
2304 *BufferSize
= 512 * Value
;
2305 Status
= EFI_BUFFER_TOO_SMALL
;
2308 // Get the bootfile size from tftp
2310 Status
= PxeBc
->Mtftp (
2312 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
,
2318 (UINT8
*) Private
->BootFileName
,
2324 Private
->FileSize
= (UINTN
) *BufferSize
;
2331 GC_NOTO: Add function description
2333 @param This GC_NOTO: add argument
2335 @param FilePath GC_NOTO: add argument
2337 @param BootPolicy GC_NOTO: add argument
2339 @param BufferSize GC_NOTO: add argument
2341 @param Buffer GC_NOTO: add argument
2344 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
2346 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
2353 IN EFI_LOAD_FILE_PROTOCOL
* This
,
2354 IN EFI_DEVICE_PATH_PROTOCOL
* FilePath
,
2355 IN BOOLEAN BootPolicy
,
2356 IN OUT UINTN
*BufferSize
,
2357 IN VOID
*Buffer OPTIONAL
2360 PXEBC_PRIVATE_DATA
*Private
;
2361 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
2362 BOOLEAN NewMakeCallback
;
2367 Private
= PXEBC_PRIVATE_DATA_FROM_LOADFILE (This
);
2368 PxeBc
= &Private
->PxeBc
;
2369 NewMakeCallback
= FALSE
;
2371 Status
= EFI_DEVICE_ERROR
;
2373 if (This
== NULL
|| BufferSize
== NULL
) {
2375 return EFI_INVALID_PARAMETER
;
2379 // Only support BootPolicy
2382 return EFI_UNSUPPORTED
;
2385 Status
= PxeBc
->Start (PxeBc
, FALSE
);
2386 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
2390 Status
= gBS
->HandleProtocol (
2391 Private
->Controller
,
2392 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2393 (VOID
**) &Private
->PxeBcCallback
2395 if (Status
== EFI_UNSUPPORTED
) {
2397 CopyMem (&Private
->LoadFileCallback
, &mPxeBcCallBackTemplate
, sizeof (Private
->LoadFileCallback
));
2399 Status
= gBS
->InstallProtocolInterface (
2400 &Private
->Controller
,
2401 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2402 EFI_NATIVE_INTERFACE
,
2403 &Private
->LoadFileCallback
2406 NewMakeCallback
= (BOOLEAN
) (Status
== EFI_SUCCESS
);
2408 Status
= PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2409 if (EFI_ERROR (Status
)) {
2410 PxeBc
->Stop (PxeBc
);
2415 if (Private
->FileSize
== 0) {
2417 Status
= DiscoverBootFile (Private
, &TmpBufSize
, Buffer
);
2419 if (sizeof (UINTN
) < sizeof (UINT64
) && (TmpBufSize
> 0xFFFFFFFF)) {
2420 Status
= EFI_DEVICE_ERROR
;
2422 *BufferSize
= (UINTN
) TmpBufSize
;
2424 } else if (Buffer
== NULL
) {
2425 *BufferSize
= Private
->FileSize
;
2426 Status
= EFI_BUFFER_TOO_SMALL
;
2429 // Download the file.
2431 TmpBufSize
= (UINT64
) (*BufferSize
);
2432 Status
= PxeBc
->Mtftp (
2434 EFI_PXE_BASE_CODE_TFTP_READ_FILE
,
2440 (UINT8
*) Private
->BootFileName
,
2446 // If we added a callback protocol, now is the time to remove it.
2448 if (NewMakeCallback
) {
2450 NewMakeCallback
= FALSE
;
2452 PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2454 gBS
->UninstallProtocolInterface (
2455 Private
->Controller
,
2456 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2457 &Private
->LoadFileCallback
2462 // Check download status
2464 if (Status
== EFI_SUCCESS
) {
2467 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
2468 if (Buffer
!= NULL
) {
2469 AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
2474 } else if (Status
== EFI_DEVICE_ERROR
) {
2475 AsciiPrint ("PXE-E07: Network device error.\n");
2477 } else if (Status
== EFI_OUT_OF_RESOURCES
) {
2478 AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
2480 } else if (Status
== EFI_NO_MEDIA
) {
2481 AsciiPrint ("PXE-E12: Could not detect network connection.\n");
2483 } else if (Status
== EFI_NO_RESPONSE
) {
2484 AsciiPrint ("PXE-E16: No offer received.\n");
2486 } else if (Status
== EFI_TIMEOUT
) {
2487 AsciiPrint ("PXE-E18: Server response timeout.\n");
2489 } else if (Status
== EFI_ABORTED
) {
2490 AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
2492 } else if (Status
== EFI_ICMP_ERROR
) {
2493 AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
2495 } else if (Status
== EFI_TFTP_ERROR
) {
2496 AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
2499 AsciiPrint ("PXE-E99: Unexpected network error.\n");
2502 PxeBc
->Stop (PxeBc
);
2507 EFI_LOAD_FILE_PROTOCOL mLoadFileProtocolTemplate
= { EfiPxeLoadFile
};