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"
28 GC_NOTO: Add function description
30 @param This GC_NOTO: add argument
32 @param UseIpv6 GC_NOTO: add argument
35 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
37 @retval EFI_ALREADY_STARTED GC_NOTO: Add description for
39 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
41 @retval EFI_SUCCESS GC_NOTO: Add description for
48 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
52 PXEBC_PRIVATE_DATA
*Private
;
53 EFI_PXE_BASE_CODE_MODE
*Mode
;
57 return EFI_INVALID_PARAMETER
;
60 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
61 Mode
= Private
->PxeBc
.Mode
;
64 return EFI_ALREADY_STARTED
;
69 // IPv6 is not supported now.
71 return EFI_UNSUPPORTED
;
75 // Configure the udp4 instance to let it receive data
77 Status
= Private
->Udp4
->Configure (Private
->Udp4
, &Private
->Udp4CfgData
);
78 if (EFI_ERROR (Status
)) {
82 Private
->AddressIsOk
= FALSE
;
84 ZeroMem (Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
87 Mode
->TTL
= DEFAULT_TTL
;
88 Mode
->ToS
= DEFAULT_ToS
;
96 GC_NOTO: Add function description
98 @param This GC_NOTO: add argument
101 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
103 @retval EFI_NOT_STARTED GC_NOTO: Add description for
105 @retval EFI_SUCCESS GC_NOTO: Add description for
112 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
115 PXEBC_PRIVATE_DATA
*Private
;
116 EFI_PXE_BASE_CODE_MODE
*Mode
;
119 return EFI_INVALID_PARAMETER
;
122 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
123 Mode
= Private
->PxeBc
.Mode
;
125 if (!Mode
->Started
) {
126 return EFI_NOT_STARTED
;
129 Mode
->Started
= FALSE
;
132 // Reset and leave joined groups
134 Private
->Udp4
->Groups (Private
->Udp4
, FALSE
, NULL
);
136 Private
->Udp4
->Configure (Private
->Udp4
, NULL
);
138 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
139 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
141 Private
->FileSize
= 0;
148 GC_NOTO: Add function description
150 @param This GC_NOTO: add argument
152 @param SortOffers GC_NOTO: add argument
155 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
157 @retval EFI_NOT_STARTED GC_NOTO: Add description for
164 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
165 IN BOOLEAN SortOffers
168 PXEBC_PRIVATE_DATA
*Private
;
169 EFI_PXE_BASE_CODE_MODE
*Mode
;
170 EFI_DHCP4_PROTOCOL
*Dhcp4
;
171 EFI_DHCP4_CONFIG_DATA Dhcp4CfgData
;
172 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
173 EFI_DHCP4_PACKET_OPTION
*OptList
[PXEBC_DHCP4_MAX_OPTION_NUM
];
175 UINT32 DiscoverTimeout
;
178 EFI_ARP_CONFIG_DATA ArpConfigData
;
181 return EFI_INVALID_PARAMETER
;
184 Status
= EFI_SUCCESS
;
185 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
186 Mode
= Private
->PxeBc
.Mode
;
187 Dhcp4
= Private
->Dhcp4
;
188 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
189 Private
->SortOffers
= SortOffers
;
191 if (!Mode
->Started
) {
192 return EFI_NOT_STARTED
;
195 // Initialize the DHCP options and build the option list
197 OptCount
= PxeBcBuildDhcpOptions (Private
, OptList
, TRUE
);
200 // Set the DHCP4 config data.
202 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
203 Dhcp4CfgData
.OptionCount
= OptCount
;
204 Dhcp4CfgData
.OptionList
= OptList
;
205 Dhcp4CfgData
.Dhcp4Callback
= PxeBcDhcpCallBack
;
206 Dhcp4CfgData
.CallbackContext
= Private
;
207 Dhcp4CfgData
.DiscoverTryCount
= 1;
208 Dhcp4CfgData
.DiscoverTimeout
= &DiscoverTimeout
;
210 for (Index
= 0; Index
< PXEBC_DHCP4_DISCOVER_RETRIES
; Index
++) {
212 // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.
214 DiscoverTimeout
= (PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT
<< Index
);
216 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
217 if (EFI_ERROR (Status
)) {
221 // Zero those arrays to record the varies numbers of DHCP OFFERS.
223 Private
->NumOffers
= 0;
224 Private
->BootpIndex
= 0;
225 ZeroMem (Private
->ServerCount
, sizeof (Private
->ServerCount
));
226 ZeroMem (Private
->ProxyIndex
, sizeof (Private
->ProxyIndex
));
228 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
229 if (EFI_ERROR (Status
)) {
230 if (Status
== EFI_TIMEOUT
) {
232 // If no response is received or all received offers don't match
233 // the PXE boot requirements, EFI_TIMEOUT will be returned.
238 // Other error status means the DHCP really fails.
243 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
244 if (EFI_ERROR (Status
)) {
248 ASSERT (Dhcp4Mode
.State
== Dhcp4Bound
);
250 CopyMem (&Private
->StationIp
, &Dhcp4Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
251 CopyMem (&Private
->SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
252 CopyMem (&Private
->GatewayIp
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
255 // Check the selected offer to see whether BINL is required, if no or BINL is
256 // finished, set the various Mode members.
258 Status
= PxeBcCheckSelectedOffer (Private
);
259 if (!EFI_ERROR (Status
)) {
264 if (EFI_ERROR (Status
)) {
266 Dhcp4
->Configure (Dhcp4
, NULL
);
269 // Remove the previously configured option list and callback function
271 ZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
272 Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
274 Private
->AddressIsOk
= TRUE
;
276 if (!Mode
->UsingIpv6
) {
278 // If in IPv4 mode, configure the corresponding ARP with this new
279 // station IP address.
281 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
283 ArpConfigData
.SwAddressType
= 0x0800;
284 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
285 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
287 Private
->Arp
->Configure (Private
->Arp
, NULL
);
288 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
297 GC_NOTO: Add function description
299 @param This GC_NOTO: add argument
301 @param Type GC_NOTO: add argument
303 @param Layer GC_NOTO: add argument
305 @param UseBis GC_NOTO: add argument
307 @param Info GC_NOTO: add argument
310 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
312 @retval EFI_NOT_STARTED GC_NOTO: Add description for
314 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
316 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
318 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
320 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
327 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
331 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*Info OPTIONAL
334 PXEBC_PRIVATE_DATA
*Private
;
335 EFI_PXE_BASE_CODE_MODE
*Mode
;
336 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
337 EFI_PXE_BASE_CODE_SRVLIST
*SrvList
;
338 EFI_PXE_BASE_CODE_SRVLIST DefaultSrvList
;
339 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
340 PXEBC_VENDOR_OPTION
*VendorOpt
;
343 PXEBC_BOOT_SVR_ENTRY
*BootSvrEntry
;
346 return EFI_INVALID_PARAMETER
;
349 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
350 Mode
= Private
->PxeBc
.Mode
;
353 Status
= EFI_DEVICE_ERROR
;
354 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
356 if (!Private
->AddressIsOk
) {
357 return EFI_INVALID_PARAMETER
;
360 if (!Mode
->Started
) {
361 return EFI_NOT_STARTED
;
365 // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
366 // use the previous setting;
367 // If info isn't offered,
368 // use the cached DhcpAck and ProxyOffer packets.
370 if (*Layer
!= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
) {
372 if (!Mode
->PxeDiscoverValid
|| !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
374 return EFI_INVALID_PARAMETER
;
377 DefaultInfo
.IpCnt
= 1;
378 DefaultInfo
.UseUCast
= TRUE
;
380 DefaultSrvList
.Type
= Type
;
381 DefaultSrvList
.AcceptAnyResponse
= FALSE
;
382 DefaultSrvList
.IpAddr
.Addr
[0] = Private
->ServerIp
.Addr
[0];
384 SrvList
= &DefaultSrvList
;
386 } else if (Info
== NULL
) {
388 // Create info by the cached packet before
390 Packet
= (Mode
->ProxyOfferReceived
) ? &Private
->ProxyOffer
: &Private
->Dhcp4Ack
;
391 VendorOpt
= &Packet
->PxeVendorOption
;
393 if (!Mode
->DhcpAckReceived
|| !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt
->BitMap
)) {
395 // Address is not acquired or no discovery options.
397 return EFI_INVALID_PARAMETER
;
400 DefaultInfo
.UseMCast
= (BOOLEAN
)!IS_DISABLE_MCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
401 DefaultInfo
.UseBCast
= (BOOLEAN
)!IS_DISABLE_BCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
402 DefaultInfo
.MustUseList
= (BOOLEAN
) IS_ENABLE_USE_SERVER_LIST (VendorOpt
->DiscoverCtrl
);
403 DefaultInfo
.UseUCast
= DefaultInfo
.MustUseList
;
405 if (DefaultInfo
.UseMCast
) {
407 // Get the multicast discover ip address from vendor option.
409 CopyMem (&DefaultInfo
.ServerMCastIp
.Addr
, &VendorOpt
->DiscoverMcastIp
, sizeof (EFI_IPv4_ADDRESS
));
412 DefaultInfo
.IpCnt
= 0;
414 if (DefaultInfo
.MustUseList
) {
415 BootSvrEntry
= VendorOpt
->BootSvr
;
416 Status
= EFI_INVALID_PARAMETER
;
418 while (((UINT8
) (BootSvrEntry
- VendorOpt
->BootSvr
)) < VendorOpt
->BootSvrLen
) {
420 if (BootSvrEntry
->Type
== HTONS (Type
)) {
421 Status
= EFI_SUCCESS
;
425 BootSvrEntry
= GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry
);
428 if (EFI_ERROR (Status
)) {
432 DefaultInfo
.IpCnt
= BootSvrEntry
->IpCnt
;
438 SrvList
= Info
->SrvList
;
440 if (!SrvList
[0].AcceptAnyResponse
) {
442 for (Index
= 1; Index
< Info
->IpCnt
; Index
++) {
443 if (SrvList
[Index
].AcceptAnyResponse
) {
448 if (Index
!= Info
->IpCnt
) {
449 return EFI_INVALID_PARAMETER
;
454 if ((!Info
->UseUCast
&& !Info
->UseBCast
&& !Info
->UseMCast
) || (Info
->MustUseList
&& Info
->IpCnt
== 0)) {
456 return EFI_INVALID_PARAMETER
;
459 // Execute discover by UniCast/BroadCast/MultiCast
461 if (Info
->UseUCast
) {
463 for (Index
= 0; Index
< Info
->IpCnt
; Index
++) {
465 if (BootSvrEntry
== NULL
) {
466 Private
->ServerIp
.Addr
[0] = SrvList
[Index
].IpAddr
.Addr
[0];
468 CopyMem (&Private
->ServerIp
, &BootSvrEntry
->IpAddr
[Index
], sizeof (EFI_IPv4_ADDRESS
));
471 Status
= PxeBcDiscvBootService (
476 &SrvList
[Index
].IpAddr
,
480 &Private
->PxeReply
.Packet
.Ack
484 } else if (Info
->UseMCast
) {
486 Status
= PxeBcDiscvBootService (
491 &Info
->ServerMCastIp
,
495 &Private
->PxeReply
.Packet
.Ack
498 } else if (Info
->UseBCast
) {
500 Status
= PxeBcDiscvBootService (
509 &Private
->PxeReply
.Packet
.Ack
513 if (EFI_ERROR (Status
) || !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
515 Status
= EFI_DEVICE_ERROR
;
517 PxeBcParseCachedDhcpPacket (&Private
->PxeReply
);
520 if (Mode
->PxeBisReplyReceived
) {
521 CopyMem (&Private
->ServerIp
, &Mode
->PxeReply
.Dhcpv4
.BootpSiAddr
, sizeof (EFI_IPv4_ADDRESS
));
529 GC_NOTO: Add function description
531 @param This GC_NOTO: add argument
533 @param Operation GC_NOTO: add argument
535 @param BufferPtr GC_NOTO: add argument
537 @param Overwrite GC_NOTO: add argument
539 @param BufferSize GC_NOTO: add argument
541 @param BlockSize GC_NOTO: add argument
543 @param ServerIp GC_NOTO: add argument
545 @param Filename GC_NOTO: add argument
547 @param Info GC_NOTO: add argument
549 @param DontUseBuffer GC_NOTO: add argument
552 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
559 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
560 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
561 IN OUT VOID
*BufferPtr
,
562 IN BOOLEAN Overwrite
,
563 IN OUT UINT64
*BufferSize
,
564 IN UINTN
*BlockSize OPTIONAL
,
565 IN EFI_IP_ADDRESS
*ServerIp
,
567 IN EFI_PXE_BASE_CODE_MTFTP_INFO
*Info OPTIONAL
,
568 IN BOOLEAN DontUseBuffer
571 PXEBC_PRIVATE_DATA
*Private
;
572 EFI_MTFTP4_CONFIG_DATA Mtftp4Config
;
575 if ((This
== NULL
) ||
576 (Filename
== NULL
) ||
577 (BufferSize
== NULL
) ||
578 ((ServerIp
== NULL
) || !Ip4IsUnicast (NTOHL (ServerIp
->Addr
[0]), 0)) ||
579 ((BufferPtr
== NULL
) && DontUseBuffer
) ||
580 ((BlockSize
!= NULL
) && (*BlockSize
< 512))) {
582 return EFI_INVALID_PARAMETER
;
585 Status
= EFI_DEVICE_ERROR
;
586 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
588 Mtftp4Config
.UseDefaultSetting
= FALSE
;
589 Mtftp4Config
.TimeoutValue
= PXEBC_MTFTP_TIMEOUT
;
590 Mtftp4Config
.TryCount
= PXEBC_MTFTP_RETRIES
;
592 CopyMem (&Mtftp4Config
.StationIp
, &Private
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
593 CopyMem (&Mtftp4Config
.SubnetMask
, &Private
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
594 CopyMem (&Mtftp4Config
.GatewayIp
, &Private
->GatewayIp
, sizeof (EFI_IPv4_ADDRESS
));
595 CopyMem (&Mtftp4Config
.ServerIp
, ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
599 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
:
601 Status
= PxeBcTftpGetFileSize (
609 if (!EFI_ERROR (Status
)) {
610 Status
= EFI_BUFFER_TOO_SMALL
;
615 case EFI_PXE_BASE_CODE_TFTP_READ_FILE
:
617 Status
= PxeBcTftpReadFile (
629 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
:
631 Status
= PxeBcTftpWriteFile (
643 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY
:
645 Status
= PxeBcTftpReadDirectory (
657 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE
:
658 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE
:
659 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY
:
660 Status
= EFI_UNSUPPORTED
;
665 Status
= EFI_INVALID_PARAMETER
;
674 GC_NOTO: Add function description
676 @param This GC_NOTO: add argument
678 @param OpFlags GC_NOTO: add argument
680 @param DestIp GC_NOTO: add argument
682 @param DestPort GC_NOTO: add argument
684 @param GatewayIp GC_NOTO: add argument
686 @param SrcIp GC_NOTO: add argument
688 @param SrcPort GC_NOTO: add argument
690 @param HeaderSize GC_NOTO: add argument
692 @param HeaderPtr GC_NOTO: add argument
694 @param BufferSize GC_NOTO: add argument
696 @param BufferPtr GC_NOTO: add argument
699 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
701 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
703 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
705 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
707 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
714 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
716 IN EFI_IP_ADDRESS
*DestIp
,
717 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
,
718 IN EFI_IP_ADDRESS
*GatewayIp OPTIONAL
,
719 IN EFI_IP_ADDRESS
*SrcIp OPTIONAL
,
720 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort OPTIONAL
,
721 IN UINTN
*HeaderSize OPTIONAL
,
722 IN VOID
*HeaderPtr OPTIONAL
,
723 IN UINTN
*BufferSize
,
727 PXEBC_PRIVATE_DATA
*Private
;
728 EFI_UDP4_PROTOCOL
*Udp4
;
729 EFI_UDP4_COMPLETION_TOKEN Token
;
730 EFI_UDP4_TRANSMIT_DATA
*Udp4TxData
;
733 EFI_UDP4_SESSION_DATA Udp4Session
;
736 UINT16 RandomSrcPort
;
740 if ((This
== NULL
) || (DestIp
== NULL
) || (DestPort
== NULL
)) {
741 return EFI_INVALID_PARAMETER
;
744 if ((GatewayIp
!= NULL
) && !Ip4IsUnicast (NTOHL (GatewayIp
->Addr
[0]), 0)) {
746 // Gateway is provided but it's not a unicast IP address.
748 return EFI_INVALID_PARAMETER
;
751 if ((HeaderSize
!= NULL
) && ((*HeaderSize
== 0) || (HeaderPtr
== NULL
))) {
753 // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
756 return EFI_INVALID_PARAMETER
;
759 if ((BufferSize
== NULL
) || ((*BufferSize
!= 0) && (BufferPtr
== NULL
))) {
760 return EFI_INVALID_PARAMETER
;
763 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
764 Udp4
= Private
->Udp4
;
766 if (!Private
->AddressIsOk
&& (SrcIp
== NULL
)) {
767 return EFI_INVALID_PARAMETER
;
771 SrcIp
= &Private
->StationIp
;
773 if (GatewayIp
== NULL
) {
774 GatewayIp
= &Private
->GatewayIp
;
778 if ((SrcPort
== NULL
) || (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
)) {
779 RandomSrcPort
= (UINT16
) (NET_RANDOM (NetRandomInitSeed ()) % 10000 + 1024);
781 if (SrcPort
== NULL
) {
783 SrcPort
= &RandomSrcPort
;
786 *SrcPort
= RandomSrcPort
;
790 ZeroMem (&Token
, sizeof (EFI_UDP4_COMPLETION_TOKEN
));
791 ZeroMem (&Udp4Session
, sizeof (EFI_UDP4_SESSION_DATA
));
793 CopyMem (&Udp4Session
.DestinationAddress
, DestIp
, sizeof (EFI_IPv4_ADDRESS
));
794 Udp4Session
.DestinationPort
= *DestPort
;
795 CopyMem (&Udp4Session
.SourceAddress
, SrcIp
, sizeof (EFI_IPv4_ADDRESS
));
796 Udp4Session
.SourcePort
= *SrcPort
;
798 FragCount
= (HeaderSize
!= NULL
) ? 2 : 1;
799 Udp4TxData
= (EFI_UDP4_TRANSMIT_DATA
*) AllocatePool (sizeof (EFI_UDP4_TRANSMIT_DATA
) + (FragCount
- 1) * sizeof (EFI_UDP4_FRAGMENT_DATA
));
800 if (Udp4TxData
== NULL
) {
801 return EFI_OUT_OF_RESOURCES
;
804 Udp4TxData
->FragmentCount
= FragCount
;
805 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentLength
= (UINT32
) *BufferSize
;
806 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentBuffer
= BufferPtr
;
807 DataLength
= (UINT32
) *BufferSize
;
809 if (FragCount
== 2) {
811 Udp4TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) *HeaderSize
;
812 Udp4TxData
->FragmentTable
[0].FragmentBuffer
= HeaderPtr
;
813 DataLength
+= (UINT32
) *HeaderSize
;
816 Udp4TxData
->GatewayAddress
= (EFI_IPv4_ADDRESS
*) GatewayIp
;
817 Udp4TxData
->UdpSessionData
= &Udp4Session
;
818 Udp4TxData
->DataLength
= DataLength
;
819 Token
.Packet
.TxData
= Udp4TxData
;
821 Status
= gBS
->CreateEvent (
828 if (EFI_ERROR (Status
)) {
832 Status
= Udp4
->Transmit (Udp4
, &Token
);
833 if (EFI_ERROR (Status
)) {
842 Status
= Token
.Status
;
846 if (Token
.Event
!= NULL
) {
847 gBS
->CloseEvent (Token
.Event
);
850 gBS
->FreePool (Udp4TxData
);
856 Validate IP packages by IP filter settings
858 @param PxeBcMode Pointer to EFI_PXEBC_MODE
860 @param Session Received UDP session
862 @retval TRUE The UDP package matches IP filters
864 @retval FLASE The UDP package doesn't matches IP filters
870 EFI_PXE_BASE_CODE_MODE
*PxeBcMode
,
871 EFI_UDP4_SESSION_DATA
*Session
875 EFI_IPv4_ADDRESS Ip4Address
;
876 EFI_IPv4_ADDRESS DestIp4Address
;
878 if (PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
882 CopyMem (&DestIp4Address
, &Session
->DestinationAddress
, sizeof (DestIp4Address
));
883 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) &&
884 IP4_IS_MULTICAST (NTOHL (EFI_IP4 (DestIp4Address
)))
889 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) &&
890 IP4_IS_LOCAL_BROADCAST (EFI_NTOHL (DestIp4Address
))
895 CopyMem (&Ip4Address
, &PxeBcMode
->StationIp
.v4
, sizeof (Ip4Address
));
896 if ((PxeBcMode
->IpFilter
.Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) &&
897 EFI_IP4_EQUAL (&PxeBcMode
->StationIp
.v4
, &DestIp4Address
)
902 for (Index
= 0; Index
< PxeBcMode
->IpFilter
.IpCnt
; ++Index
) {
903 CopyMem (&Ip4Address
, &PxeBcMode
->IpFilter
.IpList
[Index
].v4
, sizeof (Ip4Address
));
904 if (EFI_IP4_EQUAL (&Ip4Address
, &DestIp4Address
)) {
913 GC_NOTO: Add function description
915 @param This GC_NOTO: add argument
917 @param OpFlags GC_NOTO: add argument
919 @param DestIp GC_NOTO: add argument
921 @param DestPort GC_NOTO: add argument
923 @param SrcIp GC_NOTO: add argument
925 @param SrcPort GC_NOTO: add argument
927 @param HeaderSize GC_NOTO: add argument
929 @param HeaderPtr GC_NOTO: add argument
931 @param BufferSize GC_NOTO: add argument
933 @param BufferPtr GC_NOTO: add argument
936 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
938 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
940 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
942 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
944 @retval EFI_NOT_STARTED GC_NOTO: Add description for
946 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
953 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
955 IN OUT EFI_IP_ADDRESS
*DestIp
, OPTIONAL
956 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
, OPTIONAL
957 IN OUT EFI_IP_ADDRESS
*SrcIp
, OPTIONAL
958 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort
, OPTIONAL
959 IN UINTN
*HeaderSize
, OPTIONAL
960 IN VOID
*HeaderPtr
, OPTIONAL
961 IN OUT UINTN
*BufferSize
,
965 PXEBC_PRIVATE_DATA
*Private
;
966 EFI_PXE_BASE_CODE_MODE
*Mode
;
967 EFI_UDP4_PROTOCOL
*Udp4
;
968 EFI_UDP4_COMPLETION_TOKEN Token
;
969 EFI_UDP4_RECEIVE_DATA
*RxData
;
970 EFI_UDP4_SESSION_DATA
*Session
;
976 if (This
== NULL
|| DestIp
== NULL
|| DestPort
== NULL
) {
977 return EFI_INVALID_PARAMETER
;
980 if ((!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (DestPort
== NULL
)) ||
981 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (SrcIp
== NULL
)) ||
982 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && (SrcPort
== NULL
))) {
983 return EFI_INVALID_PARAMETER
;
986 if (((HeaderSize
!= NULL
) && (*HeaderSize
== 0)) || ((HeaderPtr
== NULL
) && (*HeaderSize
!= 0))) {
987 return EFI_INVALID_PARAMETER
;
990 if ((BufferSize
== NULL
) || ((BufferPtr
== NULL
) && (*BufferSize
!= 0))) {
991 return EFI_INVALID_PARAMETER
;
994 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
995 Mode
= Private
->PxeBc
.Mode
;
996 Udp4
= Private
->Udp4
;
998 if (!Mode
->Started
) {
999 return EFI_NOT_STARTED
;
1002 Status
= gBS
->CreateEvent (
1009 if (EFI_ERROR (Status
)) {
1010 return EFI_OUT_OF_RESOURCES
;
1014 Status
= Udp4
->Receive (Udp4
, &Token
);
1015 if (EFI_ERROR (Status
)) {
1022 Status
= EFI_TIMEOUT
;
1026 // check whether this packet matches the filters
1028 if (EFI_ERROR (Token
.Status
)){
1032 RxData
= Token
.Packet
.RxData
;
1033 Session
= &RxData
->UdpSession
;
1037 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
) {
1039 // Check UDP package by IP filter settings
1041 if (CheckIpByFilter (Mode
, Session
)) {
1048 // Match the destination ip of the received udp dgram
1050 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
) {
1053 if (DestIp
!= NULL
) {
1054 CopyMem (DestIp
, &Session
->DestinationAddress
, sizeof (EFI_IPv4_ADDRESS
));
1057 if (DestIp
!= NULL
) {
1058 if (EFI_IP4_EQUAL (DestIp
, &Session
->DestinationAddress
)) {
1062 if (EFI_IP4_EQUAL (&Private
->StationIp
, &Session
->DestinationAddress
)) {
1071 // Match the destination port of the received udp dgram
1073 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) {
1075 if (DestPort
!= NULL
) {
1076 *DestPort
= Session
->DestinationPort
;
1080 if (*DestPort
!= Session
->DestinationPort
) {
1088 // Match the source ip of the received udp dgram
1090 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) {
1092 if (SrcIp
!= NULL
) {
1093 CopyMem (SrcIp
, &Session
->SourceAddress
, sizeof (EFI_IPv4_ADDRESS
));
1097 if (!EFI_IP4_EQUAL (SrcIp
, &Session
->SourceAddress
)) {
1105 // Match the source port of the received udp dgram
1107 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
1109 if (SrcPort
!= NULL
) {
1110 *SrcPort
= Session
->SourcePort
;
1114 if (*SrcPort
!= Session
->SourcePort
) {
1124 if (HeaderSize
!= NULL
) {
1125 CopyLen
= MIN (*HeaderSize
, RxData
->DataLength
);
1126 CopyMem (HeaderPtr
, RxData
->FragmentTable
[0].FragmentBuffer
, CopyLen
);
1127 *HeaderSize
= CopyLen
;
1130 if (RxData
->DataLength
- CopyLen
> *BufferSize
) {
1132 Status
= EFI_BUFFER_TOO_SMALL
;
1135 *BufferSize
= RxData
->DataLength
- CopyLen
;
1136 CopyMem (BufferPtr
, (UINT8
*) RxData
->FragmentTable
[0].FragmentBuffer
+ CopyLen
, *BufferSize
);
1140 Status
= EFI_TIMEOUT
;
1144 // Recycle the RxData
1146 gBS
->SignalEvent (RxData
->RecycleSignal
);
1151 Udp4
->Cancel (Udp4
, &Token
);
1153 gBS
->CloseEvent (Token
.Event
);
1160 GC_NOTO: Add function description
1162 @param This GC_NOTO: add argument
1164 @param NewFilter GC_NOTO: add argument
1167 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1173 EfiPxeBcSetIpFilter (
1174 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1175 IN EFI_PXE_BASE_CODE_IP_FILTER
*NewFilter
1179 PXEBC_PRIVATE_DATA
*Private
;
1180 EFI_PXE_BASE_CODE_MODE
*Mode
;
1182 BOOLEAN PromiscuousNeed
;
1185 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL.\n"));
1186 return EFI_INVALID_PARAMETER
;
1189 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1190 Mode
= Private
->PxeBc
.Mode
;
1192 if (Private
== NULL
) {
1193 DEBUG ((EFI_D_ERROR
, "PXEBC_PRIVATE_DATA poiner == NULL.\n"));
1194 return EFI_INVALID_PARAMETER
;
1197 if (NewFilter
== NULL
) {
1198 DEBUG ((EFI_D_ERROR
, "IP Filter *NewFilter == NULL.\n"));
1199 return EFI_INVALID_PARAMETER
;
1202 if (!Mode
->Started
) {
1203 DEBUG ((EFI_D_ERROR
, "BC was not started.\n"));
1204 return EFI_NOT_STARTED
;
1207 PromiscuousNeed
= FALSE
;
1208 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1209 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter
->IpList
[Index
].v4
))) {
1211 // The IP is a broadcast address.
1213 DEBUG ((EFI_D_ERROR
, "There is broadcast address in NewFilter.\n"));
1214 return EFI_INVALID_PARAMETER
;
1216 if (Ip4IsUnicast (EFI_IP4 (NewFilter
->IpList
[Index
].v4
), 0) &&
1217 (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
)
1220 // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,
1221 // promiscuous mode is needed.
1223 PromiscuousNeed
= TRUE
;
1228 // Clear the UDP instance configuration, all joined groups will be left
1229 // during the operation.
1231 Private
->Udp4
->Configure (Private
->Udp4
, NULL
);
1232 Private
->Udp4CfgData
.AcceptPromiscuous
= FALSE
;
1233 Private
->Udp4CfgData
.AcceptBroadcast
= FALSE
;
1235 if (PromiscuousNeed
||
1236 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
||
1237 NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
1240 // Configure the udp4 filter to receive all packages
1242 Private
->Udp4CfgData
.AcceptPromiscuous
= TRUE
;
1245 // Configure the UDP instance with the new configuration.
1247 Status
= Private
->Udp4
->Configure (Private
->Udp4
, &Private
->Udp4CfgData
);
1248 if (EFI_ERROR (Status
)) {
1254 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
) {
1256 // Configure the udp4 filter to receive all broadcast packages
1258 Private
->Udp4CfgData
.AcceptBroadcast
= TRUE
;
1262 // Configure the UDP instance with the new configuration.
1264 Status
= Private
->Udp4
->Configure (Private
->Udp4
, &Private
->Udp4CfgData
);
1265 if (EFI_ERROR (Status
)) {
1269 if (NewFilter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1271 for (Index
= 0; Index
< NewFilter
->IpCnt
; ++Index
) {
1272 if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter
->IpList
[Index
].v4
))) {
1274 // Join the mutilcast group
1276 Status
= Private
->Udp4
->Groups (Private
->Udp4
, TRUE
, &NewFilter
->IpList
[Index
].v4
);
1277 if (EFI_ERROR (Status
)) {
1287 // Save the new filter.
1289 CopyMem (&Mode
->IpFilter
, NewFilter
, sizeof (Mode
->IpFilter
));
1296 GC_NOTO: Add function description
1298 @param This GC_NOTO: add argument
1300 @param IpAddr GC_NOTO: add argument
1302 @param MacAddr GC_NOTO: add argument
1305 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1312 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1313 IN EFI_IP_ADDRESS
* IpAddr
,
1314 IN EFI_MAC_ADDRESS
* MacAddr OPTIONAL
1317 PXEBC_PRIVATE_DATA
*Private
;
1318 EFI_PXE_BASE_CODE_MODE
*Mode
;
1320 EFI_MAC_ADDRESS TempMacAddr
;
1322 if (This
== NULL
|| IpAddr
== NULL
) {
1323 return EFI_INVALID_PARAMETER
;
1326 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1327 Mode
= Private
->PxeBc
.Mode
;
1329 if (!Mode
->Started
) {
1330 return EFI_NOT_STARTED
;
1333 if (!Private
->AddressIsOk
|| Mode
->UsingIpv6
) {
1335 // We can't resolve the IP address if we don't have a local address now.
1336 // Don't have ARP for IPv6.
1338 return EFI_INVALID_PARAMETER
;
1341 Status
= Private
->Arp
->Request (Private
->Arp
, &IpAddr
->v4
, NULL
, &TempMacAddr
);
1342 if (EFI_ERROR (Status
)) {
1346 if (MacAddr
!= NULL
) {
1347 CopyMem (MacAddr
, &TempMacAddr
, sizeof (EFI_MAC_ADDRESS
));
1356 GC_NOTO: Add function description
1358 @param This GC_NOTO: add argument
1360 @param NewAutoArp GC_NOTO: add argument
1362 @param NewSendGUID GC_NOTO: add argument
1364 @param NewTTL GC_NOTO: add argument
1366 @param NewToS GC_NOTO: add argument
1368 @param NewMakeCallback GC_NOTO: add argument
1371 @return GC_NOTO: add return values
1376 EfiPxeBcSetParameters (
1377 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1378 IN BOOLEAN
*NewAutoArp
, OPTIONAL
1379 IN BOOLEAN
*NewSendGUID
, OPTIONAL
1380 IN UINT8
*NewTTL
, OPTIONAL
1381 IN UINT8
*NewToS
, OPTIONAL
1382 IN BOOLEAN
*NewMakeCallback
// OPTIONAL
1385 PXEBC_PRIVATE_DATA
*Private
;
1386 EFI_PXE_BASE_CODE_MODE
*Mode
;
1389 Status
= EFI_SUCCESS
;
1392 Status
= EFI_INVALID_PARAMETER
;
1396 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1397 Mode
= Private
->PxeBc
.Mode
;
1399 if (NewSendGUID
!= NULL
&& *NewSendGUID
== TRUE
) {
1401 // FixMe, cann't locate SendGuid
1405 if (NewMakeCallback
!= NULL
&& *NewMakeCallback
== TRUE
) {
1407 Status
= gBS
->HandleProtocol (
1408 Private
->Controller
,
1409 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1410 (VOID
**) &Private
->PxeBcCallback
1412 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1414 Status
= EFI_INVALID_PARAMETER
;
1419 if (!Mode
->Started
) {
1420 Status
= EFI_NOT_STARTED
;
1424 if (NewMakeCallback
!= NULL
) {
1426 if (*NewMakeCallback
) {
1428 // Update the Callback protocol.
1430 Status
= gBS
->HandleProtocol (
1431 Private
->Controller
,
1432 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1433 (VOID
**) &Private
->PxeBcCallback
1436 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1437 Status
= EFI_INVALID_PARAMETER
;
1441 Private
->PxeBcCallback
= NULL
;
1444 Mode
->MakeCallbacks
= *NewMakeCallback
;
1447 if (NewAutoArp
!= NULL
) {
1448 Mode
->AutoArp
= *NewAutoArp
;
1451 if (NewSendGUID
!= NULL
) {
1452 Mode
->SendGUID
= *NewSendGUID
;
1455 if (NewTTL
!= NULL
) {
1456 Mode
->TTL
= *NewTTL
;
1459 if (NewToS
!= NULL
) {
1460 Mode
->ToS
= *NewToS
;
1469 GC_NOTO: Add function description
1471 @param This GC_NOTO: add argument
1473 @param NewStationIp GC_NOTO: add argument
1475 @param NewSubnetMask GC_NOTO: add argument
1478 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1480 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1482 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1484 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1486 @retval EFI_SUCCESS GC_NOTO: Add description for
1492 EfiPxeBcSetStationIP (
1493 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1494 IN EFI_IP_ADDRESS
* NewStationIp
, OPTIONAL
1495 IN EFI_IP_ADDRESS
* NewSubnetMask OPTIONAL
1498 PXEBC_PRIVATE_DATA
*Private
;
1499 EFI_PXE_BASE_CODE_MODE
*Mode
;
1500 EFI_ARP_CONFIG_DATA ArpConfigData
;
1503 return EFI_INVALID_PARAMETER
;
1506 if (NewStationIp
!= NULL
&& !Ip4IsUnicast (NTOHL (NewStationIp
->Addr
[0]), 0)) {
1507 return EFI_INVALID_PARAMETER
;
1510 if (NewSubnetMask
!= NULL
&& !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask
->Addr
[0]))) {
1511 return EFI_INVALID_PARAMETER
;
1514 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1515 Mode
= Private
->PxeBc
.Mode
;
1517 if (!Mode
->Started
) {
1518 return EFI_NOT_STARTED
;
1521 if (NewStationIp
!= NULL
) {
1522 Mode
->StationIp
= *NewStationIp
;
1525 if (NewSubnetMask
!= NULL
) {
1526 Mode
->SubnetMask
= *NewSubnetMask
;
1529 Private
->AddressIsOk
= TRUE
;
1531 if (!Mode
->UsingIpv6
) {
1533 // If in IPv4 mode, configure the corresponding ARP with this new
1534 // station IP address.
1536 ZeroMem (&ArpConfigData
, sizeof (EFI_ARP_CONFIG_DATA
));
1538 ArpConfigData
.SwAddressType
= 0x0800;
1539 ArpConfigData
.SwAddressLength
= sizeof (EFI_IPv4_ADDRESS
);
1540 ArpConfigData
.StationAddress
= &Private
->StationIp
.v4
;
1542 Private
->Arp
->Configure (Private
->Arp
, NULL
);
1543 Private
->Arp
->Configure (Private
->Arp
, &ArpConfigData
);
1551 GC_NOTO: Add function description
1553 @param This GC_NOTO: add argument
1555 @param NewDhcpDiscoverValid GC_NOTO: add argument
1557 @param NewDhcpAckReceived GC_NOTO: add argument
1559 @param NewProxyOfferReceived GC_NOTO: add argument
1561 @param NewPxeDiscoverValid GC_NOTO: add argument
1563 @param NewPxeReplyReceived GC_NOTO: add argument
1565 @param NewPxeBisReplyReceived GC_NOTO: add argument
1567 @param NewDhcpDiscover GC_NOTO: add argument
1569 @param NewDhcpAck GC_NOTO: add argument
1571 @param NewProxyOffer GC_NOTO: add argument
1573 @param NewPxeDiscover GC_NOTO: add argument
1575 @param NewPxeReply GC_NOTO: add argument
1577 @param NewPxeBisReply GC_NOTO: add argument
1580 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1582 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1584 @retval EFI_SUCCESS GC_NOTO: Add description for
1590 EfiPxeBcSetPackets (
1591 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1592 IN BOOLEAN
* NewDhcpDiscoverValid
, OPTIONAL
1593 IN BOOLEAN
* NewDhcpAckReceived
, OPTIONAL
1594 IN BOOLEAN
* NewProxyOfferReceived
, OPTIONAL
1595 IN BOOLEAN
* NewPxeDiscoverValid
, OPTIONAL
1596 IN BOOLEAN
* NewPxeReplyReceived
, OPTIONAL
1597 IN BOOLEAN
* NewPxeBisReplyReceived
, OPTIONAL
1598 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
1599 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
1600 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
1601 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
1602 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
1603 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
1606 PXEBC_PRIVATE_DATA
*Private
;
1607 EFI_PXE_BASE_CODE_MODE
*Mode
;
1610 return EFI_INVALID_PARAMETER
;
1613 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1614 Mode
= Private
->PxeBc
.Mode
;
1616 if (!Mode
->Started
) {
1617 return EFI_NOT_STARTED
;
1620 Private
->FileSize
= 0;
1622 if (NewDhcpDiscoverValid
!= NULL
) {
1623 Mode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
1626 if (NewDhcpAckReceived
!= NULL
) {
1627 Mode
->DhcpAckReceived
= *NewDhcpAckReceived
;
1630 if (NewProxyOfferReceived
!= NULL
) {
1631 Mode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
1634 if (NewPxeDiscoverValid
!= NULL
) {
1635 Mode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
1638 if (NewPxeReplyReceived
!= NULL
) {
1639 Mode
->PxeReplyReceived
= *NewPxeReplyReceived
;
1642 if (NewPxeBisReplyReceived
!= NULL
) {
1643 Mode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
1646 if (NewDhcpDiscover
!= NULL
) {
1647 CopyMem (&Mode
->DhcpDiscover
, NewDhcpDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1650 if (NewDhcpAck
!= NULL
) {
1651 CopyMem (&Mode
->DhcpAck
, NewDhcpAck
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1654 if (NewProxyOffer
!= NULL
) {
1655 CopyMem (&Mode
->ProxyOffer
, NewProxyOffer
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1658 if (NewPxeDiscover
!= NULL
) {
1659 CopyMem (&Mode
->PxeDiscover
, NewPxeDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1662 if (NewPxeReply
!= NULL
) {
1663 CopyMem (&Mode
->PxeReply
, NewPxeReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1666 if (NewPxeBisReply
!= NULL
) {
1667 CopyMem (&Mode
->PxeBisReply
, NewPxeBisReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1673 EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate
= {
1674 EFI_PXE_BASE_CODE_PROTOCOL_REVISION
,
1682 EfiPxeBcSetIpFilter
,
1684 EfiPxeBcSetParameters
,
1685 EfiPxeBcSetStationIP
,
1692 GC_NOTO: Add function description
1694 @param This GC_NOTO: add argument
1696 @param Function GC_NOTO: add argument
1698 @param Received GC_NOTO: add argument
1700 @param PacketLength GC_NOTO: add argument
1702 @param PacketPtr GC_NOTO: add argument
1705 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT GC_NOTO: Add description for
1707 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1709 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1711 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1713 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1717 EFI_PXE_BASE_CODE_CALLBACK_STATUS
1719 EfiPxeLoadFileCallback (
1720 IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL
* This
,
1721 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
1722 IN BOOLEAN Received
,
1723 IN UINT32 PacketLength
,
1724 IN EFI_PXE_BASE_CODE_PACKET
* PacketPtr OPTIONAL
1731 // Catch Ctrl-C or ESC to abort.
1733 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1735 if (!EFI_ERROR (Status
)) {
1737 if (Key
.ScanCode
== SCAN_ESC
|| Key
.UnicodeChar
== (0x1F & 'c')) {
1739 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT
;
1743 // No print if receive packet
1746 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
1749 // Print only for three functions
1753 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP
:
1755 // Print only for open MTFTP packets, not every MTFTP packets
1757 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
1758 if (PacketPtr
->Raw
[0x1C] != 0x00 || PacketPtr
->Raw
[0x1D] != 0x01) {
1759 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
1764 case EFI_PXE_BASE_CODE_FUNCTION_DHCP
:
1765 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
:
1769 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
1772 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
1774 // Print '.' when transmit a packet
1780 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
1783 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate
= {
1784 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION
,
1785 EfiPxeLoadFileCallback
1790 GC_NOTO: Add function description
1792 @param Private GC_NOTO: add argument
1794 @param BufferSize GC_NOTO: add argument
1796 @param Buffer GC_NOTO: add argument
1799 @return GC_NOTO: add return values
1804 IN PXEBC_PRIVATE_DATA
*Private
,
1805 IN OUT UINT64
*BufferSize
,
1809 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
1810 EFI_PXE_BASE_CODE_MODE
*Mode
;
1816 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
1819 PxeBc
= &Private
->PxeBc
;
1821 Type
= EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
;
1822 Layer
= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
;
1827 Status
= PxeBc
->Dhcp (PxeBc
, TRUE
);
1828 if (EFI_ERROR (Status
)) {
1833 // Select a boot server
1835 Status
= PxeBcSelectBootPrompt (Private
);
1837 if (Status
== EFI_SUCCESS
) {
1838 Status
= PxeBcSelectBootMenu (Private
, &Type
, TRUE
);
1839 } else if (Status
== EFI_TIMEOUT
) {
1840 Status
= PxeBcSelectBootMenu (Private
, &Type
, FALSE
);
1843 if (!EFI_ERROR (Status
)) {
1845 if (Type
== EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
) {
1847 // Local boot(PXE bootstrap server) need abort
1852 UseBis
= (BOOLEAN
) (Mode
->BisSupported
&& Mode
->BisDetected
);
1853 Status
= PxeBc
->Discover (PxeBc
, Type
, &Layer
, UseBis
, NULL
);
1854 if (EFI_ERROR (Status
)) {
1863 // Get bootfile name and (m)tftp server ip addresss
1865 if (Mode
->PxeReplyReceived
) {
1866 Packet
= &Private
->PxeReply
;
1867 } else if (Mode
->ProxyOfferReceived
) {
1868 Packet
= &Private
->ProxyOffer
;
1870 Packet
= &Private
->Dhcp4Ack
;
1873 CopyMem (&Private
->ServerIp
, &Packet
->Packet
.Offer
.Dhcp4
.Header
.ServerAddr
, sizeof (EFI_IPv4_ADDRESS
));
1874 if (Private
->ServerIp
.Addr
[0] == 0) {
1876 // next server ip address is zero, use option 54 instead
1880 Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_SERVER_ID
]->Data
,
1881 sizeof (EFI_IPv4_ADDRESS
)
1885 ASSERT (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
);
1890 Private
->BootFileName
= (CHAR8
*) (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
]->Data
);
1892 if (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
] != NULL
) {
1894 // Already have the bootfile length option, compute the file size
1896 CopyMem (&Value
, Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
]->Data
, sizeof (Value
));
1897 Value
= NTOHS (Value
);
1898 *BufferSize
= 512 * Value
;
1899 Status
= EFI_BUFFER_TOO_SMALL
;
1902 // Get the bootfile size from tftp
1904 Status
= PxeBc
->Mtftp (
1906 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
,
1912 (UINT8
*) Private
->BootFileName
,
1918 Private
->FileSize
= (UINTN
) *BufferSize
;
1925 GC_NOTO: Add function description
1927 @param This GC_NOTO: add argument
1929 @param FilePath GC_NOTO: add argument
1931 @param BootPolicy GC_NOTO: add argument
1933 @param BufferSize GC_NOTO: add argument
1935 @param Buffer GC_NOTO: add argument
1938 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1940 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1947 IN EFI_LOAD_FILE_PROTOCOL
* This
,
1948 IN EFI_DEVICE_PATH_PROTOCOL
* FilePath
,
1949 IN BOOLEAN BootPolicy
,
1950 IN OUT UINTN
*BufferSize
,
1951 IN VOID
*Buffer OPTIONAL
1954 PXEBC_PRIVATE_DATA
*Private
;
1955 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
1956 BOOLEAN NewMakeCallback
;
1961 Private
= PXEBC_PRIVATE_DATA_FROM_LOADFILE (This
);
1962 PxeBc
= &Private
->PxeBc
;
1963 NewMakeCallback
= FALSE
;
1965 Status
= EFI_DEVICE_ERROR
;
1967 if (This
== NULL
|| BufferSize
== NULL
) {
1969 return EFI_INVALID_PARAMETER
;
1973 // Only support BootPolicy
1976 return EFI_UNSUPPORTED
;
1979 Status
= PxeBc
->Start (PxeBc
, FALSE
);
1980 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
1984 Status
= gBS
->HandleProtocol (
1985 Private
->Controller
,
1986 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1987 (VOID
**) &Private
->PxeBcCallback
1989 if (Status
== EFI_UNSUPPORTED
) {
1991 CopyMem (&Private
->LoadFileCallback
, &mPxeBcCallBackTemplate
, sizeof (Private
->LoadFileCallback
));
1993 Status
= gBS
->InstallProtocolInterface (
1994 &Private
->Controller
,
1995 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1996 EFI_NATIVE_INTERFACE
,
1997 &Private
->LoadFileCallback
2000 NewMakeCallback
= (BOOLEAN
) (Status
== EFI_SUCCESS
);
2002 Status
= PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2003 if (EFI_ERROR (Status
)) {
2004 PxeBc
->Stop (PxeBc
);
2009 if (Private
->FileSize
== 0) {
2011 Status
= DiscoverBootFile (Private
, &TmpBufSize
, Buffer
);
2013 if (sizeof (UINTN
) < sizeof (UINT64
) && (TmpBufSize
> 0xFFFFFFFF)) {
2014 Status
= EFI_DEVICE_ERROR
;
2016 *BufferSize
= (UINTN
) TmpBufSize
;
2018 } else if (Buffer
== NULL
) {
2019 *BufferSize
= Private
->FileSize
;
2020 Status
= EFI_BUFFER_TOO_SMALL
;
2023 // Download the file.
2025 TmpBufSize
= (UINT64
) (*BufferSize
);
2026 Status
= PxeBc
->Mtftp (
2028 EFI_PXE_BASE_CODE_TFTP_READ_FILE
,
2034 (UINT8
*) Private
->BootFileName
,
2040 // If we added a callback protocol, now is the time to remove it.
2042 if (NewMakeCallback
) {
2044 NewMakeCallback
= FALSE
;
2046 PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
2048 gBS
->UninstallProtocolInterface (
2049 Private
->Controller
,
2050 &gEfiPxeBaseCodeCallbackProtocolGuid
,
2051 &Private
->LoadFileCallback
2055 // Check download status
2062 case EFI_BUFFER_TOO_SMALL
:
2063 if (Buffer
!= NULL
) {
2064 AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
2070 case EFI_DEVICE_ERROR
:
2071 AsciiPrint ("PXE-E07: Network device error.\n");
2074 case EFI_OUT_OF_RESOURCES
:
2075 AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
2079 AsciiPrint ("PXE-E12: Could not detect network connection.\n");
2082 case EFI_NO_RESPONSE
:
2083 AsciiPrint ("PXE-E16: No offer received.\n");
2087 AsciiPrint ("PXE-E18: Server response timeout.\n");
2091 AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
2094 case EFI_ICMP_ERROR
:
2095 AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
2098 case EFI_TFTP_ERROR
:
2099 AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
2103 AsciiPrint ("PXE-E99: Unexpected network error.\n");
2107 PxeBc
->Stop (PxeBc
);
2112 EFI_LOAD_FILE_PROTOCOL mLoadFileProtocolTemplate
= { EfiPxeLoadFile
};