3 Copyright (c) 2007, 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
;
131 Private
->Udp4
->Configure (Private
->Udp4
, NULL
);
133 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
134 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
136 Private
->FileSize
= 0;
143 GC_NOTO: Add function description
145 @param This GC_NOTO: add argument
147 @param SortOffers GC_NOTO: add argument
150 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
152 @retval EFI_NOT_STARTED GC_NOTO: Add description for
159 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
160 IN BOOLEAN SortOffers
163 PXEBC_PRIVATE_DATA
*Private
;
164 EFI_PXE_BASE_CODE_MODE
*Mode
;
165 EFI_DHCP4_PROTOCOL
*Dhcp4
;
166 EFI_DHCP4_CONFIG_DATA Dhcp4CfgData
;
167 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
168 EFI_DHCP4_PACKET_OPTION
*OptList
[PXEBC_DHCP4_MAX_OPTION_NUM
];
170 UINT32 DiscoverTimeout
;
175 return EFI_INVALID_PARAMETER
;
178 Status
= EFI_SUCCESS
;
179 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
180 Mode
= Private
->PxeBc
.Mode
;
181 Dhcp4
= Private
->Dhcp4
;
182 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
183 Private
->SortOffers
= SortOffers
;
185 if (!Mode
->Started
) {
186 return EFI_NOT_STARTED
;
189 // Initialize the DHCP options and build the option list
191 OptCount
= PxeBcBuildDhcpOptions (Private
, OptList
, TRUE
);
194 // Set the DHCP4 config data.
196 NetZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
197 Dhcp4CfgData
.OptionCount
= OptCount
;
198 Dhcp4CfgData
.OptionList
= OptList
;
199 Dhcp4CfgData
.Dhcp4Callback
= PxeBcDhcpCallBack
;
200 Dhcp4CfgData
.CallbackContext
= Private
;
201 Dhcp4CfgData
.DiscoverTryCount
= 1;
202 Dhcp4CfgData
.DiscoverTimeout
= &DiscoverTimeout
;
204 for (Index
= 0; Index
< PXEBC_DHCP4_DISCOVER_RETRIES
; Index
++) {
206 // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.
208 DiscoverTimeout
= (PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT
<< Index
);
210 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
211 if (EFI_ERROR (Status
)) {
215 // Zero those arrays to record the varies numbers of DHCP OFFERS.
217 Private
->NumOffers
= 0;
218 Private
->BootpIndex
= 0;
219 NetZeroMem (Private
->ServerCount
, sizeof (Private
->ServerCount
));
220 NetZeroMem (Private
->ProxyIndex
, sizeof (Private
->ProxyIndex
));
222 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
223 if (EFI_ERROR (Status
)) {
224 if (Status
== EFI_TIMEOUT
) {
226 // If no response is received or all received offers don't match
227 // the PXE boot requirements, EFI_TIMEOUT will be returned.
232 // Other error status means the DHCP really fails.
237 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
238 if (EFI_ERROR (Status
)) {
242 ASSERT (Dhcp4Mode
.State
== Dhcp4Bound
);
244 NetCopyMem (&Private
->StationIp
, &Dhcp4Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
245 NetCopyMem (&Private
->SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
246 NetCopyMem (&Private
->GatewayIp
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
249 // Check the selected offer to see whether BINL is required, if no or BINL is
250 // finished, set the various Mode members.
252 Status
= PxeBcCheckSelectedOffer (Private
);
253 if (!EFI_ERROR (Status
)) {
258 if (EFI_ERROR (Status
)) {
260 Dhcp4
->Configure (Dhcp4
, NULL
);
263 // Remove the previously configured option list and callback function
265 NetZeroMem (&Dhcp4CfgData
, sizeof (EFI_DHCP4_CONFIG_DATA
));
266 Dhcp4
->Configure (Dhcp4
, &Dhcp4CfgData
);
268 Private
->AddressIsOk
= TRUE
;
276 GC_NOTO: Add function description
278 @param This GC_NOTO: add argument
280 @param Type GC_NOTO: add argument
282 @param Layer GC_NOTO: add argument
284 @param UseBis GC_NOTO: add argument
286 @param Info GC_NOTO: add argument
289 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
291 @retval EFI_NOT_STARTED GC_NOTO: Add description for
293 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
295 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
297 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
299 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
306 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
310 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*Info OPTIONAL
313 PXEBC_PRIVATE_DATA
*Private
;
314 EFI_PXE_BASE_CODE_MODE
*Mode
;
315 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
316 EFI_PXE_BASE_CODE_SRVLIST
*SrvList
;
317 EFI_PXE_BASE_CODE_SRVLIST DefaultSrvList
;
318 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
319 PXEBC_VENDOR_OPTION
*VendorOpt
;
322 PXEBC_BOOT_SVR_ENTRY
*BootSvrEntry
;
325 return EFI_INVALID_PARAMETER
;
328 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
329 Mode
= Private
->PxeBc
.Mode
;
332 Status
= EFI_DEVICE_ERROR
;
333 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
335 if (!Private
->AddressIsOk
) {
336 return EFI_INVALID_PARAMETER
;
339 if (!Mode
->Started
) {
340 return EFI_NOT_STARTED
;
344 // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
345 // use the previous setting;
346 // If info isn't offered,
347 // use the cached DhcpAck and ProxyOffer packets.
349 if (*Layer
!= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
) {
351 if (!Mode
->PxeDiscoverValid
|| !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
353 return EFI_INVALID_PARAMETER
;
356 DefaultInfo
.IpCnt
= 1;
357 DefaultInfo
.UseUCast
= TRUE
;
359 DefaultSrvList
.Type
= Type
;
360 DefaultSrvList
.AcceptAnyResponse
= FALSE
;
361 DefaultSrvList
.IpAddr
.Addr
[0] = Private
->ServerIp
.Addr
[0];
363 SrvList
= &DefaultSrvList
;
365 } else if (Info
== NULL
) {
367 // Create info by the cached packet before
369 Packet
= (Mode
->ProxyOfferReceived
) ? &Private
->ProxyOffer
: &Private
->Dhcp4Ack
;
370 VendorOpt
= &Packet
->PxeVendorOption
;
372 if (!Mode
->DhcpAckReceived
|| !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt
->BitMap
)) {
374 // Address is not acquired or no discovery options.
376 return EFI_INVALID_PARAMETER
;
379 DefaultInfo
.UseMCast
= (BOOLEAN
)!IS_DISABLE_MCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
380 DefaultInfo
.UseBCast
= (BOOLEAN
)!IS_DISABLE_BCAST_DISCOVER (VendorOpt
->DiscoverCtrl
);
381 DefaultInfo
.MustUseList
= (BOOLEAN
) IS_ENABLE_USE_SERVER_LIST (VendorOpt
->DiscoverCtrl
);
382 DefaultInfo
.UseUCast
= DefaultInfo
.MustUseList
;
384 if (DefaultInfo
.UseMCast
) {
386 // Get the multicast discover ip address from vendor option.
388 NetCopyMem (&DefaultInfo
.ServerMCastIp
.Addr
, &VendorOpt
->DiscoverMcastIp
, sizeof (EFI_IPv4_ADDRESS
));
391 DefaultInfo
.IpCnt
= 0;
393 if (DefaultInfo
.MustUseList
) {
394 BootSvrEntry
= VendorOpt
->BootSvr
;
395 Status
= EFI_INVALID_PARAMETER
;
397 while (((UINT8
) (BootSvrEntry
- VendorOpt
->BootSvr
)) < VendorOpt
->BootSvrLen
) {
399 if (BootSvrEntry
->Type
== HTONS (Type
)) {
400 Status
= EFI_SUCCESS
;
404 BootSvrEntry
= GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry
);
407 if (EFI_ERROR (Status
)) {
411 DefaultInfo
.IpCnt
= BootSvrEntry
->IpCnt
;
417 SrvList
= Info
->SrvList
;
419 if (!SrvList
[0].AcceptAnyResponse
) {
421 for (Index
= 1; Index
< Info
->IpCnt
; Index
++) {
422 if (SrvList
[Index
].AcceptAnyResponse
) {
427 if (Index
!= Info
->IpCnt
) {
428 return EFI_INVALID_PARAMETER
;
433 if ((!Info
->UseUCast
&& !Info
->UseBCast
&& !Info
->UseMCast
) || (Info
->MustUseList
&& Info
->IpCnt
== 0)) {
435 return EFI_INVALID_PARAMETER
;
438 // Execute discover by UniCast/BroadCast/MultiCast
440 if (Info
->UseUCast
) {
442 for (Index
= 0; Index
< Info
->IpCnt
; Index
++) {
444 if (BootSvrEntry
== NULL
) {
445 Private
->ServerIp
.Addr
[0] = SrvList
[Index
].IpAddr
.Addr
[0];
447 NetCopyMem (&Private
->ServerIp
, &BootSvrEntry
->IpAddr
[Index
], sizeof (EFI_IPv4_ADDRESS
));
450 Status
= PxeBcDiscvBootService (
455 &SrvList
[Index
].IpAddr
,
459 &Private
->PxeReply
.Packet
.Ack
463 } else if (Info
->UseMCast
) {
465 Status
= PxeBcDiscvBootService (
470 &Info
->ServerMCastIp
,
474 &Private
->PxeReply
.Packet
.Ack
477 } else if (Info
->UseBCast
) {
479 Status
= PxeBcDiscvBootService (
488 &Private
->PxeReply
.Packet
.Ack
492 if (EFI_ERROR (Status
) || !Mode
->PxeReplyReceived
|| (!Mode
->PxeBisReplyReceived
&& UseBis
)) {
494 Status
= EFI_DEVICE_ERROR
;
496 PxeBcParseCachedDhcpPacket (&Private
->PxeReply
);
499 if (Mode
->PxeBisReplyReceived
) {
500 NetCopyMem (&Private
->ServerIp
, &Mode
->PxeReply
.Dhcpv4
.BootpSiAddr
, sizeof (EFI_IPv4_ADDRESS
));
508 GC_NOTO: Add function description
510 @param This GC_NOTO: add argument
512 @param Operation GC_NOTO: add argument
514 @param BufferPtr GC_NOTO: add argument
516 @param Overwrite GC_NOTO: add argument
518 @param BufferSize GC_NOTO: add argument
520 @param BlockSize GC_NOTO: add argument
522 @param ServerIp GC_NOTO: add argument
524 @param Filename GC_NOTO: add argument
526 @param Info GC_NOTO: add argument
528 @param DontUseBuffer GC_NOTO: add argument
531 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
538 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
539 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
540 IN OUT VOID
*BufferPtr
,
541 IN BOOLEAN Overwrite
,
542 IN OUT UINT64
*BufferSize
,
543 IN UINTN
*BlockSize OPTIONAL
,
544 IN EFI_IP_ADDRESS
*ServerIp
,
546 IN EFI_PXE_BASE_CODE_MTFTP_INFO
*Info OPTIONAL
,
547 IN BOOLEAN DontUseBuffer
550 PXEBC_PRIVATE_DATA
*Private
;
551 EFI_MTFTP4_CONFIG_DATA Mtftp4Config
;
554 if ((This
== NULL
) ||
555 (Filename
== NULL
) ||
556 (BufferSize
== NULL
) ||
557 ((ServerIp
== NULL
) || !Ip4IsUnicast (NTOHL (ServerIp
->Addr
[0]), 0)) ||
558 ((BufferPtr
== NULL
) && DontUseBuffer
) ||
559 ((BlockSize
!= NULL
) && (*BlockSize
< 512))) {
561 return EFI_INVALID_PARAMETER
;
564 Status
= EFI_DEVICE_ERROR
;
565 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
567 Mtftp4Config
.UseDefaultSetting
= FALSE
;
568 Mtftp4Config
.TimeoutValue
= PXEBC_MTFTP_TIMEOUT
;
569 Mtftp4Config
.TryCount
= PXEBC_MTFTP_RETRIES
;
571 NetCopyMem (&Mtftp4Config
.StationIp
, &Private
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
572 NetCopyMem (&Mtftp4Config
.SubnetMask
, &Private
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
573 NetCopyMem (&Mtftp4Config
.GatewayIp
, &Private
->GatewayIp
, sizeof (EFI_IPv4_ADDRESS
));
574 NetCopyMem (&Mtftp4Config
.ServerIp
, ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
578 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
:
580 Status
= PxeBcTftpGetFileSize (
588 if (!EFI_ERROR (Status
)) {
589 Status
= EFI_BUFFER_TOO_SMALL
;
594 case EFI_PXE_BASE_CODE_TFTP_READ_FILE
:
596 Status
= PxeBcTftpReadFile (
608 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
:
610 Status
= PxeBcTftpWriteFile (
622 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY
:
624 Status
= PxeBcTftpReadDirectory (
636 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE
:
637 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE
:
638 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY
:
639 Status
= EFI_UNSUPPORTED
;
644 Status
= EFI_INVALID_PARAMETER
;
653 GC_NOTO: Add function description
655 @param This GC_NOTO: add argument
657 @param OpFlags GC_NOTO: add argument
659 @param DestIp GC_NOTO: add argument
661 @param DestPort GC_NOTO: add argument
663 @param GatewayIp GC_NOTO: add argument
665 @param SrcIp GC_NOTO: add argument
667 @param SrcPort GC_NOTO: add argument
669 @param HeaderSize GC_NOTO: add argument
671 @param HeaderPtr GC_NOTO: add argument
673 @param BufferSize GC_NOTO: add argument
675 @param BufferPtr GC_NOTO: add argument
678 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
680 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
682 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
684 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
686 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
693 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
695 IN EFI_IP_ADDRESS
*DestIp
,
696 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
,
697 IN EFI_IP_ADDRESS
*GatewayIp OPTIONAL
,
698 IN EFI_IP_ADDRESS
*SrcIp OPTIONAL
,
699 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort OPTIONAL
,
700 IN UINTN
*HeaderSize OPTIONAL
,
701 IN VOID
*HeaderPtr OPTIONAL
,
702 IN UINTN
*BufferSize
,
706 PXEBC_PRIVATE_DATA
*Private
;
707 EFI_UDP4_PROTOCOL
*Udp4
;
708 EFI_UDP4_COMPLETION_TOKEN Token
;
709 EFI_UDP4_TRANSMIT_DATA
*Udp4TxData
;
712 EFI_UDP4_SESSION_DATA Udp4Session
;
715 UINT16 RandomSrcPort
;
719 if ((This
== NULL
) || (DestIp
== NULL
) || (DestPort
== NULL
)) {
720 return EFI_INVALID_PARAMETER
;
723 if ((GatewayIp
!= NULL
) && !Ip4IsUnicast (NTOHL (GatewayIp
->Addr
[0]), 0)) {
725 // Gateway is provided but it's not a unicast IP address.
727 return EFI_INVALID_PARAMETER
;
730 if ((HeaderSize
!= NULL
) && ((*HeaderSize
== 0) || (HeaderPtr
== NULL
))) {
732 // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
735 return EFI_INVALID_PARAMETER
;
738 if ((BufferSize
== NULL
) || ((*BufferSize
!= 0) && (BufferPtr
== NULL
))) {
739 return EFI_INVALID_PARAMETER
;
742 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
743 Udp4
= Private
->Udp4
;
745 if (!Private
->AddressIsOk
&& (SrcIp
== NULL
)) {
746 return EFI_INVALID_PARAMETER
;
750 SrcIp
= &Private
->StationIp
;
752 if (GatewayIp
== NULL
) {
753 GatewayIp
= &Private
->GatewayIp
;
757 if ((SrcPort
== NULL
) || (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
)) {
758 RandomSrcPort
= (UINT16
) (NET_RANDOM (NetRandomInitSeed ()) % 10000 + 1024);
760 if (SrcPort
== NULL
) {
762 SrcPort
= &RandomSrcPort
;
765 *SrcPort
= RandomSrcPort
;
769 ZeroMem (&Token
, sizeof (EFI_UDP4_COMPLETION_TOKEN
));
770 ZeroMem (&Udp4Session
, sizeof (EFI_UDP4_SESSION_DATA
));
772 NetCopyMem (&Udp4Session
.DestinationAddress
, DestIp
, sizeof (EFI_IPv4_ADDRESS
));
773 Udp4Session
.DestinationPort
= *DestPort
;
774 NetCopyMem (&Udp4Session
.SourceAddress
, SrcIp
, sizeof (EFI_IPv4_ADDRESS
));
775 Udp4Session
.SourcePort
= *SrcPort
;
777 FragCount
= (HeaderSize
!= NULL
) ? 2 : 1;
778 Udp4TxData
= (EFI_UDP4_TRANSMIT_DATA
*) NetAllocatePool (sizeof (EFI_UDP4_TRANSMIT_DATA
) + (FragCount
- 1) * sizeof (EFI_UDP4_FRAGMENT_DATA
));
779 if (Udp4TxData
== NULL
) {
780 return EFI_OUT_OF_RESOURCES
;
783 Udp4TxData
->FragmentCount
= FragCount
;
784 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentLength
= (UINT32
) *BufferSize
;
785 Udp4TxData
->FragmentTable
[FragCount
- 1].FragmentBuffer
= BufferPtr
;
786 DataLength
= (UINT32
) *BufferSize
;
788 if (FragCount
== 2) {
790 Udp4TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) *HeaderSize
;
791 Udp4TxData
->FragmentTable
[0].FragmentBuffer
= HeaderPtr
;
792 DataLength
+= (UINT32
) *HeaderSize
;
795 Udp4TxData
->GatewayAddress
= (EFI_IPv4_ADDRESS
*) GatewayIp
;
796 Udp4TxData
->UdpSessionData
= &Udp4Session
;
797 Udp4TxData
->DataLength
= DataLength
;
798 Token
.Packet
.TxData
= Udp4TxData
;
800 Status
= gBS
->CreateEvent (
807 if (EFI_ERROR (Status
)) {
811 Status
= Udp4
->Transmit (Udp4
, &Token
);
812 if (EFI_ERROR (Status
)) {
821 Status
= Token
.Status
;
825 if (Token
.Event
!= NULL
) {
826 gBS
->CloseEvent (Token
.Event
);
829 NetFreePool (Udp4TxData
);
836 GC_NOTO: Add function description
838 @param This GC_NOTO: add argument
840 @param OpFlags GC_NOTO: add argument
842 @param DestIp GC_NOTO: add argument
844 @param DestPort GC_NOTO: add argument
846 @param SrcIp GC_NOTO: add argument
848 @param SrcPort GC_NOTO: add argument
850 @param HeaderSize GC_NOTO: add argument
852 @param HeaderPtr GC_NOTO: add argument
854 @param BufferSize GC_NOTO: add argument
856 @param BufferPtr GC_NOTO: add argument
859 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
861 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
863 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
865 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
867 @retval EFI_NOT_STARTED GC_NOTO: Add description for
869 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
876 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
878 IN OUT EFI_IP_ADDRESS
*DestIp
, OPTIONAL
879 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
, OPTIONAL
880 IN OUT EFI_IP_ADDRESS
*SrcIp
, OPTIONAL
881 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort
, OPTIONAL
882 IN UINTN
*HeaderSize
, OPTIONAL
883 IN VOID
*HeaderPtr
, OPTIONAL
884 IN OUT UINTN
*BufferSize
,
888 PXEBC_PRIVATE_DATA
*Private
;
889 EFI_PXE_BASE_CODE_MODE
*Mode
;
890 EFI_UDP4_PROTOCOL
*Udp4
;
891 EFI_UDP4_COMPLETION_TOKEN Token
;
892 EFI_UDP4_RECEIVE_DATA
*RxData
;
893 EFI_UDP4_SESSION_DATA
*Session
;
899 if (This
== NULL
|| DestIp
== NULL
|| DestPort
== NULL
) {
900 return EFI_INVALID_PARAMETER
;
903 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
) {
904 return EFI_UNSUPPORTED
;
907 if ((!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (DestPort
== NULL
)) ||
908 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && (SrcIp
== NULL
)) ||
909 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && (SrcPort
== NULL
))) {
910 return EFI_INVALID_PARAMETER
;
913 if (((HeaderSize
!= NULL
) && (*HeaderSize
== 0)) || ((HeaderPtr
== NULL
) && (*HeaderSize
!= 0))) {
914 return EFI_INVALID_PARAMETER
;
917 if ((BufferSize
== NULL
) || ((BufferPtr
== NULL
) && (*BufferSize
!= 0))) {
918 return EFI_INVALID_PARAMETER
;
921 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
922 Mode
= Private
->PxeBc
.Mode
;
923 Udp4
= Private
->Udp4
;
925 if (!Mode
->Started
) {
926 return EFI_NOT_STARTED
;
929 Status
= gBS
->CreateEvent (
936 if (EFI_ERROR (Status
)) {
937 return EFI_OUT_OF_RESOURCES
;
941 Status
= Udp4
->Receive (Udp4
, &Token
);
942 if (EFI_ERROR (Status
)) {
949 Status
= EFI_TIMEOUT
;
953 // check whether this packet matches the filters
955 if (EFI_ERROR (Token
.Status
)){
959 RxData
= Token
.Packet
.RxData
;
960 Session
= &RxData
->UdpSession
;
965 // Match the destination ip of the received udp dgram
967 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
) {
970 if (DestIp
!= NULL
) {
971 NetCopyMem (DestIp
, &Session
->DestinationAddress
, sizeof (EFI_IPv4_ADDRESS
));
974 if (DestIp
!= NULL
) {
975 if (EFI_IP4_EQUAL (DestIp
, &Session
->DestinationAddress
)) {
979 if (EFI_IP4_EQUAL (&Private
->StationIp
, &Session
->DestinationAddress
)) {
987 // Match the destination port of the received udp dgram
989 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) {
991 if (DestPort
!= NULL
) {
992 *DestPort
= Session
->DestinationPort
;
996 if (*DestPort
!= Session
->DestinationPort
) {
1004 // Match the source ip of the received udp dgram
1006 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) {
1008 if (SrcIp
!= NULL
) {
1009 NetCopyMem (SrcIp
, &Session
->SourceAddress
, sizeof (EFI_IPv4_ADDRESS
));
1013 if (!EFI_IP4_EQUAL (SrcIp
, &Session
->SourceAddress
)) {
1021 // Match the source port of the received udp dgram
1023 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
1025 if (SrcPort
!= NULL
) {
1026 *SrcPort
= Session
->SourcePort
;
1030 if (*SrcPort
!= Session
->SourcePort
) {
1040 if (HeaderSize
!= NULL
) {
1041 CopyLen
= MIN (*HeaderSize
, RxData
->DataLength
);
1042 NetCopyMem (HeaderPtr
, RxData
->FragmentTable
[0].FragmentBuffer
, CopyLen
);
1043 *HeaderSize
= CopyLen
;
1046 if (RxData
->DataLength
- CopyLen
> *BufferSize
) {
1048 Status
= EFI_BUFFER_TOO_SMALL
;
1051 *BufferSize
= RxData
->DataLength
- CopyLen
;
1052 NetCopyMem (BufferPtr
, (UINT8
*) RxData
->FragmentTable
[0].FragmentBuffer
+ CopyLen
, *BufferSize
);
1056 Status
= EFI_TIMEOUT
;
1060 // Recycle the RxData
1062 gBS
->SignalEvent (RxData
->RecycleSignal
);
1067 Udp4
->Cancel (Udp4
, &Token
);
1069 gBS
->CloseEvent (Token
.Event
);
1076 GC_NOTO: Add function description
1078 @param This GC_NOTO: add argument
1080 @param NewFilter GC_NOTO: add argument
1083 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1089 EfiPxeBcSetIpFilter (
1090 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1091 IN EFI_PXE_BASE_CODE_IP_FILTER
*NewFilter
1094 return EFI_UNSUPPORTED
;
1099 GC_NOTO: Add function description
1101 @param This GC_NOTO: add argument
1103 @param IpAddr GC_NOTO: add argument
1105 @param MacAddr GC_NOTO: add argument
1108 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1115 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1116 IN EFI_IP_ADDRESS
* IpAddr
,
1117 IN EFI_MAC_ADDRESS
* MacAddr OPTIONAL
1120 return EFI_UNSUPPORTED
;
1125 GC_NOTO: Add function description
1127 @param This GC_NOTO: add argument
1129 @param NewAutoArp GC_NOTO: add argument
1131 @param NewSendGUID GC_NOTO: add argument
1133 @param NewTTL GC_NOTO: add argument
1135 @param NewToS GC_NOTO: add argument
1137 @param NewMakeCallback GC_NOTO: add argument
1140 @return GC_NOTO: add return values
1145 EfiPxeBcSetParameters (
1146 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1147 IN BOOLEAN
*NewAutoArp
, OPTIONAL
1148 IN BOOLEAN
*NewSendGUID
, OPTIONAL
1149 IN UINT8
*NewTTL
, OPTIONAL
1150 IN UINT8
*NewToS
, OPTIONAL
1151 IN BOOLEAN
*NewMakeCallback
// OPTIONAL
1154 PXEBC_PRIVATE_DATA
*Private
;
1155 EFI_PXE_BASE_CODE_MODE
*Mode
;
1158 Status
= EFI_SUCCESS
;
1161 Status
= EFI_INVALID_PARAMETER
;
1165 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1166 Mode
= Private
->PxeBc
.Mode
;
1168 if (NewSendGUID
!= NULL
&& *NewSendGUID
== TRUE
) {
1170 // FixMe, cann't locate SendGuid
1174 if (NewMakeCallback
!= NULL
&& *NewMakeCallback
== TRUE
) {
1176 Status
= gBS
->HandleProtocol (
1177 Private
->Controller
,
1178 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1179 (VOID
**) &Private
->PxeBcCallback
1181 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1183 Status
= EFI_INVALID_PARAMETER
;
1188 if (!Mode
->Started
) {
1189 Status
= EFI_NOT_STARTED
;
1193 if (NewMakeCallback
!= NULL
) {
1195 if (*NewMakeCallback
) {
1197 // Update the Callback protocol.
1199 Status
= gBS
->HandleProtocol (
1200 Private
->Controller
,
1201 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1202 (VOID
**) &Private
->PxeBcCallback
1205 if (EFI_ERROR (Status
) || (Private
->PxeBcCallback
->Callback
== NULL
)) {
1206 Status
= EFI_INVALID_PARAMETER
;
1210 Private
->PxeBcCallback
= NULL
;
1213 Mode
->MakeCallbacks
= *NewMakeCallback
;
1216 if (NewAutoArp
!= NULL
) {
1217 Mode
->AutoArp
= *NewAutoArp
;
1220 if (NewSendGUID
!= NULL
) {
1221 Mode
->SendGUID
= *NewSendGUID
;
1224 if (NewTTL
!= NULL
) {
1225 Mode
->TTL
= *NewTTL
;
1228 if (NewToS
!= NULL
) {
1229 Mode
->ToS
= *NewToS
;
1238 GC_NOTO: Add function description
1240 @param This GC_NOTO: add argument
1242 @param NewStationIp GC_NOTO: add argument
1244 @param NewSubnetMask GC_NOTO: add argument
1247 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1249 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1251 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1253 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1255 @retval EFI_SUCCESS GC_NOTO: Add description for
1261 EfiPxeBcSetStationIP (
1262 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1263 IN EFI_IP_ADDRESS
* NewStationIp
, OPTIONAL
1264 IN EFI_IP_ADDRESS
* NewSubnetMask OPTIONAL
1267 PXEBC_PRIVATE_DATA
*Private
;
1268 EFI_PXE_BASE_CODE_MODE
*Mode
;
1271 return EFI_INVALID_PARAMETER
;
1274 if (NewStationIp
!= NULL
&& !Ip4IsUnicast (NTOHL (NewStationIp
->Addr
[0]), 0)) {
1275 return EFI_INVALID_PARAMETER
;
1278 if (NewSubnetMask
!= NULL
&& !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask
->Addr
[0]))) {
1279 return EFI_INVALID_PARAMETER
;
1282 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1283 Mode
= Private
->PxeBc
.Mode
;
1285 if (!Mode
->Started
) {
1286 return EFI_NOT_STARTED
;
1289 if (NewStationIp
!= NULL
) {
1290 Mode
->StationIp
= *NewStationIp
;
1293 if (NewSubnetMask
!= NULL
) {
1294 Mode
->SubnetMask
= *NewSubnetMask
;
1297 Private
->AddressIsOk
= TRUE
;
1304 GC_NOTO: Add function description
1306 @param This GC_NOTO: add argument
1308 @param NewDhcpDiscoverValid GC_NOTO: add argument
1310 @param NewDhcpAckReceived GC_NOTO: add argument
1312 @param NewProxyOfferReceived GC_NOTO: add argument
1314 @param NewPxeDiscoverValid GC_NOTO: add argument
1316 @param NewPxeReplyReceived GC_NOTO: add argument
1318 @param NewPxeBisReplyReceived GC_NOTO: add argument
1320 @param NewDhcpDiscover GC_NOTO: add argument
1322 @param NewDhcpAck GC_NOTO: add argument
1324 @param NewProxyOffer GC_NOTO: add argument
1326 @param NewPxeDiscover GC_NOTO: add argument
1328 @param NewPxeReply GC_NOTO: add argument
1330 @param NewPxeBisReply GC_NOTO: add argument
1333 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1335 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1337 @retval EFI_SUCCESS GC_NOTO: Add description for
1343 EfiPxeBcSetPackets (
1344 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
1345 IN BOOLEAN
* NewDhcpDiscoverValid
, OPTIONAL
1346 IN BOOLEAN
* NewDhcpAckReceived
, OPTIONAL
1347 IN BOOLEAN
* NewProxyOfferReceived
, OPTIONAL
1348 IN BOOLEAN
* NewPxeDiscoverValid
, OPTIONAL
1349 IN BOOLEAN
* NewPxeReplyReceived
, OPTIONAL
1350 IN BOOLEAN
* NewPxeBisReplyReceived
, OPTIONAL
1351 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
1352 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
1353 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
1354 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
1355 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
1356 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
1359 PXEBC_PRIVATE_DATA
*Private
;
1360 EFI_PXE_BASE_CODE_MODE
*Mode
;
1363 return EFI_INVALID_PARAMETER
;
1366 Private
= PXEBC_PRIVATE_DATA_FROM_PXEBC (This
);
1367 Mode
= Private
->PxeBc
.Mode
;
1369 if (!Mode
->Started
) {
1370 return EFI_NOT_STARTED
;
1373 Private
->FileSize
= 0;
1375 if (NewDhcpDiscoverValid
!= NULL
) {
1376 Mode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
1379 if (NewDhcpAckReceived
!= NULL
) {
1380 Mode
->DhcpAckReceived
= *NewDhcpAckReceived
;
1383 if (NewProxyOfferReceived
!= NULL
) {
1384 Mode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
1387 if (NewPxeDiscoverValid
!= NULL
) {
1388 Mode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
1391 if (NewPxeReplyReceived
!= NULL
) {
1392 Mode
->PxeReplyReceived
= *NewPxeReplyReceived
;
1395 if (NewPxeBisReplyReceived
!= NULL
) {
1396 Mode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
1399 if (NewDhcpDiscover
!= NULL
) {
1400 NetCopyMem (&Mode
->DhcpDiscover
, NewDhcpDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1403 if (NewDhcpAck
!= NULL
) {
1404 NetCopyMem (&Mode
->DhcpAck
, NewDhcpAck
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1407 if (NewProxyOffer
!= NULL
) {
1408 NetCopyMem (&Mode
->ProxyOffer
, NewProxyOffer
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1411 if (NewPxeDiscover
!= NULL
) {
1412 NetCopyMem (&Mode
->PxeDiscover
, NewPxeDiscover
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1415 if (NewPxeReply
!= NULL
) {
1416 NetCopyMem (&Mode
->PxeReply
, NewPxeReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1419 if (NewPxeBisReply
!= NULL
) {
1420 NetCopyMem (&Mode
->PxeBisReply
, NewPxeBisReply
, sizeof (EFI_PXE_BASE_CODE_PACKET
));
1426 EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate
= {
1427 EFI_PXE_BASE_CODE_PROTOCOL_REVISION
,
1435 EfiPxeBcSetIpFilter
,
1437 EfiPxeBcSetParameters
,
1438 EfiPxeBcSetStationIP
,
1445 GC_NOTO: Add function description
1447 @param This GC_NOTO: add argument
1449 @param Function GC_NOTO: add argument
1451 @param Received GC_NOTO: add argument
1453 @param PacketLength GC_NOTO: add argument
1455 @param PacketPtr GC_NOTO: add argument
1458 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT GC_NOTO: Add description for
1460 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1462 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1464 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1466 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1470 EFI_PXE_BASE_CODE_CALLBACK_STATUS
1472 EfiPxeLoadFileCallback (
1473 IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL
* This
,
1474 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
1475 IN BOOLEAN Received
,
1476 IN UINT32 PacketLength
,
1477 IN EFI_PXE_BASE_CODE_PACKET
* PacketPtr OPTIONAL
1484 // Catch Ctrl-C or ESC to abort.
1486 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1488 if (!EFI_ERROR (Status
)) {
1490 if (Key
.ScanCode
== SCAN_ESC
|| Key
.UnicodeChar
== (0x1F & 'c')) {
1492 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT
;
1496 // No print if receive packet
1499 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
1502 // Print only for three functions
1506 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP
:
1508 // Print only for open MTFTP packets, not every MTFTP packets
1510 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
1511 if (PacketPtr
->Raw
[0x1C] != 0x00 || PacketPtr
->Raw
[0x1D] != 0x01) {
1512 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
1517 case EFI_PXE_BASE_CODE_FUNCTION_DHCP
:
1518 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
:
1522 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
1525 if (PacketLength
!= 0 && PacketPtr
!= NULL
) {
1527 // Print '.' when transmit a packet
1533 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
;
1536 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate
= {
1537 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION
,
1538 EfiPxeLoadFileCallback
1543 GC_NOTO: Add function description
1545 @param Private GC_NOTO: add argument
1547 @param BufferSize GC_NOTO: add argument
1549 @param Buffer GC_NOTO: add argument
1552 @return GC_NOTO: add return values
1557 IN PXEBC_PRIVATE_DATA
*Private
,
1558 IN OUT UINT64
*BufferSize
,
1562 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
1563 EFI_PXE_BASE_CODE_MODE
*Mode
;
1569 PXEBC_CACHED_DHCP4_PACKET
*Packet
;
1572 PxeBc
= &Private
->PxeBc
;
1574 Type
= EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
;
1575 Layer
= EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL
;
1580 Status
= PxeBc
->Dhcp (PxeBc
, TRUE
);
1581 if (EFI_ERROR (Status
)) {
1586 // Select a boot server
1588 Status
= PxeBcSelectBootPrompt (Private
);
1590 if (Status
== EFI_SUCCESS
) {
1591 Status
= PxeBcSelectBootMenu (Private
, &Type
, TRUE
);
1592 } else if (Status
== EFI_TIMEOUT
) {
1593 Status
= PxeBcSelectBootMenu (Private
, &Type
, FALSE
);
1596 if (!EFI_ERROR (Status
)) {
1598 if (Type
== EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
) {
1600 // Local boot(PXE bootstrap server) need abort
1605 UseBis
= (BOOLEAN
) (Mode
->BisSupported
&& Mode
->BisDetected
);
1606 Status
= PxeBc
->Discover (PxeBc
, Type
, &Layer
, UseBis
, NULL
);
1607 if (EFI_ERROR (Status
)) {
1616 // Get bootfile name and (m)tftp server ip addresss
1618 if (Mode
->PxeReplyReceived
) {
1619 Packet
= &Private
->PxeReply
;
1620 } else if (Mode
->ProxyOfferReceived
) {
1621 Packet
= &Private
->ProxyOffer
;
1623 Packet
= &Private
->Dhcp4Ack
;
1626 NetCopyMem (&Private
->ServerIp
, &Packet
->Packet
.Offer
.Dhcp4
.Header
.ServerAddr
, sizeof (EFI_IPv4_ADDRESS
));
1627 if (Private
->ServerIp
.Addr
[0] == 0) {
1629 // next server ip address is zero, use option 54 instead
1633 Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_SERVER_ID
]->Data
,
1634 sizeof (EFI_IPv4_ADDRESS
)
1638 ASSERT (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
);
1643 Private
->BootFileName
= (CHAR8
*) (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE
]->Data
);
1645 if (Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
] != NULL
) {
1647 // Already have the bootfile length option, compute the file size
1649 NetCopyMem (&Value
, Packet
->Dhcp4Option
[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN
]->Data
, sizeof (Value
));
1650 Value
= NTOHS (Value
);
1651 *BufferSize
= 512 * Value
;
1652 Status
= EFI_BUFFER_TOO_SMALL
;
1655 // Get the bootfile size from tftp
1657 Status
= PxeBc
->Mtftp (
1659 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
,
1665 (UINT8
*) Private
->BootFileName
,
1671 Private
->FileSize
= (UINTN
) *BufferSize
;
1678 GC_NOTO: Add function description
1680 @param This GC_NOTO: add argument
1682 @param FilePath GC_NOTO: add argument
1684 @param BootPolicy GC_NOTO: add argument
1686 @param BufferSize GC_NOTO: add argument
1688 @param Buffer GC_NOTO: add argument
1691 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1693 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1700 IN EFI_LOAD_FILE_PROTOCOL
* This
,
1701 IN EFI_DEVICE_PATH_PROTOCOL
* FilePath
,
1702 IN BOOLEAN BootPolicy
,
1703 IN OUT UINTN
*BufferSize
,
1704 IN VOID
*Buffer OPTIONAL
1707 PXEBC_PRIVATE_DATA
*Private
;
1708 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBc
;
1709 BOOLEAN NewMakeCallback
;
1714 Private
= PXEBC_PRIVATE_DATA_FROM_LOADFILE (This
);
1715 PxeBc
= &Private
->PxeBc
;
1716 NewMakeCallback
= FALSE
;
1718 Status
= EFI_DEVICE_ERROR
;
1720 if (This
== NULL
|| BufferSize
== NULL
) {
1722 return EFI_INVALID_PARAMETER
;
1726 // Only support BootPolicy
1729 return EFI_UNSUPPORTED
;
1732 Status
= PxeBc
->Start (PxeBc
, FALSE
);
1733 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
1737 Status
= gBS
->HandleProtocol (
1738 Private
->Controller
,
1739 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1740 (VOID
**) &Private
->PxeBcCallback
1742 if (Status
== EFI_UNSUPPORTED
) {
1744 CopyMem (&Private
->LoadFileCallback
, &mPxeBcCallBackTemplate
, sizeof (Private
->LoadFileCallback
));
1746 Status
= gBS
->InstallProtocolInterface (
1747 &Private
->Controller
,
1748 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1749 EFI_NATIVE_INTERFACE
,
1750 &Private
->LoadFileCallback
1753 NewMakeCallback
= (BOOLEAN
) (Status
== EFI_SUCCESS
);
1755 Status
= PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
1756 if (EFI_ERROR (Status
)) {
1757 PxeBc
->Stop (PxeBc
);
1762 if (Private
->FileSize
== 0) {
1764 Status
= DiscoverBootFile (Private
, &TmpBufSize
, Buffer
);
1766 if (sizeof (UINTN
) < sizeof (UINT64
) && (TmpBufSize
> 0xFFFFFFFF)) {
1767 Status
= EFI_DEVICE_ERROR
;
1769 *BufferSize
= (UINTN
) TmpBufSize
;
1771 } else if (Buffer
== NULL
) {
1772 *BufferSize
= Private
->FileSize
;
1773 Status
= EFI_BUFFER_TOO_SMALL
;
1776 // Download the file.
1778 TmpBufSize
= (UINT64
) (*BufferSize
);
1779 Status
= PxeBc
->Mtftp (
1781 EFI_PXE_BASE_CODE_TFTP_READ_FILE
,
1787 (UINT8
*) Private
->BootFileName
,
1793 // If we added a callback protocol, now is the time to remove it.
1795 if (NewMakeCallback
) {
1797 NewMakeCallback
= FALSE
;
1799 PxeBc
->SetParameters (PxeBc
, NULL
, NULL
, NULL
, NULL
, &NewMakeCallback
);
1801 gBS
->UninstallProtocolInterface (
1802 Private
->Controller
,
1803 &gEfiPxeBaseCodeCallbackProtocolGuid
,
1804 &Private
->LoadFileCallback
1808 // Check download status
1815 case EFI_BUFFER_TOO_SMALL
:
1816 if (Buffer
!= NULL
) {
1817 AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
1823 case EFI_DEVICE_ERROR
:
1824 AsciiPrint ("PXE-E07: Network device error.\n");
1827 case EFI_OUT_OF_RESOURCES
:
1828 AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
1832 AsciiPrint ("PXE-E12: Could not detect network connection.\n");
1835 case EFI_NO_RESPONSE
:
1836 AsciiPrint ("PXE-E16: No offer received.\n");
1840 AsciiPrint ("PXE-E18: Server response timeout.\n");
1844 AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
1847 case EFI_ICMP_ERROR
:
1848 AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
1851 case EFI_TFTP_ERROR
:
1852 AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
1856 AsciiPrint ("PXE-E99: Unexpected network error.\n");
1860 PxeBc
->Stop (PxeBc
);
1865 EFI_LOAD_FILE_PROTOCOL mLoadFileProtocolTemplate
= { EfiPxeLoadFile
};