TianoCore EDK2 master
Loading...
Searching...
No Matches
PxeBcImpl.c
Go to the documentation of this file.
1
10#include "PxeBcImpl.h"
11
42EFIAPI
45 IN BOOLEAN UseIpv6
46 )
47{
48 PXEBC_PRIVATE_DATA *Private;
50 UINTN Index;
51 EFI_STATUS Status;
52
53 if (This == NULL) {
54 return EFI_INVALID_PARAMETER;
55 }
56
57 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
58 Mode = Private->PxeBc.Mode;
59
60 if (Mode->Started) {
61 return EFI_ALREADY_STARTED;
62 }
63
64 //
65 // Detect whether using IPv6 or not, and set it into mode data.
66 //
67 if (UseIpv6 && Mode->Ipv6Available && Mode->Ipv6Supported && (Private->Ip6Nic != NULL)) {
68 Mode->UsingIpv6 = TRUE;
69 } else if (!UseIpv6 && (Private->Ip4Nic != NULL)) {
70 Mode->UsingIpv6 = FALSE;
71 } else {
72 return EFI_UNSUPPORTED;
73 }
74
77 EFI_IO_BUS_IP_NETWORK | EFI_IOB_PC_RECONFIG,
78 (VOID *)&(Mode->UsingIpv6),
79 sizeof (Mode->UsingIpv6)
80 );
81
82 if (Mode->UsingIpv6) {
83 AsciiPrint ("\n>>Start PXE over IPv6");
84 //
85 // Configure udp6 instance to receive data.
86 //
87 Status = Private->Udp6Read->Configure (
88 Private->Udp6Read,
89 &Private->Udp6CfgData
90 );
91 if (EFI_ERROR (Status)) {
92 goto ON_ERROR;
93 }
94
95 //
96 // Configure block size for TFTP as a default value to handle all link layers.
97 //
98 Private->BlockSize = Private->Ip6MaxPacketSize -
99 PXEBC_DEFAULT_UDP_OVERHEAD_SIZE - PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE;
100
101 //
102 // PXE over IPv6 starts here, initialize the fields and list header.
103 //
104 Private->Ip6Policy = PXEBC_IP6_POLICY_MAX;
105 Private->ProxyOffer.Dhcp6.Packet.Offer.Size = PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE;
106 Private->DhcpAck.Dhcp6.Packet.Ack.Size = PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE;
107 Private->PxeReply.Dhcp6.Packet.Ack.Size = PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE;
108
109 for (Index = 0; Index < PXEBC_OFFER_MAX_NUM; Index++) {
110 Private->OfferBuffer[Index].Dhcp6.Packet.Offer.Size = PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE;
111 }
112
113 //
114 // Create event and set status for token to capture ICMP6 error message.
115 //
116 Private->Icmp6Token.Status = EFI_NOT_READY;
117 Status = gBS->CreateEvent (
118 EVT_NOTIFY_SIGNAL,
119 TPL_NOTIFY,
121 Private,
122 &Private->Icmp6Token.Event
123 );
124 if (EFI_ERROR (Status)) {
125 goto ON_ERROR;
126 }
127
128 //
129 // Set Ip6 policy to Automatic to start the IP6 router discovery.
130 //
131 Status = PxeBcSetIp6Policy (Private);
132 if (EFI_ERROR (Status)) {
133 goto ON_ERROR;
134 }
135 } else {
136 AsciiPrint ("\n>>Start PXE over IPv4");
137 //
138 // Configure udp4 instance to receive data.
139 //
140 Status = Private->Udp4Read->Configure (
141 Private->Udp4Read,
142 &Private->Udp4CfgData
143 );
144 if (EFI_ERROR (Status)) {
145 goto ON_ERROR;
146 }
147
148 //
149 // Configure block size for TFTP as a default value to handle all link layers.
150 //
151 Private->BlockSize = Private->Ip4MaxPacketSize -
152 PXEBC_DEFAULT_UDP_OVERHEAD_SIZE - PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE;
153
154 //
155 // PXE over IPv4 starts here, initialize the fields.
156 //
157 Private->ProxyOffer.Dhcp4.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
158 Private->DhcpAck.Dhcp4.Packet.Ack.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
159 Private->PxeReply.Dhcp4.Packet.Ack.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
160
161 for (Index = 0; Index < PXEBC_OFFER_MAX_NUM; Index++) {
162 Private->OfferBuffer[Index].Dhcp4.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
163 }
164
165 PxeBcSeedDhcp4Packet (&Private->SeedPacket, Private->Udp4Read);
166
167 //
168 // Create the event for Arp cache update.
169 //
170 Status = gBS->CreateEvent (
171 EVT_TIMER | EVT_NOTIFY_SIGNAL,
172 TPL_CALLBACK,
174 Private,
175 &Private->ArpUpdateEvent
176 );
177 if (EFI_ERROR (Status)) {
178 goto ON_ERROR;
179 }
180
181 //
182 // Start a periodic timer by second to update Arp cache.
183 //
184 Status = gBS->SetTimer (
185 Private->ArpUpdateEvent,
187 TICKS_PER_SECOND
188 );
189 if (EFI_ERROR (Status)) {
190 goto ON_ERROR;
191 }
192
193 //
194 // Create event and set status for token to capture ICMP error message.
195 //
196 Private->Icmp6Token.Status = EFI_NOT_READY;
197 Status = gBS->CreateEvent (
198 EVT_NOTIFY_SIGNAL,
199 TPL_NOTIFY,
201 Private,
202 &Private->IcmpToken.Event
203 );
204 if (EFI_ERROR (Status)) {
205 goto ON_ERROR;
206 }
207
208 //
209 // DHCP4 service allows only one of its children to be configured in
210 // the active state, If the DHCP4 D.O.R.A started by IP4 auto
211 // configuration and has not been completed, the Dhcp4 state machine
212 // will not be in the right state for the PXE to start a new round D.O.R.A.
213 // so we need to switch its policy to static.
214 //
215 Status = PxeBcSetIp4Policy (Private);
216 if (EFI_ERROR (Status)) {
217 goto ON_ERROR;
218 }
219 }
220
221 //
222 // If PcdTftpBlockSize is set to non-zero, override the default value.
223 //
224 if (PcdGet64 (PcdTftpBlockSize) != 0) {
225 Private->BlockSize = (UINTN)PcdGet64 (PcdTftpBlockSize);
226 }
227
228 //
229 // Create event for UdpRead/UdpWrite timeout since they are both blocking API.
230 //
231 Status = gBS->CreateEvent (
232 EVT_TIMER,
233 TPL_CALLBACK,
234 NULL,
235 NULL,
236 &Private->UdpTimeOutEvent
237 );
238 if (EFI_ERROR (Status)) {
239 goto ON_ERROR;
240 }
241
242 Private->IsAddressOk = FALSE;
243 Mode->Started = TRUE;
244
245 return EFI_SUCCESS;
246
247ON_ERROR:
248 if (Mode->UsingIpv6) {
249 if (Private->Icmp6Token.Event != NULL) {
250 gBS->CloseEvent (Private->Icmp6Token.Event);
251 Private->Icmp6Token.Event = NULL;
252 }
253
254 Private->Udp6Read->Configure (Private->Udp6Read, NULL);
255 Private->Ip6->Configure (Private->Ip6, NULL);
256 } else {
257 if (Private->ArpUpdateEvent != NULL) {
258 gBS->CloseEvent (Private->ArpUpdateEvent);
259 Private->ArpUpdateEvent = NULL;
260 }
261
262 if (Private->IcmpToken.Event != NULL) {
263 gBS->CloseEvent (Private->IcmpToken.Event);
264 Private->IcmpToken.Event = NULL;
265 }
266
267 Private->Udp4Read->Configure (Private->Udp4Read, NULL);
268 Private->Ip4->Configure (Private->Ip4, NULL);
269 }
270
271 return Status;
272}
273
292EFIAPI
295 )
296{
297 PXEBC_PRIVATE_DATA *Private;
299 BOOLEAN Ipv6Supported;
300 BOOLEAN Ipv6Available;
301
302 if (This == NULL) {
303 return EFI_INVALID_PARAMETER;
304 }
305
306 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
307 Mode = Private->PxeBc.Mode;
308 Ipv6Supported = Mode->Ipv6Supported;
309 Ipv6Available = Mode->Ipv6Available;
310
311 if (!Mode->Started) {
312 return EFI_NOT_STARTED;
313 }
314
315 if (Mode->UsingIpv6) {
316 //
317 // Configure all the instances for IPv6 as NULL.
318 //
319 ZeroMem (&Private->Udp6CfgData.StationAddress, sizeof (EFI_IPv6_ADDRESS));
320 ZeroMem (&Private->Ip6CfgData.StationAddress, sizeof (EFI_IPv6_ADDRESS));
321 Private->Dhcp6->Stop (Private->Dhcp6);
322 Private->Dhcp6->Configure (Private->Dhcp6, NULL);
323 Private->Udp6Write->Configure (Private->Udp6Write, NULL);
324 Private->Udp6Read->Groups (Private->Udp6Read, FALSE, NULL);
325 Private->Udp6Read->Configure (Private->Udp6Read, NULL);
326 Private->Ip6->Cancel (Private->Ip6, &Private->Icmp6Token);
327 Private->Ip6->Configure (Private->Ip6, NULL);
329 if (Private->Icmp6Token.Event != NULL) {
330 gBS->CloseEvent (Private->Icmp6Token.Event);
331 Private->Icmp6Token.Event = NULL;
332 }
333
334 if (Private->Dhcp6Request != NULL) {
335 FreePool (Private->Dhcp6Request);
336 Private->Dhcp6Request = NULL;
337 }
338
339 if (Private->BootFileName != NULL) {
340 FreePool (Private->BootFileName);
341 Private->BootFileName = NULL;
342 }
343 } else {
344 //
345 // Configure all the instances for IPv4 as NULL.
346 //
347 ZeroMem (&Private->Udp4CfgData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
348 ZeroMem (&Private->Udp4CfgData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
349 ZeroMem (&Private->Ip4CfgData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
350 ZeroMem (&Private->Ip4CfgData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
351 Private->Dhcp4->Stop (Private->Dhcp4);
352 Private->Dhcp4->Configure (Private->Dhcp4, NULL);
353 Private->Udp4Write->Configure (Private->Udp4Write, NULL);
354 Private->Udp4Read->Groups (Private->Udp4Read, FALSE, NULL);
355 Private->Udp4Read->Configure (Private->Udp4Read, NULL);
356 Private->Ip4->Cancel (Private->Ip4, &Private->IcmpToken);
357 Private->Ip4->Configure (Private->Ip4, NULL);
358 if (Private->ArpUpdateEvent != NULL) {
359 gBS->CloseEvent (Private->ArpUpdateEvent);
360 Private->ArpUpdateEvent = NULL;
361 }
362
363 if (Private->IcmpToken.Event != NULL) {
364 gBS->CloseEvent (Private->IcmpToken.Event);
365 Private->IcmpToken.Event = NULL;
366 }
367
368 Private->BootFileName = NULL;
369 }
370
371 gBS->CloseEvent (Private->UdpTimeOutEvent);
372 Private->CurSrcPort = 0;
373 Private->BootFileSize = 0;
374 Private->SolicitTimes = 0;
375 Private->ElapsedTime = 0;
376 ZeroMem (&Private->StationIp, sizeof (EFI_IP_ADDRESS));
377 ZeroMem (&Private->SubnetMask, sizeof (EFI_IP_ADDRESS));
378 ZeroMem (&Private->GatewayIp, sizeof (EFI_IP_ADDRESS));
379 ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS));
380
381 //
382 // Reset the mode data.
383 //
384 ZeroMem (Mode, sizeof (EFI_PXE_BASE_CODE_MODE));
385 Mode->Ipv6Available = Ipv6Available;
386 Mode->Ipv6Supported = Ipv6Supported;
387 Mode->AutoArp = TRUE;
388 Mode->TTL = DEFAULT_TTL;
389 Mode->ToS = DEFAULT_ToS;
390
391 return EFI_SUCCESS;
392}
393
423EFIAPI
426 IN BOOLEAN SortOffers
427 )
428{
429 PXEBC_PRIVATE_DATA *Private;
431 EFI_STATUS Status;
433
434 if (This == NULL) {
435 return EFI_INVALID_PARAMETER;
436 }
437
438 Status = EFI_SUCCESS;
439 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
440 Mode = Private->PxeBc.Mode;
441 Mode->IcmpErrorReceived = FALSE;
442 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DHCP;
443 Private->IsOfferSorted = SortOffers;
444 Private->SolicitTimes = 0;
445 Private->ElapsedTime = 0;
446
447 if (!Mode->Started) {
448 return EFI_NOT_STARTED;
449 }
450
451 if (Mode->UsingIpv6) {
452 //
453 // Stop Udp6Read instance
454 //
455 Private->Udp6Read->Configure (Private->Udp6Read, NULL);
456
457 //
458 // Start S.A.R.R. process to get a IPv6 address and other boot information.
459 //
460 Status = PxeBcDhcp6Sarr (Private, Private->Dhcp6);
461 } else {
462 //
463 // Stop Udp4Read instance
464 //
465 Private->Udp4Read->Configure (Private->Udp4Read, NULL);
466
467 //
468 // Start D.O.R.A. process to get a IPv4 address and other boot information.
469 //
470 Status = PxeBcDhcp4Dora (Private, Private->Dhcp4);
471 }
472
473 //
474 // Reconfigure the UDP instance with the default configuration.
475 //
476 if (Mode->UsingIpv6) {
477 Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);
478 } else {
479 Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
480 }
481
482 //
483 // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP
484 // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.
485 //
486 ZeroMem (&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));
487 IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;
488 This->SetIpFilter (This, &IpFilter);
489
490 return Status;
491}
492
538EFIAPI
541 IN UINT16 Type,
542 IN UINT16 *Layer,
543 IN BOOLEAN UseBis,
545 )
546{
547 PXEBC_PRIVATE_DATA *Private;
551 PXEBC_BOOT_SVR_ENTRY *BootSvrEntry;
552 UINT16 Index;
553 EFI_STATUS Status;
555 EFI_PXE_BASE_CODE_DISCOVER_INFO *NewCreatedInfo;
556
557 if (This == NULL) {
558 return EFI_INVALID_PARAMETER;
559 }
560
561 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
562 Mode = Private->PxeBc.Mode;
563 Mode->IcmpErrorReceived = FALSE;
564 BootSvrEntry = NULL;
565 SrvList = NULL;
566 Status = EFI_DEVICE_ERROR;
567 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER;
568 NewCreatedInfo = NULL;
569
570 if (!Mode->Started) {
571 return EFI_NOT_STARTED;
572 }
573
574 //
575 // Station address should be ready before do discover.
576 //
577 if (!Private->IsAddressOk) {
578 return EFI_INVALID_PARAMETER;
579 }
580
581 if (Mode->UsingIpv6) {
582 //
583 // Stop Udp6Read instance
584 //
585 Private->Udp6Read->Configure (Private->Udp6Read, NULL);
586 } else {
587 //
588 // Stop Udp4Read instance
589 //
590 Private->Udp4Read->Configure (Private->Udp4Read, NULL);
591 }
592
593 //
594 // There are 3 methods to get the information for discover.
595 //
596 ZeroMem (&DefaultInfo, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO));
597 if (*Layer != EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL) {
598 //
599 // 1. Take the previous setting as the discover info.
600 //
601 if (!Mode->PxeDiscoverValid ||
602 !Mode->PxeReplyReceived ||
603 (!Mode->PxeBisReplyReceived && UseBis))
604 {
605 Status = EFI_INVALID_PARAMETER;
606 goto ON_EXIT;
607 }
608
609 Info = &DefaultInfo;
610 Info->IpCnt = 1;
611 Info->UseUCast = TRUE;
612 SrvList = Info->SrvList;
613 SrvList[0].Type = Type;
614 SrvList[0].AcceptAnyResponse = FALSE;
615
616 CopyMem (&SrvList->IpAddr, &Private->ServerIp, sizeof (EFI_IP_ADDRESS));
617 } else if (Info == NULL) {
618 //
619 // 2. Extract the discover information from the cached packets if unspecified.
620 //
621 NewCreatedInfo = &DefaultInfo;
622 Status = PxeBcExtractDiscoverInfo (Private, Type, &NewCreatedInfo, &BootSvrEntry, &SrvList);
623 if (EFI_ERROR (Status)) {
624 goto ON_EXIT;
625 }
626
627 ASSERT (NewCreatedInfo != NULL);
628 Info = NewCreatedInfo;
629 } else {
630 //
631 // 3. Take the pass-in information as the discover info, and validate the server list.
632 //
633 SrvList = Info->SrvList;
634
635 if (!SrvList[0].AcceptAnyResponse) {
636 for (Index = 1; Index < Info->IpCnt; Index++) {
637 if (SrvList[Index].AcceptAnyResponse) {
638 break;
639 }
640 }
641
642 if (Index != Info->IpCnt) {
643 //
644 // It's invalid if the first server doesn't accept any response
645 // but any of the other servers does accept any response.
646 //
647 Status = EFI_INVALID_PARAMETER;
648 goto ON_EXIT;
649 }
650 }
651 }
652
653 //
654 // Info and BootSvrEntry/SrvList are all ready by now, so execute discover by UniCast/BroadCast/MultiCast.
655 //
656 if ((!Info->UseUCast && !Info->UseBCast && !Info->UseMCast) ||
657 (Info->MustUseList && (Info->IpCnt == 0)))
658 {
659 Status = EFI_INVALID_PARAMETER;
660 goto ON_EXIT;
661 }
662
663 Private->IsDoDiscover = TRUE;
664
665 if (Info->UseMCast) {
666 //
667 // Do discover by multicast.
668 //
669 Status = PxeBcDiscoverBootServer (
670 Private,
671 Type,
672 Layer,
673 UseBis,
674 &Info->ServerMCastIp,
675 Info->IpCnt,
676 SrvList
677 );
678 } else if (Info->UseBCast) {
679 //
680 // Do discover by broadcast, but only valid for IPv4.
681 //
682 ASSERT (!Mode->UsingIpv6);
683 Status = PxeBcDiscoverBootServer (
684 Private,
685 Type,
686 Layer,
687 UseBis,
688 NULL,
689 Info->IpCnt,
690 SrvList
691 );
692 } else if (Info->UseUCast) {
693 //
694 // Do discover by unicast.
695 //
696 for (Index = 0; Index < Info->IpCnt; Index++) {
697 if (BootSvrEntry == NULL) {
698 CopyMem (&Private->ServerIp, &SrvList[Index].IpAddr, sizeof (EFI_IP_ADDRESS));
699 } else {
700 ASSERT (!Mode->UsingIpv6);
701 ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS));
702 CopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS));
703 }
704
705 Status = PxeBcDiscoverBootServer (
706 Private,
707 Type,
708 Layer,
709 UseBis,
710 &Private->ServerIp,
711 Info->IpCnt,
712 SrvList
713 );
714 }
715 }
716
717 if (!EFI_ERROR (Status)) {
718 //
719 // Parse the cached PXE reply packet, and store it into mode data if valid.
720 //
721 if (Mode->UsingIpv6) {
722 Status = PxeBcParseDhcp6Packet (&Private->PxeReply.Dhcp6);
723 if (!EFI_ERROR (Status)) {
724 CopyMem (
725 &Mode->PxeReply.Dhcpv6,
726 &Private->PxeReply.Dhcp6.Packet.Ack.Dhcp6,
727 Private->PxeReply.Dhcp6.Packet.Ack.Length
728 );
729 Mode->PxeReplyReceived = TRUE;
730 Mode->PxeDiscoverValid = TRUE;
731 }
732 } else {
733 Status = PxeBcParseDhcp4Packet (&Private->PxeReply.Dhcp4);
734 if (!EFI_ERROR (Status)) {
735 CopyMem (
736 &Mode->PxeReply.Dhcpv4,
737 &Private->PxeReply.Dhcp4.Packet.Ack.Dhcp4,
738 Private->PxeReply.Dhcp4.Packet.Ack.Length
739 );
740 Mode->PxeReplyReceived = TRUE;
741 Mode->PxeDiscoverValid = TRUE;
742 }
743 }
744 }
745
746ON_EXIT:
747
748 if ((NewCreatedInfo != NULL) && (NewCreatedInfo != &DefaultInfo)) {
749 FreePool (NewCreatedInfo);
750 }
751
752 if (Mode->UsingIpv6) {
753 Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);
754 } else {
755 Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
756 }
757
758 //
759 // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP
760 // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.
761 //
762 ZeroMem (&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));
763 IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;
764 This->SetIpFilter (This, &IpFilter);
765
766 return Status;
767}
768
833EFIAPI
837 IN OUT VOID *BufferPtr OPTIONAL,
838 IN BOOLEAN Overwrite,
839 IN OUT UINT64 *BufferSize,
840 IN UINTN *BlockSize OPTIONAL,
841 IN EFI_IP_ADDRESS *ServerIp,
842 IN UINT8 *Filename,
843 IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL,
844 IN BOOLEAN DontUseBuffer
845 )
846{
847 PXEBC_PRIVATE_DATA *Private;
849 EFI_MTFTP4_CONFIG_DATA Mtftp4Config;
850 EFI_MTFTP6_CONFIG_DATA Mtftp6Config;
851 VOID *Config;
852 EFI_STATUS Status;
854 UINTN WindowSize;
855
856 if ((This == NULL) ||
857 (Filename == NULL) ||
858 (BufferSize == NULL) ||
859 (ServerIp == NULL) ||
860 ((BlockSize != NULL) && (*BlockSize < PXE_MTFTP_DEFAULT_BLOCK_SIZE)))
861 {
862 return EFI_INVALID_PARAMETER;
863 }
864
865 if ((Operation == EFI_PXE_BASE_CODE_TFTP_READ_FILE) ||
866 (Operation == EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY) ||
867 (Operation == EFI_PXE_BASE_CODE_MTFTP_READ_FILE) ||
868 (Operation == EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY))
869 {
870 if ((BufferPtr == NULL) && !DontUseBuffer) {
871 return EFI_INVALID_PARAMETER;
872 }
873 }
874
875 Config = NULL;
876 Status = EFI_DEVICE_ERROR;
877 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
878 Mode = Private->PxeBc.Mode;
879
880 //
881 // Get PcdPxeTftpWindowSize.
882 //
883 WindowSize = (UINTN)PcdGet64 (PcdPxeTftpWindowSize);
884
885 if (Mode->UsingIpv6) {
886 if (!NetIp6IsValidUnicast (&ServerIp->v6)) {
887 return EFI_INVALID_PARAMETER;
888 }
889 } else {
890 if (IP4_IS_UNSPECIFIED (NTOHL (ServerIp->Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (ServerIp->Addr[0]))) {
891 return EFI_INVALID_PARAMETER;
892 }
893 }
894
895 if (Mode->UsingIpv6) {
896 //
897 // Set configuration data for Mtftp6 instance.
898 //
899 ZeroMem (&Mtftp6Config, sizeof (EFI_MTFTP6_CONFIG_DATA));
900 Config = &Mtftp6Config;
901 Mtftp6Config.TimeoutValue = PXEBC_MTFTP_TIMEOUT;
902 Mtftp6Config.TryCount = PXEBC_MTFTP_RETRIES;
903 CopyMem (&Mtftp6Config.StationIp, &Private->StationIp.v6, sizeof (EFI_IPv6_ADDRESS));
904 CopyMem (&Mtftp6Config.ServerIp, &ServerIp->v6, sizeof (EFI_IPv6_ADDRESS));
905 //
906 // Stop Udp6Read instance
907 //
908 Private->Udp6Read->Configure (Private->Udp6Read, NULL);
909 } else {
910 //
911 // Set configuration data for Mtftp4 instance.
912 //
913 ZeroMem (&Mtftp4Config, sizeof (EFI_MTFTP4_CONFIG_DATA));
914 Config = &Mtftp4Config;
915 Mtftp4Config.UseDefaultSetting = FALSE;
916 Mtftp4Config.TimeoutValue = PXEBC_MTFTP_TIMEOUT;
917 Mtftp4Config.TryCount = PXEBC_MTFTP_RETRIES;
918 CopyMem (&Mtftp4Config.StationIp, &Private->StationIp.v4, sizeof (EFI_IPv4_ADDRESS));
919 CopyMem (&Mtftp4Config.SubnetMask, &Private->SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
920 CopyMem (&Mtftp4Config.GatewayIp, &Private->GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));
921 CopyMem (&Mtftp4Config.ServerIp, &ServerIp->v4, sizeof (EFI_IPv4_ADDRESS));
922 //
923 // Stop Udp4Read instance
924 //
925 Private->Udp4Read->Configure (Private->Udp4Read, NULL);
926 }
927
928 Mode->TftpErrorReceived = FALSE;
929 Mode->IcmpErrorReceived = FALSE;
930
931 switch (Operation) {
932 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE:
933 //
934 // Send TFTP request to get file size.
935 //
936 Status = PxeBcTftpGetFileSize (
937 Private,
938 Config,
939 Filename,
940 BlockSize,
941 (WindowSize > 1) ? &WindowSize : NULL,
942 BufferSize
943 );
944
945 break;
946
947 case EFI_PXE_BASE_CODE_TFTP_READ_FILE:
948 //
949 // Send TFTP request to read file.
950 //
951 Status = PxeBcTftpReadFile (
952 Private,
953 Config,
954 Filename,
955 BlockSize,
956 (WindowSize > 1) ? &WindowSize : NULL,
957 BufferPtr,
958 BufferSize,
959 DontUseBuffer
960 );
961
962 break;
963
964 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE:
965 //
966 // Send TFTP request to write file.
967 //
968 Status = PxeBcTftpWriteFile (
969 Private,
970 Config,
971 Filename,
972 Overwrite,
973 BlockSize,
974 BufferPtr,
975 BufferSize
976 );
977
978 break;
979
980 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY:
981 //
982 // Send TFTP request to read directory.
983 //
984 Status = PxeBcTftpReadDirectory (
985 Private,
986 Config,
987 Filename,
988 BlockSize,
989 (WindowSize > 1) ? &WindowSize : NULL,
990 BufferPtr,
991 BufferSize,
992 DontUseBuffer
993 );
994
995 break;
996
997 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE:
998 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE:
999 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY:
1000 Status = EFI_UNSUPPORTED;
1001
1002 break;
1003
1004 default:
1005 Status = EFI_INVALID_PARAMETER;
1006
1007 break;
1008 }
1009
1010 if (Status == EFI_ICMP_ERROR) {
1011 Mode->IcmpErrorReceived = TRUE;
1012 }
1013
1014 //
1015 // Reconfigure the UDP instance with the default configuration.
1016 //
1017 if (Mode->UsingIpv6) {
1018 Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);
1019 } else {
1020 Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
1021 }
1022
1023 //
1024 // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP
1025 // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.
1026 //
1027 ZeroMem (&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));
1028 IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;
1029 This->SetIpFilter (This, &IpFilter);
1030
1031 return Status;
1032}
1033
1072EFIAPI
1075 IN UINT16 OpFlags,
1076 IN EFI_IP_ADDRESS *DestIp,
1077 IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort,
1078 IN EFI_IP_ADDRESS *GatewayIp OPTIONAL,
1079 IN EFI_IP_ADDRESS *SrcIp OPTIONAL,
1080 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
1081 IN UINTN *HeaderSize OPTIONAL,
1082 IN VOID *HeaderPtr OPTIONAL,
1083 IN UINTN *BufferSize,
1084 IN VOID *BufferPtr
1085 )
1086{
1087 PXEBC_PRIVATE_DATA *Private;
1089 EFI_UDP4_SESSION_DATA Udp4Session;
1090 EFI_UDP6_SESSION_DATA Udp6Session;
1091 EFI_STATUS Status;
1092 BOOLEAN DoNotFragment;
1093
1094 if ((This == NULL) || (DestIp == NULL) || (DestPort == NULL)) {
1095 return EFI_INVALID_PARAMETER;
1096 }
1097
1098 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1099 Mode = Private->PxeBc.Mode;
1100
1101 if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT) != 0) {
1102 DoNotFragment = FALSE;
1103 } else {
1104 DoNotFragment = TRUE;
1105 }
1106
1107 if (!Mode->UsingIpv6 && (GatewayIp != NULL) && (Mode->SubnetMask.Addr[0] != 0) &&
1108 !NetIp4IsUnicast (NTOHL (GatewayIp->Addr[0]), EFI_NTOHL (Mode->SubnetMask)))
1109 {
1110 //
1111 // Gateway is provided but it's not a unicast IPv4 address, while it will be ignored for IPv6.
1112 //
1113 return EFI_INVALID_PARAMETER;
1114 }
1115
1116 if ((HeaderSize != NULL) && ((*HeaderSize == 0) || (HeaderPtr == NULL))) {
1117 return EFI_INVALID_PARAMETER;
1118 }
1119
1120 if ((BufferSize == NULL) || ((*BufferSize != 0) && (BufferPtr == NULL))) {
1121 return EFI_INVALID_PARAMETER;
1122 }
1123
1124 if (!Mode->Started) {
1125 return EFI_NOT_STARTED;
1126 }
1127
1128 if (!Private->IsAddressOk && (SrcIp == NULL)) {
1129 return EFI_INVALID_PARAMETER;
1130 }
1131
1132 if ((Private->CurSrcPort == 0) ||
1133 ((SrcPort != NULL) && (*SrcPort != Private->CurSrcPort)))
1134 {
1135 //
1136 // Reconfigure UDPv4/UDPv6 for UdpWrite if the source port changed.
1137 //
1138 if (SrcPort != NULL) {
1139 Private->CurSrcPort = *SrcPort;
1140 }
1141 }
1142
1143 if (Mode->UsingIpv6) {
1144 Status = PxeBcConfigUdp6Write (
1145 Private->Udp6Write,
1146 &Private->StationIp.v6,
1147 &Private->CurSrcPort
1148 );
1149 } else {
1150 //
1151 // Configure the UDPv4 instance with gateway information from DHCP server as default.
1152 //
1153 Status = PxeBcConfigUdp4Write (
1154 Private->Udp4Write,
1155 &Private->StationIp.v4,
1156 &Private->SubnetMask.v4,
1157 &Private->GatewayIp.v4,
1158 &Private->CurSrcPort,
1159 DoNotFragment,
1160 Private->Mode.TTL,
1161 Private->Mode.ToS
1162 );
1163 }
1164
1165 if (EFI_ERROR (Status)) {
1166 Private->CurSrcPort = 0;
1167 return EFI_INVALID_PARAMETER;
1168 } else if (SrcPort != NULL) {
1169 *SrcPort = Private->CurSrcPort;
1170 }
1171
1172 //
1173 // Start a timer as timeout event for this blocking API.
1174 //
1175 gBS->SetTimer (Private->UdpTimeOutEvent, TimerRelative, PXEBC_UDP_TIMEOUT);
1176
1177 if (Mode->UsingIpv6) {
1178 //
1179 // Construct UDPv6 session data.
1180 //
1181 ZeroMem (&Udp6Session, sizeof (EFI_UDP6_SESSION_DATA));
1182 CopyMem (&Udp6Session.DestinationAddress, DestIp, sizeof (EFI_IPv6_ADDRESS));
1183 Udp6Session.DestinationPort = *DestPort;
1184 if (SrcIp != NULL) {
1185 CopyMem (&Udp6Session.SourceAddress, SrcIp, sizeof (EFI_IPv6_ADDRESS));
1186 }
1187
1188 if (SrcPort != NULL) {
1189 Udp6Session.SourcePort = *SrcPort;
1190 }
1191
1192 Status = PxeBcUdp6Write (
1193 Private->Udp6Write,
1194 &Udp6Session,
1195 Private->UdpTimeOutEvent,
1196 HeaderSize,
1197 HeaderPtr,
1198 BufferSize,
1199 BufferPtr
1200 );
1201 } else {
1202 //
1203 // Construct UDPv4 session data.
1204 //
1205 ZeroMem (&Udp4Session, sizeof (EFI_UDP4_SESSION_DATA));
1206 CopyMem (&Udp4Session.DestinationAddress, DestIp, sizeof (EFI_IPv4_ADDRESS));
1207 Udp4Session.DestinationPort = *DestPort;
1208 if (SrcIp != NULL) {
1209 CopyMem (&Udp4Session.SourceAddress, SrcIp, sizeof (EFI_IPv4_ADDRESS));
1210 }
1211
1212 if (SrcPort != NULL) {
1213 Udp4Session.SourcePort = *SrcPort;
1214 }
1215
1216 //
1217 // Override the gateway information if user specified.
1218 //
1219 Status = PxeBcUdp4Write (
1220 Private->Udp4Write,
1221 &Udp4Session,
1222 Private->UdpTimeOutEvent,
1223 (EFI_IPv4_ADDRESS *)GatewayIp,
1224 HeaderSize,
1225 HeaderPtr,
1226 BufferSize,
1227 BufferPtr
1228 );
1229 }
1230
1231 gBS->SetTimer (Private->UdpTimeOutEvent, TimerCancel, 0);
1232
1233 //
1234 // Reset the UdpWrite instance.
1235 //
1236 if (Mode->UsingIpv6) {
1237 Private->Udp6Write->Configure (Private->Udp6Write, NULL);
1238 } else {
1239 Private->Udp4Write->Configure (Private->Udp4Write, NULL);
1240 }
1241
1242 return Status;
1243}
1244
1283EFIAPI
1286 IN UINT16 OpFlags,
1287 IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL,
1288 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL,
1289 IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL,
1290 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
1291 IN UINTN *HeaderSize OPTIONAL,
1292 IN VOID *HeaderPtr OPTIONAL,
1293 IN OUT UINTN *BufferSize,
1294 IN VOID *BufferPtr
1295 )
1296{
1297 PXEBC_PRIVATE_DATA *Private;
1299 EFI_UDP4_COMPLETION_TOKEN Udp4Token;
1300 EFI_UDP6_COMPLETION_TOKEN Udp6Token;
1301 EFI_UDP4_RECEIVE_DATA *Udp4Rx;
1302 EFI_UDP6_RECEIVE_DATA *Udp6Rx;
1303 EFI_STATUS Status;
1304 BOOLEAN IsDone;
1305 BOOLEAN IsMatched;
1306 UINTN CopiedLen;
1307 UINTN HeaderLen;
1308 UINTN HeaderCopiedLen;
1309 UINTN BufferCopiedLen;
1310 UINT32 FragmentLength;
1311 UINTN FragmentIndex;
1312 UINT8 *FragmentBuffer;
1313
1314 if (This == NULL) {
1315 return EFI_INVALID_PARAMETER;
1316 }
1317
1318 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1319 Mode = Private->PxeBc.Mode;
1320 IsDone = FALSE;
1321 IsMatched = FALSE;
1322 Udp4Rx = NULL;
1323 Udp6Rx = NULL;
1324
1325 if ((((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) == 0) && (DestPort == NULL)) ||
1326 (((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) == 0) && (SrcIp == NULL)) ||
1327 (((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) == 0) && (SrcPort == NULL)))
1328 {
1329 return EFI_INVALID_PARAMETER;
1330 }
1331
1332 if (((HeaderSize != NULL) && (*HeaderSize == 0)) || ((HeaderSize != NULL) && (HeaderPtr == NULL))) {
1333 return EFI_INVALID_PARAMETER;
1334 }
1335
1336 if ((BufferSize == NULL) || (BufferPtr == NULL)) {
1337 return EFI_INVALID_PARAMETER;
1338 }
1339
1340 if (!Mode->Started) {
1341 return EFI_NOT_STARTED;
1342 }
1343
1344 ZeroMem (&Udp6Token, sizeof (EFI_UDP6_COMPLETION_TOKEN));
1345 ZeroMem (&Udp4Token, sizeof (EFI_UDP4_COMPLETION_TOKEN));
1346
1347 if (Mode->UsingIpv6) {
1348 Status = gBS->CreateEvent (
1349 EVT_NOTIFY_SIGNAL,
1350 TPL_NOTIFY,
1352 &IsDone,
1353 &Udp6Token.Event
1354 );
1355 if (EFI_ERROR (Status)) {
1356 return EFI_OUT_OF_RESOURCES;
1357 }
1358 } else {
1359 Status = gBS->CreateEvent (
1360 EVT_NOTIFY_SIGNAL,
1361 TPL_NOTIFY,
1363 &IsDone,
1364 &Udp4Token.Event
1365 );
1366 if (EFI_ERROR (Status)) {
1367 return EFI_OUT_OF_RESOURCES;
1368 }
1369 }
1370
1371 //
1372 // Start a timer as timeout event for this blocking API.
1373 //
1374 gBS->SetTimer (Private->UdpTimeOutEvent, TimerRelative, PXEBC_UDP_TIMEOUT);
1375 Mode->IcmpErrorReceived = FALSE;
1376
1377 //
1378 // Read packet by Udp4Read/Udp6Read until matched or timeout.
1379 //
1380 while (!IsMatched && !EFI_ERROR (Status)) {
1381 if (Mode->UsingIpv6) {
1382 Status = PxeBcUdp6Read (
1383 Private->Udp6Read,
1384 &Udp6Token,
1385 Mode,
1386 Private->UdpTimeOutEvent,
1387 OpFlags,
1388 &IsDone,
1389 &IsMatched,
1390 DestIp,
1391 DestPort,
1392 SrcIp,
1393 SrcPort
1394 );
1395 } else {
1396 Status = PxeBcUdp4Read (
1397 Private->Udp4Read,
1398 &Udp4Token,
1399 Mode,
1400 Private->UdpTimeOutEvent,
1401 OpFlags,
1402 &IsDone,
1403 &IsMatched,
1404 DestIp,
1405 DestPort,
1406 SrcIp,
1407 SrcPort
1408 );
1409 }
1410 }
1411
1412 if ((Status == EFI_ICMP_ERROR) ||
1413 (Status == EFI_NETWORK_UNREACHABLE) ||
1414 (Status == EFI_HOST_UNREACHABLE) ||
1415 (Status == EFI_PROTOCOL_UNREACHABLE) ||
1416 (Status == EFI_PORT_UNREACHABLE))
1417 {
1418 //
1419 // Get different return status for icmp error from Udp, refers to UEFI spec.
1420 //
1421 Mode->IcmpErrorReceived = TRUE;
1422 }
1423
1424 gBS->SetTimer (Private->UdpTimeOutEvent, TimerCancel, 0);
1425
1426 if (IsMatched) {
1427 //
1428 // Copy the received packet to user if matched by filter.
1429 //
1430 if (Mode->UsingIpv6) {
1431 Udp6Rx = Udp6Token.Packet.RxData;
1432 ASSERT (Udp6Rx != NULL);
1433
1434 HeaderLen = 0;
1435 if (HeaderSize != NULL) {
1436 HeaderLen = MIN (*HeaderSize, Udp6Rx->DataLength);
1437 }
1438
1439 if (Udp6Rx->DataLength - HeaderLen > *BufferSize) {
1440 Status = EFI_BUFFER_TOO_SMALL;
1441 } else {
1442 if (HeaderSize != NULL) {
1443 *HeaderSize = HeaderLen;
1444 }
1445
1446 *BufferSize = Udp6Rx->DataLength - HeaderLen;
1447
1448 HeaderCopiedLen = 0;
1449 BufferCopiedLen = 0;
1450 for (FragmentIndex = 0; FragmentIndex < Udp6Rx->FragmentCount; FragmentIndex++) {
1451 FragmentLength = Udp6Rx->FragmentTable[FragmentIndex].FragmentLength;
1452 FragmentBuffer = Udp6Rx->FragmentTable[FragmentIndex].FragmentBuffer;
1453 if (HeaderCopiedLen + FragmentLength < HeaderLen) {
1454 //
1455 // Copy the header part of received data.
1456 //
1457 CopyMem ((UINT8 *)HeaderPtr + HeaderCopiedLen, FragmentBuffer, FragmentLength);
1458 HeaderCopiedLen += FragmentLength;
1459 } else if (HeaderCopiedLen < HeaderLen) {
1460 //
1461 // Copy the header part of received data.
1462 //
1463 CopiedLen = HeaderLen - HeaderCopiedLen;
1464 CopyMem ((UINT8 *)HeaderPtr + HeaderCopiedLen, FragmentBuffer, CopiedLen);
1465 HeaderCopiedLen += CopiedLen;
1466
1467 //
1468 // Copy the other part of received data.
1469 //
1470 CopyMem ((UINT8 *)BufferPtr + BufferCopiedLen, FragmentBuffer + CopiedLen, FragmentLength - CopiedLen);
1471 BufferCopiedLen += (FragmentLength - CopiedLen);
1472 } else {
1473 //
1474 // Copy the other part of received data.
1475 //
1476 CopyMem ((UINT8 *)BufferPtr + BufferCopiedLen, FragmentBuffer, FragmentLength);
1477 BufferCopiedLen += FragmentLength;
1478 }
1479 }
1480 }
1481
1482 //
1483 // Recycle the receiving buffer after copy to user.
1484 //
1485 gBS->SignalEvent (Udp6Rx->RecycleSignal);
1486 } else {
1487 Udp4Rx = Udp4Token.Packet.RxData;
1488 ASSERT (Udp4Rx != NULL);
1489
1490 HeaderLen = 0;
1491 if (HeaderSize != NULL) {
1492 HeaderLen = MIN (*HeaderSize, Udp4Rx->DataLength);
1493 }
1494
1495 if (Udp4Rx->DataLength - HeaderLen > *BufferSize) {
1496 Status = EFI_BUFFER_TOO_SMALL;
1497 } else {
1498 if (HeaderSize != NULL) {
1499 *HeaderSize = HeaderLen;
1500 }
1501
1502 *BufferSize = Udp4Rx->DataLength - HeaderLen;
1503
1504 HeaderCopiedLen = 0;
1505 BufferCopiedLen = 0;
1506 for (FragmentIndex = 0; FragmentIndex < Udp4Rx->FragmentCount; FragmentIndex++) {
1507 FragmentLength = Udp4Rx->FragmentTable[FragmentIndex].FragmentLength;
1508 FragmentBuffer = Udp4Rx->FragmentTable[FragmentIndex].FragmentBuffer;
1509 if (HeaderCopiedLen + FragmentLength < HeaderLen) {
1510 //
1511 // Copy the header part of received data.
1512 //
1513 CopyMem ((UINT8 *)HeaderPtr + HeaderCopiedLen, FragmentBuffer, FragmentLength);
1514 HeaderCopiedLen += FragmentLength;
1515 } else if (HeaderCopiedLen < HeaderLen) {
1516 //
1517 // Copy the header part of received data.
1518 //
1519 CopiedLen = HeaderLen - HeaderCopiedLen;
1520 CopyMem ((UINT8 *)HeaderPtr + HeaderCopiedLen, FragmentBuffer, CopiedLen);
1521 HeaderCopiedLen += CopiedLen;
1522
1523 //
1524 // Copy the other part of received data.
1525 //
1526 CopyMem ((UINT8 *)BufferPtr + BufferCopiedLen, FragmentBuffer + CopiedLen, FragmentLength - CopiedLen);
1527 BufferCopiedLen += (FragmentLength - CopiedLen);
1528 } else {
1529 //
1530 // Copy the other part of received data.
1531 //
1532 CopyMem ((UINT8 *)BufferPtr + BufferCopiedLen, FragmentBuffer, FragmentLength);
1533 BufferCopiedLen += FragmentLength;
1534 }
1535 }
1536 }
1537
1538 //
1539 // Recycle the receiving buffer after copy to user.
1540 //
1541 gBS->SignalEvent (Udp4Rx->RecycleSignal);
1542 }
1543 }
1544
1545 if (Mode->UsingIpv6) {
1546 Private->Udp6Read->Cancel (Private->Udp6Read, &Udp6Token);
1547 gBS->CloseEvent (Udp6Token.Event);
1548 } else {
1549 Private->Udp4Read->Cancel (Private->Udp4Read, &Udp4Token);
1550 gBS->CloseEvent (Udp4Token.Event);
1551 }
1552
1553 return Status;
1554}
1555
1589EFIAPI
1593 )
1594{
1595 EFI_STATUS Status;
1596 PXEBC_PRIVATE_DATA *Private;
1598 EFI_UDP4_CONFIG_DATA *Udp4Cfg;
1599 EFI_UDP6_CONFIG_DATA *Udp6Cfg;
1600 UINTN Index;
1601 BOOLEAN NeedPromiscuous;
1602 BOOLEAN AcceptPromiscuous;
1603 BOOLEAN AcceptBroadcast;
1604 BOOLEAN MultiCastUpdate;
1605
1606 if ((This == NULL) || (NewFilter == NULL)) {
1607 return EFI_INVALID_PARAMETER;
1608 }
1609
1610 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1611 Mode = Private->PxeBc.Mode;
1612 Status = EFI_SUCCESS;
1613 NeedPromiscuous = FALSE;
1614
1615 if (!Mode->Started) {
1616 return EFI_NOT_STARTED;
1617 }
1618
1619 for (Index = 0; Index < NewFilter->IpCnt; Index++) {
1620 ASSERT (Index < EFI_PXE_BASE_CODE_MAX_IPCNT);
1621 if (!Mode->UsingIpv6 &&
1622 IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter->IpList[Index].v4)))
1623 {
1624 //
1625 // IPv4 broadcast address should not be in IP filter.
1626 //
1627 return EFI_INVALID_PARAMETER;
1628 }
1629
1630 if (Mode->UsingIpv6) {
1631 if (((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0) &&
1632 NetIp6IsValidUnicast (&NewFilter->IpList[Index].v6))
1633 {
1634 NeedPromiscuous = TRUE;
1635 }
1636 } else if ((EFI_NTOHL (Mode->StationIp) != 0) &&
1637 (EFI_NTOHL (Mode->SubnetMask) != 0) &&
1638 IP4_NET_EQUAL (EFI_NTOHL (Mode->StationIp), EFI_NTOHL (NewFilter->IpList[Index].v4), EFI_NTOHL (Mode->SubnetMask.v4)) &&
1639 NetIp4IsUnicast (EFI_IP4 (NewFilter->IpList[Index].v4), EFI_NTOHL (Mode->SubnetMask)) &&
1640 ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0))
1641 {
1642 NeedPromiscuous = TRUE;
1643 }
1644 }
1645
1646 AcceptPromiscuous = FALSE;
1647 AcceptBroadcast = FALSE;
1648 MultiCastUpdate = FALSE;
1649
1650 if (NeedPromiscuous ||
1651 ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) != 0) ||
1652 ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) != 0))
1653 {
1654 //
1655 // Configure UDPv4/UDPv6 as promiscuous mode to receive all packets.
1656 //
1657 AcceptPromiscuous = TRUE;
1658 } else if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) != 0) {
1659 //
1660 // Configure UDPv4 to receive all broadcast packets.
1661 //
1662 AcceptBroadcast = TRUE;
1663 }
1664
1665 //
1666 // In multicast condition when Promiscuous FALSE and IpCnt no-zero.
1667 // Here check if there is any update of the multicast ip address. If yes,
1668 // we need leave the old multicast group (by Config UDP instance to NULL),
1669 // and join the new multicast group.
1670 //
1671 if (!AcceptPromiscuous) {
1672 if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0) {
1673 if (Mode->IpFilter.IpCnt != NewFilter->IpCnt) {
1674 MultiCastUpdate = TRUE;
1675 } else if (CompareMem (Mode->IpFilter.IpList, NewFilter->IpList, NewFilter->IpCnt * sizeof (EFI_IP_ADDRESS)) != 0 ) {
1676 MultiCastUpdate = TRUE;
1677 }
1678 }
1679 }
1680
1681 if (!Mode->UsingIpv6) {
1682 //
1683 // Check whether we need reconfigure the UDP4 instance.
1684 //
1685 Udp4Cfg = &Private->Udp4CfgData;
1686 if ((AcceptPromiscuous != Udp4Cfg->AcceptPromiscuous) ||
1687 (AcceptBroadcast != Udp4Cfg->AcceptBroadcast) || MultiCastUpdate)
1688 {
1689 //
1690 // Clear the UDP4 instance configuration, all joined groups will be left
1691 // during the operation.
1692 //
1693 Private->Udp4Read->Configure (Private->Udp4Read, NULL);
1694
1695 //
1696 // Configure the UDP instance with the new configuration.
1697 //
1698 Udp4Cfg->AcceptPromiscuous = AcceptPromiscuous;
1699 Udp4Cfg->AcceptBroadcast = AcceptBroadcast;
1700 Status = Private->Udp4Read->Configure (Private->Udp4Read, Udp4Cfg);
1701 if (EFI_ERROR (Status)) {
1702 return Status;
1703 }
1704
1705 //
1706 // In not Promiscuous mode, need to join the new multicast group.
1707 //
1708 if (!AcceptPromiscuous) {
1709 for (Index = 0; Index < NewFilter->IpCnt; ++Index) {
1710 if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter->IpList[Index].v4))) {
1711 //
1712 // Join the multicast group.
1713 //
1714 Status = Private->Udp4Read->Groups (Private->Udp4Read, TRUE, &NewFilter->IpList[Index].v4);
1715 if (EFI_ERROR (Status)) {
1716 return Status;
1717 }
1718 }
1719 }
1720 }
1721 }
1722 } else {
1723 //
1724 // Check whether we need reconfigure the UDP6 instance.
1725 //
1726 Udp6Cfg = &Private->Udp6CfgData;
1727 if ((AcceptPromiscuous != Udp6Cfg->AcceptPromiscuous) || MultiCastUpdate) {
1728 //
1729 // Clear the UDP6 instance configuration, all joined groups will be left
1730 // during the operation.
1731 //
1732 Private->Udp6Read->Configure (Private->Udp6Read, NULL);
1733
1734 //
1735 // Configure the UDP instance with the new configuration.
1736 //
1737 Udp6Cfg->AcceptPromiscuous = AcceptPromiscuous;
1738 Status = Private->Udp6Read->Configure (Private->Udp6Read, Udp6Cfg);
1739 if (EFI_ERROR (Status)) {
1740 return Status;
1741 }
1742
1743 //
1744 // In not Promiscuous mode, need to join the new multicast group.
1745 //
1746 if (!AcceptPromiscuous) {
1747 for (Index = 0; Index < NewFilter->IpCnt; ++Index) {
1748 if (IP6_IS_MULTICAST (&NewFilter->IpList[Index].v6)) {
1749 //
1750 // Join the multicast group.
1751 //
1752 Status = Private->Udp6Read->Groups (Private->Udp6Read, TRUE, &NewFilter->IpList[Index].v6);
1753 if (EFI_ERROR (Status)) {
1754 return Status;
1755 }
1756 }
1757 }
1758 }
1759 }
1760 }
1761
1762 //
1763 // Save the new IP filter into mode data.
1764 //
1765 CopyMem (&Mode->IpFilter, NewFilter, sizeof (Mode->IpFilter));
1766
1767 return Status;
1768}
1769
1796EFIAPI
1799 IN EFI_IP_ADDRESS *IpAddr,
1800 IN EFI_MAC_ADDRESS *MacAddr OPTIONAL
1801 )
1802{
1803 PXEBC_PRIVATE_DATA *Private;
1805 EFI_EVENT ResolvedEvent;
1806 EFI_STATUS Status;
1807 EFI_MAC_ADDRESS TempMac;
1808 EFI_MAC_ADDRESS ZeroMac;
1809 BOOLEAN IsResolved;
1810
1811 if ((This == NULL) || (IpAddr == NULL)) {
1812 return EFI_INVALID_PARAMETER;
1813 }
1814
1815 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1816 Mode = Private->PxeBc.Mode;
1817 ResolvedEvent = NULL;
1818 Status = EFI_SUCCESS;
1819 IsResolved = FALSE;
1820
1821 if (!Mode->Started) {
1822 return EFI_NOT_STARTED;
1823 }
1824
1825 if (Mode->UsingIpv6) {
1826 return EFI_UNSUPPORTED;
1827 }
1828
1829 //
1830 // Station address should be ready before do arp.
1831 //
1832 if (!Private->IsAddressOk) {
1833 return EFI_INVALID_PARAMETER;
1834 }
1835
1836 Mode->IcmpErrorReceived = FALSE;
1837 ZeroMem (&TempMac, sizeof (EFI_MAC_ADDRESS));
1838 ZeroMem (&ZeroMac, sizeof (EFI_MAC_ADDRESS));
1839
1840 if (!Mode->AutoArp) {
1841 //
1842 // If AutoArp is FALSE, only search in the current Arp cache.
1843 //
1844 PxeBcArpCacheUpdate (NULL, Private);
1845 if (!PxeBcCheckArpCache (Mode, &IpAddr->v4, &TempMac)) {
1846 Status = EFI_DEVICE_ERROR;
1847 goto ON_EXIT;
1848 }
1849 } else {
1850 Status = gBS->CreateEvent (
1851 EVT_NOTIFY_SIGNAL,
1852 TPL_NOTIFY,
1854 &IsResolved,
1855 &ResolvedEvent
1856 );
1857 if (EFI_ERROR (Status)) {
1858 goto ON_EXIT;
1859 }
1860
1861 //
1862 // If AutoArp is TRUE, try to send Arp request on initiative.
1863 //
1864 Status = Private->Arp->Request (Private->Arp, &IpAddr->v4, ResolvedEvent, &TempMac);
1865 if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
1866 goto ON_EXIT;
1867 }
1868
1869 while (!IsResolved) {
1870 if (CompareMem (&TempMac, &ZeroMac, sizeof (EFI_MAC_ADDRESS)) != 0) {
1871 break;
1872 }
1873 }
1874
1875 if (CompareMem (&TempMac, &ZeroMac, sizeof (EFI_MAC_ADDRESS)) != 0) {
1876 Status = EFI_SUCCESS;
1877 } else {
1878 Status = EFI_TIMEOUT;
1879 }
1880 }
1881
1882 //
1883 // Copy the Mac address to user if needed.
1884 //
1885 if ((MacAddr != NULL) && !EFI_ERROR (Status)) {
1886 CopyMem (MacAddr, &TempMac, sizeof (EFI_MAC_ADDRESS));
1887 }
1888
1889ON_EXIT:
1890 if (ResolvedEvent != NULL) {
1891 gBS->CloseEvent (ResolvedEvent);
1892 }
1893
1894 return Status;
1895}
1896
1930EFIAPI
1933 IN BOOLEAN *NewAutoArp OPTIONAL,
1934 IN BOOLEAN *NewSendGUID OPTIONAL,
1935 IN UINT8 *NewTTL OPTIONAL,
1936 IN UINT8 *NewToS OPTIONAL,
1937 IN BOOLEAN *NewMakeCallback OPTIONAL
1938 )
1939{
1940 PXEBC_PRIVATE_DATA *Private;
1942 EFI_GUID SystemGuid;
1943 EFI_STATUS Status;
1944
1945 if (This == NULL) {
1946 return EFI_INVALID_PARAMETER;
1947 }
1948
1949 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1950 Mode = Private->PxeBc.Mode;
1951
1952 if (!Mode->Started) {
1953 return EFI_NOT_STARTED;
1954 }
1955
1956 if (NewMakeCallback != NULL) {
1957 if (*NewMakeCallback) {
1958 //
1959 // Update the previous PxeBcCallback protocol.
1960 //
1961 Status = gBS->HandleProtocol (
1962 Mode->UsingIpv6 ? Private->Ip6Nic->Controller : Private->Ip4Nic->Controller,
1963 &gEfiPxeBaseCodeCallbackProtocolGuid,
1964 (VOID **)&Private->PxeBcCallback
1965 );
1966
1967 if (EFI_ERROR (Status) || (Private->PxeBcCallback->Callback == NULL)) {
1968 return EFI_INVALID_PARAMETER;
1969 }
1970 } else {
1971 Private->PxeBcCallback = NULL;
1972 }
1973
1974 Mode->MakeCallbacks = *NewMakeCallback;
1975 }
1976
1977 if (NewSendGUID != NULL) {
1978 if (*NewSendGUID && EFI_ERROR (NetLibGetSystemGuid (&SystemGuid))) {
1979 DEBUG ((DEBUG_WARN, "PXE: Failed to read system GUID from the smbios table!\n"));
1980 return EFI_INVALID_PARAMETER;
1981 }
1982
1983 Mode->SendGUID = *NewSendGUID;
1984 }
1985
1986 if (NewAutoArp != NULL) {
1987 Mode->AutoArp = *NewAutoArp;
1988 }
1989
1990 if (NewTTL != NULL) {
1991 Mode->TTL = *NewTTL;
1992 }
1993
1994 if (NewToS != NULL) {
1995 Mode->ToS = *NewToS;
1996 }
1997
1998 return EFI_SUCCESS;
1999}
2000
2023EFIAPI
2026 IN EFI_IP_ADDRESS *NewStationIp OPTIONAL,
2027 IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL
2028 )
2029{
2030 EFI_STATUS Status;
2031 PXEBC_PRIVATE_DATA *Private;
2033
2034 if (This == NULL) {
2035 return EFI_INVALID_PARAMETER;
2036 }
2037
2038 if ((NewStationIp != NULL) && !NetIp6IsValidUnicast (&NewStationIp->v6)) {
2039 return EFI_INVALID_PARAMETER;
2040 }
2041
2042 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
2043 Mode = Private->PxeBc.Mode;
2044 Status = EFI_SUCCESS;
2045
2046 if (!Mode->UsingIpv6 &&
2047 (NewSubnetMask != NULL) &&
2048 !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask->Addr[0])))
2049 {
2050 return EFI_INVALID_PARAMETER;
2051 }
2052
2053 if (!Mode->UsingIpv6 && (NewStationIp != NULL)) {
2054 if (IP4_IS_UNSPECIFIED (NTOHL (NewStationIp->Addr[0])) ||
2055 IP4_IS_LOCAL_BROADCAST (NTOHL (NewStationIp->Addr[0])) ||
2056 ((NewSubnetMask != NULL) && (NewSubnetMask->Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (NewStationIp->Addr[0]), NTOHL (NewSubnetMask->Addr[0]))))
2057 {
2058 return EFI_INVALID_PARAMETER;
2059 }
2060 }
2061
2062 if (!Mode->Started) {
2063 return EFI_NOT_STARTED;
2064 }
2065
2066 if (Mode->UsingIpv6 && (NewStationIp != NULL)) {
2067 //
2068 // Set the IPv6 address by Ip6Config protocol.
2069 //
2070 Status = PxeBcRegisterIp6Address (Private, &NewStationIp->v6);
2071 if (EFI_ERROR (Status)) {
2072 goto ON_EXIT;
2073 }
2074 }
2075
2076 if (NewStationIp != NULL) {
2077 CopyMem (&Mode->StationIp, NewStationIp, sizeof (EFI_IP_ADDRESS));
2078 CopyMem (&Private->StationIp, NewStationIp, sizeof (EFI_IP_ADDRESS));
2079 }
2080
2081 if (!Mode->UsingIpv6 && (NewSubnetMask != NULL)) {
2082 CopyMem (&Mode->SubnetMask, NewSubnetMask, sizeof (EFI_IP_ADDRESS));
2083 CopyMem (&Private->SubnetMask, NewSubnetMask, sizeof (EFI_IP_ADDRESS));
2084 }
2085
2086 Status = PxeBcFlushStationIp (Private, NewStationIp, NewSubnetMask);
2087 if (!EFI_ERROR (Status)) {
2088 Private->IsAddressOk = TRUE;
2089 }
2090
2091ON_EXIT:
2092 return Status;
2093}
2094
2128EFIAPI
2131 IN BOOLEAN *NewDhcpDiscoverValid OPTIONAL,
2132 IN BOOLEAN *NewDhcpAckReceived OPTIONAL,
2133 IN BOOLEAN *NewProxyOfferReceived OPTIONAL,
2134 IN BOOLEAN *NewPxeDiscoverValid OPTIONAL,
2135 IN BOOLEAN *NewPxeReplyReceived OPTIONAL,
2136 IN BOOLEAN *NewPxeBisReplyReceived OPTIONAL,
2137 IN EFI_PXE_BASE_CODE_PACKET *NewDhcpDiscover OPTIONAL,
2138 IN EFI_PXE_BASE_CODE_PACKET *NewDhcpAck OPTIONAL,
2139 IN EFI_PXE_BASE_CODE_PACKET *NewProxyOffer OPTIONAL,
2140 IN EFI_PXE_BASE_CODE_PACKET *NewPxeDiscover OPTIONAL,
2141 IN EFI_PXE_BASE_CODE_PACKET *NewPxeReply OPTIONAL,
2142 IN EFI_PXE_BASE_CODE_PACKET *NewPxeBisReply OPTIONAL
2143 )
2144{
2145 PXEBC_PRIVATE_DATA *Private;
2147
2148 if (This == NULL) {
2149 return EFI_INVALID_PARAMETER;
2150 }
2151
2152 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
2153 Mode = Private->PxeBc.Mode;
2154
2155 if (!Mode->Started) {
2156 return EFI_NOT_STARTED;
2157 }
2158
2159 if (NewDhcpDiscoverValid != NULL) {
2160 Mode->DhcpDiscoverValid = *NewDhcpDiscoverValid;
2161 }
2162
2163 if (NewDhcpAckReceived != NULL) {
2164 Mode->DhcpAckReceived = *NewDhcpAckReceived;
2165 }
2166
2167 if (NewProxyOfferReceived != NULL) {
2168 Mode->ProxyOfferReceived = *NewProxyOfferReceived;
2169 }
2170
2171 if (NewPxeDiscoverValid != NULL) {
2172 Mode->PxeDiscoverValid = *NewPxeDiscoverValid;
2173 }
2174
2175 if (NewPxeReplyReceived != NULL) {
2176 Mode->PxeReplyReceived = *NewPxeReplyReceived;
2177 }
2178
2179 if (NewPxeBisReplyReceived != NULL) {
2180 Mode->PxeBisReplyReceived = *NewPxeBisReplyReceived;
2181 }
2182
2183 if (NewDhcpDiscover != NULL) {
2184 CopyMem (&Mode->DhcpDiscover, NewDhcpDiscover, sizeof (EFI_PXE_BASE_CODE_PACKET));
2185 }
2186
2187 if (NewDhcpAck != NULL) {
2188 CopyMem (&Mode->DhcpAck, NewDhcpAck, sizeof (EFI_PXE_BASE_CODE_PACKET));
2189 }
2190
2191 if (NewProxyOffer != NULL) {
2192 CopyMem (&Mode->ProxyOffer, NewProxyOffer, sizeof (EFI_PXE_BASE_CODE_PACKET));
2193 }
2194
2195 if (NewPxeDiscover != NULL) {
2196 CopyMem (&Mode->PxeDiscover, NewPxeDiscover, sizeof (EFI_PXE_BASE_CODE_PACKET));
2197 }
2198
2199 if (NewPxeReply != NULL) {
2200 CopyMem (&Mode->PxeReply, NewPxeReply, sizeof (EFI_PXE_BASE_CODE_PACKET));
2201 }
2202
2203 if (NewPxeBisReply != NULL) {
2204 CopyMem (&Mode->PxeBisReply, NewPxeBisReply, sizeof (EFI_PXE_BASE_CODE_PACKET));
2205 }
2206
2207 return EFI_SUCCESS;
2208}
2209
2210EFI_PXE_BASE_CODE_PROTOCOL gPxeBcProtocolTemplate = {
2211 EFI_PXE_BASE_CODE_PROTOCOL_REVISION,
2224 NULL
2225};
2226
2255EFIAPI
2259 IN BOOLEAN Received,
2260 IN UINT32 PacketLength,
2261 IN EFI_PXE_BASE_CODE_PACKET *PacketPtr OPTIONAL
2262 )
2263{
2264 EFI_INPUT_KEY Key;
2265 EFI_STATUS Status;
2266
2267 //
2268 // Catch Ctrl-C or ESC to abort.
2269 //
2270 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
2271
2272 if (!EFI_ERROR (Status)) {
2273 if ((Key.ScanCode == SCAN_ESC) || (Key.UnicodeChar == (0x1F & 'c'))) {
2274 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT;
2275 }
2276 }
2277
2278 //
2279 // No print if receive packet
2280 //
2281 if (Received) {
2282 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
2283 }
2284
2285 //
2286 // Print only for three functions
2287 //
2288 switch (Function) {
2289 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP:
2290 //
2291 // Print only for open MTFTP packets, not every MTFTP packets
2292 //
2293 if ((PacketLength != 0) && (PacketPtr != NULL)) {
2294 if ((PacketPtr->Raw[0x1C] != 0x00) || (PacketPtr->Raw[0x1D] != 0x01)) {
2295 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
2296 }
2297 }
2298
2299 break;
2300
2301 case EFI_PXE_BASE_CODE_FUNCTION_DHCP:
2302 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER:
2303 break;
2304
2305 default:
2306 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
2307 }
2308
2309 if ((PacketLength != 0) && (PacketPtr != NULL)) {
2310 //
2311 // Print '.' when transmit a packet
2312 //
2313 AsciiPrint (".");
2314 }
2315
2316 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
2317}
2318
2319EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL gPxeBcCallBackTemplate = {
2322};
2323
2353EFIAPI
2356 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
2357 IN BOOLEAN BootPolicy,
2358 IN OUT UINTN *BufferSize,
2359 IN VOID *Buffer OPTIONAL
2360 )
2361{
2362 PXEBC_PRIVATE_DATA *Private;
2363 PXEBC_VIRTUAL_NIC *VirtualNic;
2365 BOOLEAN UsingIpv6;
2366 EFI_STATUS Status;
2367 EFI_STATUS MediaStatus;
2368
2369 if ((This == NULL) || (BufferSize == NULL) || (FilePath == NULL) || !IsDevicePathEnd (FilePath)) {
2370 return EFI_INVALID_PARAMETER;
2371 }
2372
2373 //
2374 // Only support BootPolicy
2375 //
2376 if (!BootPolicy) {
2377 return EFI_UNSUPPORTED;
2378 }
2379
2380 VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (This);
2381 Private = VirtualNic->Private;
2382 PxeBc = &Private->PxeBc;
2383 UsingIpv6 = FALSE;
2384 Status = EFI_DEVICE_ERROR;
2385
2386 //
2387 // Check media status before PXE start
2388 //
2389 MediaStatus = EFI_SUCCESS;
2390 NetLibDetectMediaWaitTimeout (Private->Controller, PXEBC_CHECK_MEDIA_WAITING_TIME, &MediaStatus);
2391 if (MediaStatus != EFI_SUCCESS) {
2392 return EFI_NO_MEDIA;
2393 }
2394
2395 //
2396 // Check whether the virtual nic is using IPv6 or not.
2397 //
2398 if (VirtualNic == Private->Ip6Nic) {
2399 UsingIpv6 = TRUE;
2400 }
2401
2402 //
2403 // Start Pxe Base Code to initialize PXE boot.
2404 //
2405 Status = PxeBc->Start (PxeBc, UsingIpv6);
2406 if ((Status == EFI_ALREADY_STARTED) && (UsingIpv6 != PxeBc->Mode->UsingIpv6)) {
2407 //
2408 // PxeBc protocol has already been started but not on the required IP version, restart it.
2409 //
2410 Status = PxeBc->Stop (PxeBc);
2411 if (!EFI_ERROR (Status)) {
2412 Status = PxeBc->Start (PxeBc, UsingIpv6);
2413 }
2414 }
2415
2416 if ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED)) {
2417 Status = PxeBcLoadBootFile (Private, BufferSize, Buffer);
2418 }
2419
2420 if ((Status != EFI_SUCCESS) &&
2421 (Status != EFI_UNSUPPORTED) &&
2422 (Status != EFI_BUFFER_TOO_SMALL))
2423 {
2424 //
2425 // There are three cases, which needn't stop pxebc here.
2426 // 1. success to download file.
2427 // 2. success to get file size.
2428 // 3. unsupported.
2429 //
2430 PxeBc->Stop (PxeBc);
2431 } else {
2432 //
2433 // The DHCP4 can have only one configured child instance so we need to stop
2434 // reset the DHCP4 child before we return. Otherwise these programs which
2435 // also need to use DHCP4 will be impacted.
2436 //
2437 if (!PxeBc->Mode->UsingIpv6) {
2438 Private->Dhcp4->Stop (Private->Dhcp4);
2439 Private->Dhcp4->Configure (Private->Dhcp4, NULL);
2440 }
2441 }
2442
2443 return Status;
2444}
2445
2446EFI_LOAD_FILE_PROTOCOL gLoadFileProtocolTemplate = { EfiPxeLoadFile };
UINT64 UINTN
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define MIN(a, b)
Definition: Base.h:1007
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE_WITH_EXTENDED_DATA(Type, Value, ExtendedData, ExtendedDataSize)
BOOLEAN EFIAPI NetIp4IsUnicast(IN IP4_ADDR Ip, IN IP4_ADDR NetMask)
Definition: DxeNetLib.c:683
BOOLEAN EFIAPI NetIp6IsValidUnicast(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:725
EFI_STATUS EFIAPI NetLibDetectMediaWaitTimeout(IN EFI_HANDLE ServiceHandle, IN UINT64 Timeout, OUT EFI_STATUS *MediaState)
Definition: DxeNetLib.c:2683
EFI_STATUS EFIAPI NetLibGetSystemGuid(OUT EFI_GUID *SystemGuid)
Definition: DxeNetLib.c:3325
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
EFI_PXE_BASE_CODE_TFTP_OPCODE
Definition: PxeBaseCode.h:192
#define EFI_PXE_BASE_CODE_MAX_IPCNT
Definition: PxeBaseCode.h:70
#define DEFAULT_TTL
Definition: PxeBaseCode.h:37
#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION
EFI_PXE_BASE_CODE_FUNCTION
EFI_PXE_BASE_CODE_CALLBACK_STATUS
EFI_STATUS PxeBcDiscoverBootServer(IN PXEBC_PRIVATE_DATA *Private, IN UINT16 Type, IN UINT16 *Layer, IN BOOLEAN UseBis, IN EFI_IP_ADDRESS *DestIp, IN UINT16 IpCount, IN EFI_PXE_BASE_CODE_SRVLIST *SrvList)
Definition: PxeBcBoot.c:850
EFI_STATUS PxeBcExtractDiscoverInfo(IN PXEBC_PRIVATE_DATA *Private, IN UINT16 Type, IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO **DiscoverInfo, OUT PXEBC_BOOT_SVR_ENTRY **BootEntry, OUT EFI_PXE_BASE_CODE_SRVLIST **SrvList)
Definition: PxeBcBoot.c:729
EFI_STATUS PxeBcLoadBootFile(IN PXEBC_PRIVATE_DATA *Private, IN OUT UINTN *BufferSize, IN VOID *Buffer OPTIONAL)
Definition: PxeBcBoot.c:1142
EFI_STATUS PxeBcSetIp4Policy(IN PXEBC_PRIVATE_DATA *Private)
Definition: PxeBcDhcp4.c:1609
VOID PxeBcSeedDhcp4Packet(OUT EFI_DHCP4_PACKET *Seed, IN EFI_UDP4_PROTOCOL *Udp4)
Definition: PxeBcDhcp4.c:383
EFI_STATUS PxeBcDhcp4Dora(IN PXEBC_PRIVATE_DATA *Private, IN EFI_DHCP4_PROTOCOL *Dhcp4)
Definition: PxeBcDhcp4.c:1657
EFI_STATUS PxeBcParseDhcp4Packet(IN PXEBC_DHCP4_PACKET_CACHE *Cache4)
Definition: PxeBcDhcp4.c:445
EFI_STATUS PxeBcRegisterIp6Address(IN PXEBC_PRIVATE_DATA *Private, IN EFI_IPv6_ADDRESS *Address)
Definition: PxeBcDhcp6.c:1696
VOID PxeBcUnregisterIp6Address(IN PXEBC_PRIVATE_DATA *Private)
Definition: PxeBcDhcp6.c:1547
EFI_STATUS PxeBcSetIp6Policy(IN PXEBC_PRIVATE_DATA *Private)
Definition: PxeBcDhcp6.c:1881
EFI_STATUS PxeBcParseDhcp6Packet(IN PXEBC_DHCP6_PACKET_CACHE *Cache6)
Definition: PxeBcDhcp6.c:632
EFI_STATUS PxeBcDhcp6Sarr(IN PXEBC_PRIVATE_DATA *Private, IN EFI_DHCP6_PROTOCOL *Dhcp6)
Definition: PxeBcDhcp6.c:2335
EFI_STATUS EFIAPI EfiPxeBcUdpRead(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN UINT16 OpFlags, IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL, IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL, IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL, IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL, IN UINTN *HeaderSize OPTIONAL, IN VOID *HeaderPtr OPTIONAL, IN OUT UINTN *BufferSize, IN VOID *BufferPtr)
Definition: PxeBcImpl.c:1284
EFI_STATUS EFIAPI EfiPxeBcSetStationIP(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN EFI_IP_ADDRESS *NewStationIp OPTIONAL, IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL)
Definition: PxeBcImpl.c:2024
EFI_STATUS EFIAPI EfiPxeBcStart(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN BOOLEAN UseIpv6)
Definition: PxeBcImpl.c:43
EFI_STATUS EFIAPI EfiPxeBcSetIpFilter(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN EFI_PXE_BASE_CODE_IP_FILTER *NewFilter)
Definition: PxeBcImpl.c:1590
EFI_STATUS EFIAPI EfiPxeBcSetParameters(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN BOOLEAN *NewAutoArp OPTIONAL, IN BOOLEAN *NewSendGUID OPTIONAL, IN UINT8 *NewTTL OPTIONAL, IN UINT8 *NewToS OPTIONAL, IN BOOLEAN *NewMakeCallback OPTIONAL)
Definition: PxeBcImpl.c:1931
EFI_STATUS EFIAPI EfiPxeBcSetPackets(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN BOOLEAN *NewDhcpDiscoverValid OPTIONAL, IN BOOLEAN *NewDhcpAckReceived OPTIONAL, IN BOOLEAN *NewProxyOfferReceived OPTIONAL, IN BOOLEAN *NewPxeDiscoverValid OPTIONAL, IN BOOLEAN *NewPxeReplyReceived OPTIONAL, IN BOOLEAN *NewPxeBisReplyReceived OPTIONAL, IN EFI_PXE_BASE_CODE_PACKET *NewDhcpDiscover OPTIONAL, IN EFI_PXE_BASE_CODE_PACKET *NewDhcpAck OPTIONAL, IN EFI_PXE_BASE_CODE_PACKET *NewProxyOffer OPTIONAL, IN EFI_PXE_BASE_CODE_PACKET *NewPxeDiscover OPTIONAL, IN EFI_PXE_BASE_CODE_PACKET *NewPxeReply OPTIONAL, IN EFI_PXE_BASE_CODE_PACKET *NewPxeBisReply OPTIONAL)
Definition: PxeBcImpl.c:2129
EFI_STATUS EFIAPI EfiPxeLoadFile(IN EFI_LOAD_FILE_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN BOOLEAN BootPolicy, IN OUT UINTN *BufferSize, IN VOID *Buffer OPTIONAL)
Definition: PxeBcImpl.c:2354
EFI_STATUS EFIAPI EfiPxeBcDhcp(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN BOOLEAN SortOffers)
Definition: PxeBcImpl.c:424
EFI_STATUS EFIAPI EfiPxeBcMtftp(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, IN OUT VOID *BufferPtr OPTIONAL, IN BOOLEAN Overwrite, IN OUT UINT64 *BufferSize, IN UINTN *BlockSize OPTIONAL, IN EFI_IP_ADDRESS *ServerIp, IN UINT8 *Filename, IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL, IN BOOLEAN DontUseBuffer)
Definition: PxeBcImpl.c:834
EFI_STATUS EFIAPI EfiPxeBcStop(IN EFI_PXE_BASE_CODE_PROTOCOL *This)
Definition: PxeBcImpl.c:293
EFI_STATUS EFIAPI EfiPxeBcUdpWrite(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN UINT16 OpFlags, IN EFI_IP_ADDRESS *DestIp, IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort, IN EFI_IP_ADDRESS *GatewayIp OPTIONAL, IN EFI_IP_ADDRESS *SrcIp OPTIONAL, IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL, IN UINTN *HeaderSize OPTIONAL, IN VOID *HeaderPtr OPTIONAL, IN UINTN *BufferSize, IN VOID *BufferPtr)
Definition: PxeBcImpl.c:1073
EFI_PXE_BASE_CODE_CALLBACK_STATUS EFIAPI EfiPxeLoadFileCallback(IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *This, IN EFI_PXE_BASE_CODE_FUNCTION Function, IN BOOLEAN Received, IN UINT32 PacketLength, IN EFI_PXE_BASE_CODE_PACKET *PacketPtr OPTIONAL)
Definition: PxeBcImpl.c:2256
EFI_STATUS EFIAPI EfiPxeBcArp(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN EFI_IP_ADDRESS *IpAddr, IN EFI_MAC_ADDRESS *MacAddr OPTIONAL)
Definition: PxeBcImpl.c:1797
EFI_STATUS EFIAPI EfiPxeBcDiscover(IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN UINT16 Type, IN UINT16 *Layer, IN BOOLEAN UseBis, IN EFI_PXE_BASE_CODE_DISCOVER_INFO *Info OPTIONAL)
Definition: PxeBcImpl.c:539
EFI_STATUS PxeBcTftpGetFileSize(IN PXEBC_PRIVATE_DATA *Private, IN VOID *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN OUT UINT64 *BufferSize)
Definition: PxeBcMtftp.c:993
EFI_STATUS PxeBcTftpReadDirectory(IN PXEBC_PRIVATE_DATA *Private, IN VOID *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize, IN BOOLEAN DontUseBuffer)
Definition: PxeBcMtftp.c:1145
EFI_STATUS PxeBcTftpReadFile(IN PXEBC_PRIVATE_DATA *Private, IN VOID *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize, IN BOOLEAN DontUseBuffer)
Definition: PxeBcMtftp.c:1041
EFI_STATUS PxeBcTftpWriteFile(IN PXEBC_PRIVATE_DATA *Private, IN VOID *Config, IN UINT8 *Filename, IN BOOLEAN Overwrite, IN UINTN *BlockSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize)
Definition: PxeBcMtftp.c:1094
VOID EFIAPI PxeBcArpCacheUpdate(IN EFI_EVENT Event, IN VOID *Context)
Definition: PxeBcSupport.c:180
EFI_STATUS PxeBcUdp4Read(IN EFI_UDP4_PROTOCOL *Udp4, IN EFI_UDP4_COMPLETION_TOKEN *Token, IN EFI_PXE_BASE_CODE_MODE *Mode, IN EFI_EVENT TimeoutEvent, IN UINT16 OpFlags, IN BOOLEAN *IsDone, OUT BOOLEAN *IsMatched, IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL, IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL, IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL, IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL)
EFI_STATUS PxeBcUdp4Write(IN EFI_UDP4_PROTOCOL *Udp4, IN EFI_UDP4_SESSION_DATA *Session, IN EFI_EVENT TimeoutEvent, IN EFI_IPv4_ADDRESS *Gateway OPTIONAL, IN UINTN *HeaderSize OPTIONAL, IN VOID *HeaderPtr OPTIONAL, IN UINTN *BufferSize, IN VOID *BufferPtr)
Definition: PxeBcSupport.c:639
EFI_STATUS PxeBcFlushStationIp(PXEBC_PRIVATE_DATA *Private, EFI_IP_ADDRESS *StationIp OPTIONAL, EFI_IP_ADDRESS *SubnetMask OPTIONAL)
Definition: PxeBcSupport.c:24
EFI_STATUS PxeBcUdp6Write(IN EFI_UDP6_PROTOCOL *Udp6, IN EFI_UDP6_SESSION_DATA *Session, IN EFI_EVENT TimeoutEvent, IN UINTN *HeaderSize OPTIONAL, IN VOID *HeaderPtr OPTIONAL, IN UINTN *BufferSize, IN VOID *BufferPtr)
Definition: PxeBcSupport.c:745
EFI_STATUS PxeBcUdp6Read(IN EFI_UDP6_PROTOCOL *Udp6, IN EFI_UDP6_COMPLETION_TOKEN *Token, IN EFI_PXE_BASE_CODE_MODE *Mode, IN EFI_EVENT TimeoutEvent, IN UINT16 OpFlags, IN BOOLEAN *IsDone, OUT BOOLEAN *IsMatched, IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL, IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL, IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL, IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL)
VOID EFIAPI PxeBcIcmp6ErrorUpdate(IN EFI_EVENT Event, IN VOID *Context)
Definition: PxeBcSupport.c:493
EFI_STATUS PxeBcConfigUdp6Write(IN EFI_UDP6_PROTOCOL *Udp6, IN EFI_IPv6_ADDRESS *StationIp, IN OUT UINT16 *SrcPort)
Definition: PxeBcSupport.c:583
VOID EFIAPI PxeBcCommonNotify(IN EFI_EVENT Event, IN VOID *Context)
Definition: PxeBcSupport.c:123
VOID EFIAPI PxeBcIcmpErrorUpdate(IN EFI_EVENT Event, IN VOID *Context)
Definition: PxeBcSupport.c:361
BOOLEAN PxeBcCheckArpCache(IN EFI_PXE_BASE_CODE_MODE *Mode, IN EFI_IPv4_ADDRESS *Ip4Addr, OUT EFI_MAC_ADDRESS *MacAddress)
Definition: PxeBcSupport.c:144
EFI_STATUS PxeBcConfigUdp4Write(IN EFI_UDP4_PROTOCOL *Udp4, IN EFI_IPv4_ADDRESS *StationIp, IN EFI_IPv4_ADDRESS *SubnetMask, IN EFI_IPv4_ADDRESS *Gateway, IN OUT UINT16 *SrcPort, IN BOOLEAN DoNotFragment, IN UINT8 Ttl, IN UINT8 ToS)
Definition: PxeBcSupport.c:519
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_NETWORK_UNREACHABLE
Definition: UefiBaseType.h:166
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_SYSTEM_TABLE * gST
EFI_BOOT_SERVICES * gBS
UINTN EFIAPI AsciiPrint(IN CONST CHAR8 *Format,...)
Definition: UefiLibPrint.c:250
@ TimerCancel
Definition: UefiSpec.h:531
@ TimerRelative
Definition: UefiSpec.h:539
@ TimerPeriodic
Definition: UefiSpec.h:535
EFI_PXE_BASE_CODE_MODE * Mode
Definition: PxeBaseCode.h:928
UINT32 Length
Definition: Dhcp4.h:79
UINT32 Size
Definition: Dhcp4.h:74
UINT32 Size
Definition: Dhcp6.h:185
UINT32 Length
Definition: Dhcp6.h:190
EFI_EVENT Event
Definition: Ip4.h:244
EFI_IPv4_ADDRESS SubnetMask
Definition: Ip4.h:98
EFI_IPv4_ADDRESS StationAddress
Definition: Ip4.h:94
EFI_STATUS Status
Definition: Ip6.h:536
EFI_EVENT Event
Definition: Ip6.h:522
EFI_IPv6_ADDRESS StationAddress
Definition: Ip6.h:188
EFI_IPv6_ADDRESS StationIp
Definition: Mtftp6.h:226
EFI_IPv6_ADDRESS ServerIp
Definition: Mtftp6.h:234
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * ConIn
Definition: UefiSpec.h:2053
EFI_UDP6_RECEIVE_DATA * RxData
Definition: Udp6.h:288
BOOLEAN AcceptPromiscuous
Definition: Udp6.h:122
EFI_IPv6_ADDRESS StationAddress
Definition: Udp6.h:161
UINT32 FragmentLength
Length of the fragment data buffer.
Definition: Udp6.h:86
VOID * FragmentBuffer
Pointer to the fragment data buffer.
Definition: Udp6.h:87
UINT32 DataLength
Definition: Udp6.h:237
EFI_UDP6_FRAGMENT_DATA FragmentTable[1]
Definition: Udp6.h:245
EFI_EVENT RecycleSignal
Definition: Udp6.h:228
UINT32 FragmentCount
Definition: Udp6.h:241
EFI_IPv6_ADDRESS DestinationAddress
Definition: Udp6.h:110
UINT16 SourcePort
Definition: Udp6.h:105
EFI_IPv6_ADDRESS SourceAddress
Definition: Udp6.h:100
UINT16 DestinationPort
Definition: Udp6.h:115
Definition: Base.h:213