]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c
1. Enabled SetIpFilter() in UefiPxeBcDxe module.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / UefiPxeBcDxe / PxeBcImpl.c
1 /** @file
2
3 Copyright (c) 2007 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
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.
11
12 Module Name:
13
14 PxeBcImpl.c
15
16 Abstract:
17
18 Interface routines for PxeBc
19
20
21 **/
22
23
24 #include "PxeBcImpl.h"
25
26
27 /**
28 GC_NOTO: Add function description
29
30 @param This GC_NOTO: add argument
31 description
32 @param UseIpv6 GC_NOTO: add argument
33 description
34
35 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
36 return value
37 @retval EFI_ALREADY_STARTED GC_NOTO: Add description for
38 return value
39 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
40 return value
41 @retval EFI_SUCCESS GC_NOTO: Add description for
42 return value
43
44 **/
45 EFI_STATUS
46 EFIAPI
47 EfiPxeBcStart (
48 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
49 IN BOOLEAN UseIpv6
50 )
51 {
52 PXEBC_PRIVATE_DATA *Private;
53 EFI_PXE_BASE_CODE_MODE *Mode;
54 EFI_STATUS Status;
55
56 if (This == NULL) {
57 return EFI_INVALID_PARAMETER;
58 }
59
60 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
61 Mode = Private->PxeBc.Mode;
62
63 if (Mode->Started) {
64 return EFI_ALREADY_STARTED;
65 }
66
67 if (UseIpv6) {
68 //
69 // IPv6 is not supported now.
70 //
71 return EFI_UNSUPPORTED;
72 }
73
74 //
75 // Configure the udp4 instance to let it receive data
76 //
77 Status = Private->Udp4->Configure (Private->Udp4, &Private->Udp4CfgData);
78 if (EFI_ERROR (Status)) {
79 return Status;
80 }
81
82 Private->AddressIsOk = FALSE;
83
84 ZeroMem (Mode, sizeof (EFI_PXE_BASE_CODE_MODE));
85
86 Mode->Started = TRUE;
87 Mode->TTL = DEFAULT_TTL;
88 Mode->ToS = DEFAULT_ToS;
89 Mode->AutoArp = TRUE;
90
91 return EFI_SUCCESS;
92 }
93
94
95 /**
96 GC_NOTO: Add function description
97
98 @param This GC_NOTO: add argument
99 description
100
101 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
102 return value
103 @retval EFI_NOT_STARTED GC_NOTO: Add description for
104 return value
105 @retval EFI_SUCCESS GC_NOTO: Add description for
106 return value
107
108 **/
109 EFI_STATUS
110 EFIAPI
111 EfiPxeBcStop (
112 IN EFI_PXE_BASE_CODE_PROTOCOL *This
113 )
114 {
115 PXEBC_PRIVATE_DATA *Private;
116 EFI_PXE_BASE_CODE_MODE *Mode;
117
118 if (This == NULL) {
119 return EFI_INVALID_PARAMETER;
120 }
121
122 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
123 Mode = Private->PxeBc.Mode;
124
125 if (!Mode->Started) {
126 return EFI_NOT_STARTED;
127 }
128
129 Mode->Started = FALSE;
130
131 //
132 // Reset and leave joined groups
133 //
134 Private->Udp4->Groups (Private->Udp4, FALSE, NULL);
135
136 Private->Udp4->Configure (Private->Udp4, NULL);
137
138 Private->Dhcp4->Stop (Private->Dhcp4);
139 Private->Dhcp4->Configure (Private->Dhcp4, NULL);
140
141 Private->FileSize = 0;
142
143 return EFI_SUCCESS;
144 }
145
146
147 /**
148 GC_NOTO: Add function description
149
150 @param This GC_NOTO: add argument
151 description
152 @param SortOffers GC_NOTO: add argument
153 description
154
155 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
156 return value
157 @retval EFI_NOT_STARTED GC_NOTO: Add description for
158 return value
159
160 **/
161 EFI_STATUS
162 EFIAPI
163 EfiPxeBcDhcp (
164 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
165 IN BOOLEAN SortOffers
166 )
167 {
168 PXEBC_PRIVATE_DATA *Private;
169 EFI_PXE_BASE_CODE_MODE *Mode;
170 EFI_DHCP4_PROTOCOL *Dhcp4;
171 EFI_DHCP4_CONFIG_DATA Dhcp4CfgData;
172 EFI_DHCP4_MODE_DATA Dhcp4Mode;
173 EFI_DHCP4_PACKET_OPTION *OptList[PXEBC_DHCP4_MAX_OPTION_NUM];
174 UINT32 OptCount;
175 UINT32 DiscoverTimeout;
176 UINTN Index;
177 EFI_STATUS Status;
178 EFI_ARP_CONFIG_DATA ArpConfigData;
179
180 if (This == NULL) {
181 return EFI_INVALID_PARAMETER;
182 }
183
184 Status = EFI_SUCCESS;
185 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
186 Mode = Private->PxeBc.Mode;
187 Dhcp4 = Private->Dhcp4;
188 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DHCP;
189 Private->SortOffers = SortOffers;
190
191 if (!Mode->Started) {
192 return EFI_NOT_STARTED;
193 }
194 //
195 // Initialize the DHCP options and build the option list
196 //
197 OptCount = PxeBcBuildDhcpOptions (Private, OptList, TRUE);
198
199 //
200 // Set the DHCP4 config data.
201 //
202 ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));
203 Dhcp4CfgData.OptionCount = OptCount;
204 Dhcp4CfgData.OptionList = OptList;
205 Dhcp4CfgData.Dhcp4Callback = PxeBcDhcpCallBack;
206 Dhcp4CfgData.CallbackContext = Private;
207 Dhcp4CfgData.DiscoverTryCount = 1;
208 Dhcp4CfgData.DiscoverTimeout = &DiscoverTimeout;
209
210 for (Index = 0; Index < PXEBC_DHCP4_DISCOVER_RETRIES; Index++) {
211 //
212 // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.
213 //
214 DiscoverTimeout = (PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT << Index);
215
216 Status = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);
217 if (EFI_ERROR (Status)) {
218 break;
219 }
220 //
221 // Zero those arrays to record the varies numbers of DHCP OFFERS.
222 //
223 Private->NumOffers = 0;
224 Private->BootpIndex = 0;
225 ZeroMem (Private->ServerCount, sizeof (Private->ServerCount));
226 ZeroMem (Private->ProxyIndex, sizeof (Private->ProxyIndex));
227
228 Status = Dhcp4->Start (Dhcp4, NULL);
229 if (EFI_ERROR (Status)) {
230 if (Status == EFI_TIMEOUT) {
231 //
232 // If no response is received or all received offers don't match
233 // the PXE boot requirements, EFI_TIMEOUT will be returned.
234 //
235 continue;
236 }
237 //
238 // Other error status means the DHCP really fails.
239 //
240 break;
241 }
242
243 Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
244 if (EFI_ERROR (Status)) {
245 break;
246 }
247
248 ASSERT (Dhcp4Mode.State == Dhcp4Bound);
249
250 CopyMem (&Private->StationIp, &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS));
251 CopyMem (&Private->SubnetMask, &Dhcp4Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
252 CopyMem (&Private->GatewayIp, &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
253
254 //
255 // Check the selected offer to see whether BINL is required, if no or BINL is
256 // finished, set the various Mode members.
257 //
258 Status = PxeBcCheckSelectedOffer (Private);
259 if (!EFI_ERROR (Status)) {
260 break;
261 }
262 }
263
264 if (EFI_ERROR (Status)) {
265 Dhcp4->Stop (Dhcp4);
266 Dhcp4->Configure (Dhcp4, NULL);
267 } else {
268 //
269 // Remove the previously configured option list and callback function
270 //
271 ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));
272 Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);
273
274 Private->AddressIsOk = TRUE;
275
276 if (!Mode->UsingIpv6) {
277 //
278 // If in IPv4 mode, configure the corresponding ARP with this new
279 // station IP address.
280 //
281 ZeroMem (&ArpConfigData, sizeof (EFI_ARP_CONFIG_DATA));
282
283 ArpConfigData.SwAddressType = 0x0800;
284 ArpConfigData.SwAddressLength = sizeof (EFI_IPv4_ADDRESS);
285 ArpConfigData.StationAddress = &Private->StationIp.v4;
286
287 Private->Arp->Configure (Private->Arp, NULL);
288 Private->Arp->Configure (Private->Arp, &ArpConfigData);
289 }
290 }
291
292 return Status;
293 }
294
295
296 /**
297 GC_NOTO: Add function description
298
299 @param This GC_NOTO: add argument
300 description
301 @param Type GC_NOTO: add argument
302 description
303 @param Layer GC_NOTO: add argument
304 description
305 @param UseBis GC_NOTO: add argument
306 description
307 @param Info GC_NOTO: add argument
308 description
309
310 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
311 return value
312 @retval EFI_NOT_STARTED GC_NOTO: Add description for
313 return value
314 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
315 return value
316 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
317 return value
318 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
319 return value
320 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
321 return value
322
323 **/
324 EFI_STATUS
325 EFIAPI
326 EfiPxeBcDiscover (
327 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
328 IN UINT16 Type,
329 IN UINT16 *Layer,
330 IN BOOLEAN UseBis,
331 IN EFI_PXE_BASE_CODE_DISCOVER_INFO *Info OPTIONAL
332 )
333 {
334 PXEBC_PRIVATE_DATA *Private;
335 EFI_PXE_BASE_CODE_MODE *Mode;
336 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo;
337 EFI_PXE_BASE_CODE_SRVLIST *SrvList;
338 EFI_PXE_BASE_CODE_SRVLIST DefaultSrvList;
339 PXEBC_CACHED_DHCP4_PACKET *Packet;
340 PXEBC_VENDOR_OPTION *VendorOpt;
341 UINT16 Index;
342 EFI_STATUS Status;
343 PXEBC_BOOT_SVR_ENTRY *BootSvrEntry;
344
345 if (This == NULL) {
346 return EFI_INVALID_PARAMETER;
347 }
348
349 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
350 Mode = Private->PxeBc.Mode;
351 BootSvrEntry = NULL;
352 SrvList = NULL;
353 Status = EFI_DEVICE_ERROR;
354 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER;
355
356 if (!Private->AddressIsOk) {
357 return EFI_INVALID_PARAMETER;
358 }
359
360 if (!Mode->Started) {
361 return EFI_NOT_STARTED;
362 }
363
364 //
365 // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
366 // use the previous setting;
367 // If info isn't offered,
368 // use the cached DhcpAck and ProxyOffer packets.
369 //
370 if (*Layer != EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL) {
371
372 if (!Mode->PxeDiscoverValid || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {
373
374 return EFI_INVALID_PARAMETER;
375 }
376
377 DefaultInfo.IpCnt = 1;
378 DefaultInfo.UseUCast = TRUE;
379
380 DefaultSrvList.Type = Type;
381 DefaultSrvList.AcceptAnyResponse = FALSE;
382 DefaultSrvList.IpAddr.Addr[0] = Private->ServerIp.Addr[0];
383
384 SrvList = &DefaultSrvList;
385 Info = &DefaultInfo;
386 } else if (Info == NULL) {
387 //
388 // Create info by the cached packet before
389 //
390 Packet = (Mode->ProxyOfferReceived) ? &Private->ProxyOffer : &Private->Dhcp4Ack;
391 VendorOpt = &Packet->PxeVendorOption;
392
393 if (!Mode->DhcpAckReceived || !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt->BitMap)) {
394 //
395 // Address is not acquired or no discovery options.
396 //
397 return EFI_INVALID_PARAMETER;
398 }
399
400 DefaultInfo.UseMCast = (BOOLEAN)!IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl);
401 DefaultInfo.UseBCast = (BOOLEAN)!IS_DISABLE_BCAST_DISCOVER (VendorOpt->DiscoverCtrl);
402 DefaultInfo.MustUseList = (BOOLEAN) IS_ENABLE_USE_SERVER_LIST (VendorOpt->DiscoverCtrl);
403 DefaultInfo.UseUCast = DefaultInfo.MustUseList;
404
405 if (DefaultInfo.UseMCast) {
406 //
407 // Get the multicast discover ip address from vendor option.
408 //
409 CopyMem (&DefaultInfo.ServerMCastIp.Addr, &VendorOpt->DiscoverMcastIp, sizeof (EFI_IPv4_ADDRESS));
410 }
411
412 DefaultInfo.IpCnt = 0;
413
414 if (DefaultInfo.MustUseList) {
415 BootSvrEntry = VendorOpt->BootSvr;
416 Status = EFI_INVALID_PARAMETER;
417
418 while (((UINT8) (BootSvrEntry - VendorOpt->BootSvr)) < VendorOpt->BootSvrLen) {
419
420 if (BootSvrEntry->Type == HTONS (Type)) {
421 Status = EFI_SUCCESS;
422 break;
423 }
424
425 BootSvrEntry = GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry);
426 }
427
428 if (EFI_ERROR (Status)) {
429 return Status;
430 }
431
432 DefaultInfo.IpCnt = BootSvrEntry->IpCnt;
433 }
434
435 Info = &DefaultInfo;
436 } else {
437
438 SrvList = Info->SrvList;
439
440 if (!SrvList[0].AcceptAnyResponse) {
441
442 for (Index = 1; Index < Info->IpCnt; Index++) {
443 if (SrvList[Index].AcceptAnyResponse) {
444 break;
445 }
446 }
447
448 if (Index != Info->IpCnt) {
449 return EFI_INVALID_PARAMETER;
450 }
451 }
452 }
453
454 if ((!Info->UseUCast && !Info->UseBCast && !Info->UseMCast) || (Info->MustUseList && Info->IpCnt == 0)) {
455
456 return EFI_INVALID_PARAMETER;
457 }
458 //
459 // Execute discover by UniCast/BroadCast/MultiCast
460 //
461 if (Info->UseUCast) {
462
463 for (Index = 0; Index < Info->IpCnt; Index++) {
464
465 if (BootSvrEntry == NULL) {
466 Private->ServerIp.Addr[0] = SrvList[Index].IpAddr.Addr[0];
467 } else {
468 CopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS));
469 }
470
471 Status = PxeBcDiscvBootService (
472 Private,
473 Type,
474 Layer,
475 UseBis,
476 &SrvList[Index].IpAddr,
477 0,
478 NULL,
479 TRUE,
480 &Private->PxeReply.Packet.Ack
481 );
482 }
483
484 } else if (Info->UseMCast) {
485
486 Status = PxeBcDiscvBootService (
487 Private,
488 Type,
489 Layer,
490 UseBis,
491 &Info->ServerMCastIp,
492 0,
493 NULL,
494 TRUE,
495 &Private->PxeReply.Packet.Ack
496 );
497
498 } else if (Info->UseBCast) {
499
500 Status = PxeBcDiscvBootService (
501 Private,
502 Type,
503 Layer,
504 UseBis,
505 NULL,
506 Info->IpCnt,
507 SrvList,
508 TRUE,
509 &Private->PxeReply.Packet.Ack
510 );
511 }
512
513 if (EFI_ERROR (Status) || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {
514
515 Status = EFI_DEVICE_ERROR;
516 } else {
517 PxeBcParseCachedDhcpPacket (&Private->PxeReply);
518 }
519
520 if (Mode->PxeBisReplyReceived) {
521 CopyMem (&Private->ServerIp, &Mode->PxeReply.Dhcpv4.BootpSiAddr, sizeof (EFI_IPv4_ADDRESS));
522 }
523
524 return Status;
525 }
526
527
528 /**
529 GC_NOTO: Add function description
530
531 @param This GC_NOTO: add argument
532 description
533 @param Operation GC_NOTO: add argument
534 description
535 @param BufferPtr GC_NOTO: add argument
536 description
537 @param Overwrite GC_NOTO: add argument
538 description
539 @param BufferSize GC_NOTO: add argument
540 description
541 @param BlockSize GC_NOTO: add argument
542 description
543 @param ServerIp GC_NOTO: add argument
544 description
545 @param Filename GC_NOTO: add argument
546 description
547 @param Info GC_NOTO: add argument
548 description
549 @param DontUseBuffer GC_NOTO: add argument
550 description
551
552 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
553 return value
554
555 **/
556 EFI_STATUS
557 EFIAPI
558 EfiPxeBcMtftp (
559 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
560 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation,
561 IN OUT VOID *BufferPtr,
562 IN BOOLEAN Overwrite,
563 IN OUT UINT64 *BufferSize,
564 IN UINTN *BlockSize OPTIONAL,
565 IN EFI_IP_ADDRESS *ServerIp,
566 IN UINT8 *Filename,
567 IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL,
568 IN BOOLEAN DontUseBuffer
569 )
570 {
571 PXEBC_PRIVATE_DATA *Private;
572 EFI_MTFTP4_CONFIG_DATA Mtftp4Config;
573 EFI_STATUS Status;
574
575 if ((This == NULL) ||
576 (Filename == NULL) ||
577 (BufferSize == NULL) ||
578 ((ServerIp == NULL) || !Ip4IsUnicast (NTOHL (ServerIp->Addr[0]), 0)) ||
579 ((BufferPtr == NULL) && DontUseBuffer) ||
580 ((BlockSize != NULL) && (*BlockSize < 512))) {
581
582 return EFI_INVALID_PARAMETER;
583 }
584
585 Status = EFI_DEVICE_ERROR;
586 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
587
588 Mtftp4Config.UseDefaultSetting = FALSE;
589 Mtftp4Config.TimeoutValue = PXEBC_MTFTP_TIMEOUT;
590 Mtftp4Config.TryCount = PXEBC_MTFTP_RETRIES;
591
592 CopyMem (&Mtftp4Config.StationIp, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
593 CopyMem (&Mtftp4Config.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
594 CopyMem (&Mtftp4Config.GatewayIp, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS));
595 CopyMem (&Mtftp4Config.ServerIp, ServerIp, sizeof (EFI_IPv4_ADDRESS));
596
597 switch (Operation) {
598
599 case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE:
600
601 Status = PxeBcTftpGetFileSize (
602 Private,
603 &Mtftp4Config,
604 Filename,
605 BlockSize,
606 BufferSize
607 );
608
609 if (!EFI_ERROR (Status)) {
610 Status = EFI_BUFFER_TOO_SMALL;
611 }
612
613 break;
614
615 case EFI_PXE_BASE_CODE_TFTP_READ_FILE:
616
617 Status = PxeBcTftpReadFile (
618 Private,
619 &Mtftp4Config,
620 Filename,
621 BlockSize,
622 BufferPtr,
623 BufferSize,
624 DontUseBuffer
625 );
626
627 break;
628
629 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE:
630
631 Status = PxeBcTftpWriteFile (
632 Private,
633 &Mtftp4Config,
634 Filename,
635 Overwrite,
636 BlockSize,
637 BufferPtr,
638 BufferSize
639 );
640
641 break;
642
643 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY:
644
645 Status = PxeBcTftpReadDirectory (
646 Private,
647 &Mtftp4Config,
648 Filename,
649 BlockSize,
650 BufferPtr,
651 BufferSize,
652 DontUseBuffer
653 );
654
655 break;
656
657 case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE:
658 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE:
659 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY:
660 Status = EFI_UNSUPPORTED;
661 break;
662
663 default:
664
665 Status = EFI_INVALID_PARAMETER;
666 break;
667 }
668
669 return Status;
670 }
671
672
673 /**
674 GC_NOTO: Add function description
675
676 @param This GC_NOTO: add argument
677 description
678 @param OpFlags GC_NOTO: add argument
679 description
680 @param DestIp GC_NOTO: add argument
681 description
682 @param DestPort GC_NOTO: add argument
683 description
684 @param GatewayIp GC_NOTO: add argument
685 description
686 @param SrcIp GC_NOTO: add argument
687 description
688 @param SrcPort GC_NOTO: add argument
689 description
690 @param HeaderSize GC_NOTO: add argument
691 description
692 @param HeaderPtr GC_NOTO: add argument
693 description
694 @param BufferSize GC_NOTO: add argument
695 description
696 @param BufferPtr GC_NOTO: add argument
697 description
698
699 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
700 return value
701 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
702 return value
703 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
704 return value
705 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
706 return value
707 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
708 return value
709
710 **/
711 EFI_STATUS
712 EFIAPI
713 EfiPxeBcUdpWrite (
714 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
715 IN UINT16 OpFlags,
716 IN EFI_IP_ADDRESS *DestIp,
717 IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort,
718 IN EFI_IP_ADDRESS *GatewayIp OPTIONAL,
719 IN EFI_IP_ADDRESS *SrcIp OPTIONAL,
720 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
721 IN UINTN *HeaderSize OPTIONAL,
722 IN VOID *HeaderPtr OPTIONAL,
723 IN UINTN *BufferSize,
724 IN VOID *BufferPtr
725 )
726 {
727 PXEBC_PRIVATE_DATA *Private;
728 EFI_UDP4_PROTOCOL *Udp4;
729 EFI_UDP4_COMPLETION_TOKEN Token;
730 EFI_UDP4_TRANSMIT_DATA *Udp4TxData;
731 UINT32 FragCount;
732 UINT32 DataLength;
733 EFI_UDP4_SESSION_DATA Udp4Session;
734 EFI_STATUS Status;
735 BOOLEAN IsDone;
736 UINT16 RandomSrcPort;
737
738 IsDone = FALSE;
739
740 if ((This == NULL) || (DestIp == NULL) || (DestPort == NULL)) {
741 return EFI_INVALID_PARAMETER;
742 }
743
744 if ((GatewayIp != NULL) && !Ip4IsUnicast (NTOHL (GatewayIp->Addr[0]), 0)) {
745 //
746 // Gateway is provided but it's not a unicast IP address.
747 //
748 return EFI_INVALID_PARAMETER;
749 }
750
751 if ((HeaderSize != NULL) && ((*HeaderSize == 0) || (HeaderPtr == NULL))) {
752 //
753 // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
754 // is NULL.
755 //
756 return EFI_INVALID_PARAMETER;
757 }
758
759 if ((BufferSize == NULL) || ((*BufferSize != 0) && (BufferPtr == NULL))) {
760 return EFI_INVALID_PARAMETER;
761 }
762
763 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
764 Udp4 = Private->Udp4;
765
766 if (!Private->AddressIsOk && (SrcIp == NULL)) {
767 return EFI_INVALID_PARAMETER;
768 }
769
770 if (SrcIp == NULL) {
771 SrcIp = &Private->StationIp;
772
773 if (GatewayIp == NULL) {
774 GatewayIp = &Private->GatewayIp;
775 }
776 }
777
778 if ((SrcPort == NULL) || (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT)) {
779 RandomSrcPort = (UINT16) (NET_RANDOM (NetRandomInitSeed ()) % 10000 + 1024);
780
781 if (SrcPort == NULL) {
782
783 SrcPort = &RandomSrcPort;
784 } else {
785
786 *SrcPort = RandomSrcPort;
787 }
788 }
789
790 ZeroMem (&Token, sizeof (EFI_UDP4_COMPLETION_TOKEN));
791 ZeroMem (&Udp4Session, sizeof (EFI_UDP4_SESSION_DATA));
792
793 CopyMem (&Udp4Session.DestinationAddress, DestIp, sizeof (EFI_IPv4_ADDRESS));
794 Udp4Session.DestinationPort = *DestPort;
795 CopyMem (&Udp4Session.SourceAddress, SrcIp, sizeof (EFI_IPv4_ADDRESS));
796 Udp4Session.SourcePort = *SrcPort;
797
798 FragCount = (HeaderSize != NULL) ? 2 : 1;
799 Udp4TxData = (EFI_UDP4_TRANSMIT_DATA *) AllocatePool (sizeof (EFI_UDP4_TRANSMIT_DATA) + (FragCount - 1) * sizeof (EFI_UDP4_FRAGMENT_DATA));
800 if (Udp4TxData == NULL) {
801 return EFI_OUT_OF_RESOURCES;
802 }
803
804 Udp4TxData->FragmentCount = FragCount;
805 Udp4TxData->FragmentTable[FragCount - 1].FragmentLength = (UINT32) *BufferSize;
806 Udp4TxData->FragmentTable[FragCount - 1].FragmentBuffer = BufferPtr;
807 DataLength = (UINT32) *BufferSize;
808
809 if (FragCount == 2) {
810
811 Udp4TxData->FragmentTable[0].FragmentLength = (UINT32) *HeaderSize;
812 Udp4TxData->FragmentTable[0].FragmentBuffer = HeaderPtr;
813 DataLength += (UINT32) *HeaderSize;
814 }
815
816 Udp4TxData->GatewayAddress = (EFI_IPv4_ADDRESS *) GatewayIp;
817 Udp4TxData->UdpSessionData = &Udp4Session;
818 Udp4TxData->DataLength = DataLength;
819 Token.Packet.TxData = Udp4TxData;
820
821 Status = gBS->CreateEvent (
822 EVT_NOTIFY_SIGNAL,
823 TPL_NOTIFY,
824 PxeBcCommonNotify,
825 &IsDone,
826 &Token.Event
827 );
828 if (EFI_ERROR (Status)) {
829 goto ON_EXIT;
830 }
831
832 Status = Udp4->Transmit (Udp4, &Token);
833 if (EFI_ERROR (Status)) {
834 goto ON_EXIT;
835 }
836
837 while (!IsDone) {
838
839 Udp4->Poll (Udp4);
840 }
841
842 Status = Token.Status;
843
844 ON_EXIT:
845
846 if (Token.Event != NULL) {
847 gBS->CloseEvent (Token.Event);
848 }
849
850 gBS->FreePool (Udp4TxData);
851
852 return Status;
853 }
854
855 /**
856 Validate IP packages by IP filter settings
857
858 @param PxeBcMode Pointer to EFI_PXEBC_MODE
859
860 @param Session Received UDP session
861
862 @retval TRUE The UDP package matches IP filters
863
864 @retval FLASE The UDP package doesn't matches IP filters
865
866 **/
867 STATIC
868 BOOLEAN
869 CheckIpByFilter (
870 EFI_PXE_BASE_CODE_MODE *PxeBcMode,
871 EFI_UDP4_SESSION_DATA *Session
872 )
873 {
874 UINTN Index;
875 EFI_IPv4_ADDRESS Ip4Address;
876 EFI_IPv4_ADDRESS DestIp4Address;
877
878 if (PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {
879 return TRUE;
880 }
881
882 CopyMem (&DestIp4Address, &Session->DestinationAddress, sizeof (DestIp4Address));
883 if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) &&
884 IP4_IS_MULTICAST (NTOHL (EFI_IP4 (DestIp4Address)))
885 ) {
886 return TRUE;
887 }
888
889 if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) &&
890 IP4_IS_LOCAL_BROADCAST (EFI_NTOHL (DestIp4Address))
891 ) {
892 return TRUE;
893 }
894
895 CopyMem (&Ip4Address, &PxeBcMode->StationIp.v4, sizeof (Ip4Address));
896 if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) &&
897 EFI_IP4_EQUAL (&PxeBcMode->StationIp.v4, &DestIp4Address)
898 ) {
899 return TRUE;
900 }
901
902 for (Index = 0; Index < PxeBcMode->IpFilter.IpCnt; ++Index) {
903 CopyMem (&Ip4Address, &PxeBcMode->IpFilter.IpList[Index].v4, sizeof (Ip4Address));
904 if (EFI_IP4_EQUAL (&Ip4Address, &DestIp4Address)) {
905 return TRUE;
906 }
907 }
908
909 return FALSE;
910 }
911
912 /**
913 GC_NOTO: Add function description
914
915 @param This GC_NOTO: add argument
916 description
917 @param OpFlags GC_NOTO: add argument
918 description
919 @param DestIp GC_NOTO: add argument
920 description
921 @param DestPort GC_NOTO: add argument
922 description
923 @param SrcIp GC_NOTO: add argument
924 description
925 @param SrcPort GC_NOTO: add argument
926 description
927 @param HeaderSize GC_NOTO: add argument
928 description
929 @param HeaderPtr GC_NOTO: add argument
930 description
931 @param BufferSize GC_NOTO: add argument
932 description
933 @param BufferPtr GC_NOTO: add argument
934 description
935
936 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
937 return value
938 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
939 return value
940 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
941 return value
942 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
943 return value
944 @retval EFI_NOT_STARTED GC_NOTO: Add description for
945 return value
946 @retval EFI_OUT_OF_RESOURCES GC_NOTO: Add description for
947 return value
948
949 **/
950 EFI_STATUS
951 EFIAPI
952 EfiPxeBcUdpRead (
953 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
954 IN UINT16 OpFlags,
955 IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL
956 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL
957 IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL
958 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL
959 IN UINTN *HeaderSize, OPTIONAL
960 IN VOID *HeaderPtr, OPTIONAL
961 IN OUT UINTN *BufferSize,
962 IN VOID *BufferPtr
963 )
964 {
965 PXEBC_PRIVATE_DATA *Private;
966 EFI_PXE_BASE_CODE_MODE *Mode;
967 EFI_UDP4_PROTOCOL *Udp4;
968 EFI_UDP4_COMPLETION_TOKEN Token;
969 EFI_UDP4_RECEIVE_DATA *RxData;
970 EFI_UDP4_SESSION_DATA *Session;
971 EFI_STATUS Status;
972 BOOLEAN IsDone;
973 BOOLEAN Matched;
974 UINTN CopyLen;
975
976 if (This == NULL || DestIp == NULL || DestPort == NULL) {
977 return EFI_INVALID_PARAMETER;
978 }
979
980 if ((!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && (DestPort == NULL)) ||
981 (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && (SrcIp == NULL)) ||
982 (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && (SrcPort == NULL))) {
983 return EFI_INVALID_PARAMETER;
984 }
985
986 if (((HeaderSize != NULL) && (*HeaderSize == 0)) || ((HeaderPtr == NULL) && (*HeaderSize != 0))) {
987 return EFI_INVALID_PARAMETER;
988 }
989
990 if ((BufferSize == NULL) || ((BufferPtr == NULL) && (*BufferSize != 0))) {
991 return EFI_INVALID_PARAMETER;
992 }
993
994 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
995 Mode = Private->PxeBc.Mode;
996 Udp4 = Private->Udp4;
997
998 if (!Mode->Started) {
999 return EFI_NOT_STARTED;
1000 }
1001
1002 Status = gBS->CreateEvent (
1003 EVT_NOTIFY_SIGNAL,
1004 TPL_NOTIFY,
1005 PxeBcCommonNotify,
1006 &IsDone,
1007 &Token.Event
1008 );
1009 if (EFI_ERROR (Status)) {
1010 return EFI_OUT_OF_RESOURCES;
1011 }
1012
1013 IsDone = FALSE;
1014 Status = Udp4->Receive (Udp4, &Token);
1015 if (EFI_ERROR (Status)) {
1016 goto ON_EXIT;
1017 }
1018
1019 Udp4->Poll (Udp4);
1020
1021 if (!IsDone) {
1022 Status = EFI_TIMEOUT;
1023 } else {
1024
1025 //
1026 // check whether this packet matches the filters
1027 //
1028 if (EFI_ERROR (Token.Status)){
1029 goto ON_EXIT;
1030 }
1031
1032 RxData = Token.Packet.RxData;
1033 Session = &RxData->UdpSession;
1034
1035 Matched = FALSE;
1036
1037 if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER) {
1038 //
1039 // Check UDP package by IP filter settings
1040 //
1041 if (CheckIpByFilter (Mode, Session)) {
1042 Matched = TRUE;
1043 }
1044 }
1045
1046 if (Matched) {
1047 //
1048 // Match the destination ip of the received udp dgram
1049 //
1050 if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP) {
1051 Matched = TRUE;
1052
1053 if (DestIp != NULL) {
1054 CopyMem (DestIp, &Session->DestinationAddress, sizeof (EFI_IPv4_ADDRESS));
1055 }
1056 } else {
1057 if (DestIp != NULL) {
1058 if (EFI_IP4_EQUAL (DestIp, &Session->DestinationAddress)) {
1059 Matched = TRUE;
1060 }
1061 } else {
1062 if (EFI_IP4_EQUAL (&Private->StationIp, &Session->DestinationAddress)) {
1063 Matched = TRUE;
1064 }
1065 }
1066 }
1067 }
1068
1069 if (Matched) {
1070 //
1071 // Match the destination port of the received udp dgram
1072 //
1073 if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) {
1074
1075 if (DestPort != NULL) {
1076 *DestPort = Session->DestinationPort;
1077 }
1078 } else {
1079
1080 if (*DestPort != Session->DestinationPort) {
1081 Matched = FALSE;
1082 }
1083 }
1084 }
1085
1086 if (Matched) {
1087 //
1088 // Match the source ip of the received udp dgram
1089 //
1090 if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) {
1091
1092 if (SrcIp != NULL) {
1093 CopyMem (SrcIp, &Session->SourceAddress, sizeof (EFI_IPv4_ADDRESS));
1094 }
1095 } else {
1096
1097 if (!EFI_IP4_EQUAL (SrcIp, &Session->SourceAddress)) {
1098 Matched = FALSE;
1099 }
1100 }
1101 }
1102
1103 if (Matched) {
1104 //
1105 // Match the source port of the received udp dgram
1106 //
1107 if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) {
1108
1109 if (SrcPort != NULL) {
1110 *SrcPort = Session->SourcePort;
1111 }
1112 } else {
1113
1114 if (*SrcPort != Session->SourcePort) {
1115 Matched = FALSE;
1116 }
1117 }
1118 }
1119
1120 if (Matched) {
1121
1122 CopyLen = 0;
1123
1124 if (HeaderSize != NULL) {
1125 CopyLen = MIN (*HeaderSize, RxData->DataLength);
1126 CopyMem (HeaderPtr, RxData->FragmentTable[0].FragmentBuffer, CopyLen);
1127 *HeaderSize = CopyLen;
1128 }
1129
1130 if (RxData->DataLength - CopyLen > *BufferSize) {
1131
1132 Status = EFI_BUFFER_TOO_SMALL;
1133 } else {
1134
1135 *BufferSize = RxData->DataLength - CopyLen;
1136 CopyMem (BufferPtr, (UINT8 *) RxData->FragmentTable[0].FragmentBuffer + CopyLen, *BufferSize);
1137 }
1138 } else {
1139
1140 Status = EFI_TIMEOUT;
1141 }
1142
1143 //
1144 // Recycle the RxData
1145 //
1146 gBS->SignalEvent (RxData->RecycleSignal);
1147 }
1148
1149 ON_EXIT:
1150
1151 Udp4->Cancel (Udp4, &Token);
1152
1153 gBS->CloseEvent (Token.Event);
1154
1155 return Status;
1156 }
1157
1158
1159 /**
1160 GC_NOTO: Add function description
1161
1162 @param This GC_NOTO: add argument
1163 description
1164 @param NewFilter GC_NOTO: add argument
1165 description
1166
1167 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1168 return value
1169
1170 **/
1171 EFI_STATUS
1172 EFIAPI
1173 EfiPxeBcSetIpFilter (
1174 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
1175 IN EFI_PXE_BASE_CODE_IP_FILTER *NewFilter
1176 )
1177 {
1178 EFI_STATUS Status;
1179 PXEBC_PRIVATE_DATA *Private;
1180 EFI_PXE_BASE_CODE_MODE *Mode;
1181 UINTN Index;
1182 BOOLEAN PromiscuousNeed;
1183
1184 if (This == NULL) {
1185 DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL.\n"));
1186 return EFI_INVALID_PARAMETER;
1187 }
1188
1189 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1190 Mode = Private->PxeBc.Mode;
1191
1192 if (Private == NULL) {
1193 DEBUG ((EFI_D_ERROR, "PXEBC_PRIVATE_DATA poiner == NULL.\n"));
1194 return EFI_INVALID_PARAMETER;
1195 }
1196
1197 if (NewFilter == NULL) {
1198 DEBUG ((EFI_D_ERROR, "IP Filter *NewFilter == NULL.\n"));
1199 return EFI_INVALID_PARAMETER;
1200 }
1201
1202 if (!Mode->Started) {
1203 DEBUG ((EFI_D_ERROR, "BC was not started.\n"));
1204 return EFI_NOT_STARTED;
1205 }
1206
1207 PromiscuousNeed = FALSE;
1208 for (Index = 0; Index < NewFilter->IpCnt; ++Index) {
1209 if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter->IpList[Index].v4))) {
1210 //
1211 // The IP is a broadcast address.
1212 //
1213 DEBUG ((EFI_D_ERROR, "There is broadcast address in NewFilter.\n"));
1214 return EFI_INVALID_PARAMETER;
1215 }
1216 if (Ip4IsUnicast (EFI_IP4 (NewFilter->IpList[Index].v4), 0) &&
1217 (NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP)
1218 ) {
1219 //
1220 // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,
1221 // promiscuous mode is needed.
1222 //
1223 PromiscuousNeed = TRUE;
1224 }
1225 }
1226
1227 //
1228 // Clear the UDP instance configuration, all joined groups will be left
1229 // during the operation.
1230 //
1231 Private->Udp4->Configure (Private->Udp4, NULL);
1232 Private->Udp4CfgData.AcceptPromiscuous = FALSE;
1233 Private->Udp4CfgData.AcceptBroadcast = FALSE;
1234
1235 if (PromiscuousNeed ||
1236 NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS ||
1237 NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
1238 ) {
1239 //
1240 // Configure the udp4 filter to receive all packages
1241 //
1242 Private->Udp4CfgData.AcceptPromiscuous = TRUE;
1243
1244 //
1245 // Configure the UDP instance with the new configuration.
1246 //
1247 Status = Private->Udp4->Configure (Private->Udp4, &Private->Udp4CfgData);
1248 if (EFI_ERROR (Status)) {
1249 return Status;
1250 }
1251
1252 } else {
1253
1254 if (NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) {
1255 //
1256 // Configure the udp4 filter to receive all broadcast packages
1257 //
1258 Private->Udp4CfgData.AcceptBroadcast = TRUE;
1259 }
1260
1261 //
1262 // Configure the UDP instance with the new configuration.
1263 //
1264 Status = Private->Udp4->Configure (Private->Udp4, &Private->Udp4CfgData);
1265 if (EFI_ERROR (Status)) {
1266 return Status;
1267 }
1268
1269 if (NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) {
1270
1271 for (Index = 0; Index < NewFilter->IpCnt; ++Index) {
1272 if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter->IpList[Index].v4))) {
1273 //
1274 // Join the mutilcast group
1275 //
1276 Status = Private->Udp4->Groups (Private->Udp4, TRUE, &NewFilter->IpList[Index].v4);
1277 if (EFI_ERROR (Status)) {
1278 return Status;
1279 }
1280 }
1281 }
1282 }
1283 }
1284
1285
1286 //
1287 // Save the new filter.
1288 //
1289 CopyMem (&Mode->IpFilter, NewFilter, sizeof (Mode->IpFilter));
1290
1291 return EFI_SUCCESS;
1292 }
1293
1294
1295 /**
1296 GC_NOTO: Add function description
1297
1298 @param This GC_NOTO: add argument
1299 description
1300 @param IpAddr GC_NOTO: add argument
1301 description
1302 @param MacAddr GC_NOTO: add argument
1303 description
1304
1305 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1306 return value
1307
1308 **/
1309 EFI_STATUS
1310 EFIAPI
1311 EfiPxeBcArp (
1312 IN EFI_PXE_BASE_CODE_PROTOCOL * This,
1313 IN EFI_IP_ADDRESS * IpAddr,
1314 IN EFI_MAC_ADDRESS * MacAddr OPTIONAL
1315 )
1316 {
1317 PXEBC_PRIVATE_DATA *Private;
1318 EFI_PXE_BASE_CODE_MODE *Mode;
1319 EFI_STATUS Status;
1320 EFI_MAC_ADDRESS TempMacAddr;
1321
1322 if (This == NULL || IpAddr == NULL) {
1323 return EFI_INVALID_PARAMETER;
1324 }
1325
1326 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1327 Mode = Private->PxeBc.Mode;
1328
1329 if (!Mode->Started) {
1330 return EFI_NOT_STARTED;
1331 }
1332
1333 if (!Private->AddressIsOk || Mode->UsingIpv6) {
1334 //
1335 // We can't resolve the IP address if we don't have a local address now.
1336 // Don't have ARP for IPv6.
1337 //
1338 return EFI_INVALID_PARAMETER;
1339 }
1340
1341 Status = Private->Arp->Request (Private->Arp, &IpAddr->v4, NULL, &TempMacAddr);
1342 if (EFI_ERROR (Status)) {
1343 return Status;
1344 }
1345
1346 if (MacAddr != NULL) {
1347 CopyMem (MacAddr, &TempMacAddr, sizeof (EFI_MAC_ADDRESS));
1348 }
1349
1350 return EFI_SUCCESS;
1351 }
1352
1353
1354
1355 /**
1356 GC_NOTO: Add function description
1357
1358 @param This GC_NOTO: add argument
1359 description
1360 @param NewAutoArp GC_NOTO: add argument
1361 description
1362 @param NewSendGUID GC_NOTO: add argument
1363 description
1364 @param NewTTL GC_NOTO: add argument
1365 description
1366 @param NewToS GC_NOTO: add argument
1367 description
1368 @param NewMakeCallback GC_NOTO: add argument
1369 description
1370
1371 @return GC_NOTO: add return values
1372
1373 **/
1374 EFI_STATUS
1375 EFIAPI
1376 EfiPxeBcSetParameters (
1377 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
1378 IN BOOLEAN *NewAutoArp, OPTIONAL
1379 IN BOOLEAN *NewSendGUID, OPTIONAL
1380 IN UINT8 *NewTTL, OPTIONAL
1381 IN UINT8 *NewToS, OPTIONAL
1382 IN BOOLEAN *NewMakeCallback // OPTIONAL
1383 )
1384 {
1385 PXEBC_PRIVATE_DATA *Private;
1386 EFI_PXE_BASE_CODE_MODE *Mode;
1387 EFI_STATUS Status;
1388
1389 Status = EFI_SUCCESS;
1390
1391 if (This == NULL) {
1392 Status = EFI_INVALID_PARAMETER;
1393 goto ON_EXIT;
1394 }
1395
1396 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1397 Mode = Private->PxeBc.Mode;
1398
1399 if (NewSendGUID != NULL && *NewSendGUID == TRUE) {
1400 //
1401 // FixMe, cann't locate SendGuid
1402 //
1403 }
1404
1405 if (NewMakeCallback != NULL && *NewMakeCallback == TRUE) {
1406
1407 Status = gBS->HandleProtocol (
1408 Private->Controller,
1409 &gEfiPxeBaseCodeCallbackProtocolGuid,
1410 (VOID **) &Private->PxeBcCallback
1411 );
1412 if (EFI_ERROR (Status) || (Private->PxeBcCallback->Callback == NULL)) {
1413
1414 Status = EFI_INVALID_PARAMETER;
1415 goto ON_EXIT;
1416 }
1417 }
1418
1419 if (!Mode->Started) {
1420 Status = EFI_NOT_STARTED;
1421 goto ON_EXIT;
1422 }
1423
1424 if (NewMakeCallback != NULL) {
1425
1426 if (*NewMakeCallback) {
1427 //
1428 // Update the Callback protocol.
1429 //
1430 Status = gBS->HandleProtocol (
1431 Private->Controller,
1432 &gEfiPxeBaseCodeCallbackProtocolGuid,
1433 (VOID **) &Private->PxeBcCallback
1434 );
1435
1436 if (EFI_ERROR (Status) || (Private->PxeBcCallback->Callback == NULL)) {
1437 Status = EFI_INVALID_PARAMETER;
1438 goto ON_EXIT;
1439 }
1440 } else {
1441 Private->PxeBcCallback = NULL;
1442 }
1443
1444 Mode->MakeCallbacks = *NewMakeCallback;
1445 }
1446
1447 if (NewAutoArp != NULL) {
1448 Mode->AutoArp = *NewAutoArp;
1449 }
1450
1451 if (NewSendGUID != NULL) {
1452 Mode->SendGUID = *NewSendGUID;
1453 }
1454
1455 if (NewTTL != NULL) {
1456 Mode->TTL = *NewTTL;
1457 }
1458
1459 if (NewToS != NULL) {
1460 Mode->ToS = *NewToS;
1461 }
1462
1463 ON_EXIT:
1464 return Status;
1465 }
1466
1467
1468 /**
1469 GC_NOTO: Add function description
1470
1471 @param This GC_NOTO: add argument
1472 description
1473 @param NewStationIp GC_NOTO: add argument
1474 description
1475 @param NewSubnetMask GC_NOTO: add argument
1476 description
1477
1478 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1479 return value
1480 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1481 return value
1482 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1483 return value
1484 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1485 return value
1486 @retval EFI_SUCCESS GC_NOTO: Add description for
1487 return value
1488
1489 **/
1490 EFI_STATUS
1491 EFIAPI
1492 EfiPxeBcSetStationIP (
1493 IN EFI_PXE_BASE_CODE_PROTOCOL * This,
1494 IN EFI_IP_ADDRESS * NewStationIp, OPTIONAL
1495 IN EFI_IP_ADDRESS * NewSubnetMask OPTIONAL
1496 )
1497 {
1498 PXEBC_PRIVATE_DATA *Private;
1499 EFI_PXE_BASE_CODE_MODE *Mode;
1500 EFI_ARP_CONFIG_DATA ArpConfigData;
1501
1502 if (This == NULL) {
1503 return EFI_INVALID_PARAMETER;
1504 }
1505
1506 if (NewStationIp != NULL && !Ip4IsUnicast (NTOHL (NewStationIp->Addr[0]), 0)) {
1507 return EFI_INVALID_PARAMETER;
1508 }
1509
1510 if (NewSubnetMask != NULL && !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask->Addr[0]))) {
1511 return EFI_INVALID_PARAMETER;
1512 }
1513
1514 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1515 Mode = Private->PxeBc.Mode;
1516
1517 if (!Mode->Started) {
1518 return EFI_NOT_STARTED;
1519 }
1520
1521 if (NewStationIp != NULL) {
1522 Mode->StationIp = *NewStationIp;
1523 }
1524
1525 if (NewSubnetMask != NULL) {
1526 Mode->SubnetMask = *NewSubnetMask;
1527 }
1528
1529 Private->AddressIsOk = TRUE;
1530
1531 if (!Mode->UsingIpv6) {
1532 //
1533 // If in IPv4 mode, configure the corresponding ARP with this new
1534 // station IP address.
1535 //
1536 ZeroMem (&ArpConfigData, sizeof (EFI_ARP_CONFIG_DATA));
1537
1538 ArpConfigData.SwAddressType = 0x0800;
1539 ArpConfigData.SwAddressLength = sizeof (EFI_IPv4_ADDRESS);
1540 ArpConfigData.StationAddress = &Private->StationIp.v4;
1541
1542 Private->Arp->Configure (Private->Arp, NULL);
1543 Private->Arp->Configure (Private->Arp, &ArpConfigData);
1544 }
1545
1546 return EFI_SUCCESS;
1547 }
1548
1549
1550 /**
1551 GC_NOTO: Add function description
1552
1553 @param This GC_NOTO: add argument
1554 description
1555 @param NewDhcpDiscoverValid GC_NOTO: add argument
1556 description
1557 @param NewDhcpAckReceived GC_NOTO: add argument
1558 description
1559 @param NewProxyOfferReceived GC_NOTO: add argument
1560 description
1561 @param NewPxeDiscoverValid GC_NOTO: add argument
1562 description
1563 @param NewPxeReplyReceived GC_NOTO: add argument
1564 description
1565 @param NewPxeBisReplyReceived GC_NOTO: add argument
1566 description
1567 @param NewDhcpDiscover GC_NOTO: add argument
1568 description
1569 @param NewDhcpAck GC_NOTO: add argument
1570 description
1571 @param NewProxyOffer GC_NOTO: add argument
1572 description
1573 @param NewPxeDiscover GC_NOTO: add argument
1574 description
1575 @param NewPxeReply GC_NOTO: add argument
1576 description
1577 @param NewPxeBisReply GC_NOTO: add argument
1578 description
1579
1580 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1581 return value
1582 @retval EFI_NOT_STARTED GC_NOTO: Add description for
1583 return value
1584 @retval EFI_SUCCESS GC_NOTO: Add description for
1585 return value
1586
1587 **/
1588 EFI_STATUS
1589 EFIAPI
1590 EfiPxeBcSetPackets (
1591 IN EFI_PXE_BASE_CODE_PROTOCOL * This,
1592 IN BOOLEAN * NewDhcpDiscoverValid, OPTIONAL
1593 IN BOOLEAN * NewDhcpAckReceived, OPTIONAL
1594 IN BOOLEAN * NewProxyOfferReceived, OPTIONAL
1595 IN BOOLEAN * NewPxeDiscoverValid, OPTIONAL
1596 IN BOOLEAN * NewPxeReplyReceived, OPTIONAL
1597 IN BOOLEAN * NewPxeBisReplyReceived, OPTIONAL
1598 IN EFI_PXE_BASE_CODE_PACKET * NewDhcpDiscover, OPTIONAL
1599 IN EFI_PXE_BASE_CODE_PACKET * NewDhcpAck, OPTIONAL
1600 IN EFI_PXE_BASE_CODE_PACKET * NewProxyOffer, OPTIONAL
1601 IN EFI_PXE_BASE_CODE_PACKET * NewPxeDiscover, OPTIONAL
1602 IN EFI_PXE_BASE_CODE_PACKET * NewPxeReply, OPTIONAL
1603 IN EFI_PXE_BASE_CODE_PACKET * NewPxeBisReply OPTIONAL
1604 )
1605 {
1606 PXEBC_PRIVATE_DATA *Private;
1607 EFI_PXE_BASE_CODE_MODE *Mode;
1608
1609 if (This == NULL) {
1610 return EFI_INVALID_PARAMETER;
1611 }
1612
1613 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1614 Mode = Private->PxeBc.Mode;
1615
1616 if (!Mode->Started) {
1617 return EFI_NOT_STARTED;
1618 }
1619
1620 Private->FileSize = 0;
1621
1622 if (NewDhcpDiscoverValid != NULL) {
1623 Mode->DhcpDiscoverValid = *NewDhcpDiscoverValid;
1624 }
1625
1626 if (NewDhcpAckReceived != NULL) {
1627 Mode->DhcpAckReceived = *NewDhcpAckReceived;
1628 }
1629
1630 if (NewProxyOfferReceived != NULL) {
1631 Mode->ProxyOfferReceived = *NewProxyOfferReceived;
1632 }
1633
1634 if (NewPxeDiscoverValid != NULL) {
1635 Mode->PxeDiscoverValid = *NewPxeDiscoverValid;
1636 }
1637
1638 if (NewPxeReplyReceived != NULL) {
1639 Mode->PxeReplyReceived = *NewPxeReplyReceived;
1640 }
1641
1642 if (NewPxeBisReplyReceived != NULL) {
1643 Mode->PxeBisReplyReceived = *NewPxeBisReplyReceived;
1644 }
1645
1646 if (NewDhcpDiscover != NULL) {
1647 CopyMem (&Mode->DhcpDiscover, NewDhcpDiscover, sizeof (EFI_PXE_BASE_CODE_PACKET));
1648 }
1649
1650 if (NewDhcpAck != NULL) {
1651 CopyMem (&Mode->DhcpAck, NewDhcpAck, sizeof (EFI_PXE_BASE_CODE_PACKET));
1652 }
1653
1654 if (NewProxyOffer != NULL) {
1655 CopyMem (&Mode->ProxyOffer, NewProxyOffer, sizeof (EFI_PXE_BASE_CODE_PACKET));
1656 }
1657
1658 if (NewPxeDiscover != NULL) {
1659 CopyMem (&Mode->PxeDiscover, NewPxeDiscover, sizeof (EFI_PXE_BASE_CODE_PACKET));
1660 }
1661
1662 if (NewPxeReply != NULL) {
1663 CopyMem (&Mode->PxeReply, NewPxeReply, sizeof (EFI_PXE_BASE_CODE_PACKET));
1664 }
1665
1666 if (NewPxeBisReply != NULL) {
1667 CopyMem (&Mode->PxeBisReply, NewPxeBisReply, sizeof (EFI_PXE_BASE_CODE_PACKET));
1668 }
1669
1670 return EFI_SUCCESS;
1671 }
1672
1673 EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate = {
1674 EFI_PXE_BASE_CODE_PROTOCOL_REVISION,
1675 EfiPxeBcStart,
1676 EfiPxeBcStop,
1677 EfiPxeBcDhcp,
1678 EfiPxeBcDiscover,
1679 EfiPxeBcMtftp,
1680 EfiPxeBcUdpWrite,
1681 EfiPxeBcUdpRead,
1682 EfiPxeBcSetIpFilter,
1683 EfiPxeBcArp,
1684 EfiPxeBcSetParameters,
1685 EfiPxeBcSetStationIP,
1686 EfiPxeBcSetPackets,
1687 NULL
1688 };
1689
1690
1691 /**
1692 GC_NOTO: Add function description
1693
1694 @param This GC_NOTO: add argument
1695 description
1696 @param Function GC_NOTO: add argument
1697 description
1698 @param Received GC_NOTO: add argument
1699 description
1700 @param PacketLength GC_NOTO: add argument
1701 description
1702 @param PacketPtr GC_NOTO: add argument
1703 description
1704
1705 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT GC_NOTO: Add description for
1706 return value
1707 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1708 return value
1709 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1710 return value
1711 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1712 return value
1713 @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE GC_NOTO: Add description for
1714 return value
1715
1716 **/
1717 EFI_PXE_BASE_CODE_CALLBACK_STATUS
1718 EFIAPI
1719 EfiPxeLoadFileCallback (
1720 IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL * This,
1721 IN EFI_PXE_BASE_CODE_FUNCTION Function,
1722 IN BOOLEAN Received,
1723 IN UINT32 PacketLength,
1724 IN EFI_PXE_BASE_CODE_PACKET * PacketPtr OPTIONAL
1725 )
1726 {
1727 EFI_INPUT_KEY Key;
1728 EFI_STATUS Status;
1729
1730 //
1731 // Catch Ctrl-C or ESC to abort.
1732 //
1733 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1734
1735 if (!EFI_ERROR (Status)) {
1736
1737 if (Key.ScanCode == SCAN_ESC || Key.UnicodeChar == (0x1F & 'c')) {
1738
1739 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT;
1740 }
1741 }
1742 //
1743 // No print if receive packet
1744 //
1745 if (Received) {
1746 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
1747 }
1748 //
1749 // Print only for three functions
1750 //
1751 switch (Function) {
1752
1753 case EFI_PXE_BASE_CODE_FUNCTION_MTFTP:
1754 //
1755 // Print only for open MTFTP packets, not every MTFTP packets
1756 //
1757 if (PacketLength != 0 && PacketPtr != NULL) {
1758 if (PacketPtr->Raw[0x1C] != 0x00 || PacketPtr->Raw[0x1D] != 0x01) {
1759 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
1760 }
1761 }
1762 break;
1763
1764 case EFI_PXE_BASE_CODE_FUNCTION_DHCP:
1765 case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER:
1766 break;
1767
1768 default:
1769 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
1770 }
1771
1772 if (PacketLength != 0 && PacketPtr != NULL) {
1773 //
1774 // Print '.' when transmit a packet
1775 //
1776 AsciiPrint (".");
1777
1778 }
1779
1780 return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
1781 }
1782
1783 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate = {
1784 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION,
1785 EfiPxeLoadFileCallback
1786 };
1787
1788
1789 /**
1790 GC_NOTO: Add function description
1791
1792 @param Private GC_NOTO: add argument
1793 description
1794 @param BufferSize GC_NOTO: add argument
1795 description
1796 @param Buffer GC_NOTO: add argument
1797 description
1798
1799 @return GC_NOTO: add return values
1800
1801 **/
1802 EFI_STATUS
1803 DiscoverBootFile (
1804 IN PXEBC_PRIVATE_DATA *Private,
1805 IN OUT UINT64 *BufferSize,
1806 IN VOID *Buffer
1807 )
1808 {
1809 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
1810 EFI_PXE_BASE_CODE_MODE *Mode;
1811 EFI_STATUS Status;
1812 UINT16 Type;
1813 UINT16 Layer;
1814 BOOLEAN UseBis;
1815 UINTN BlockSize;
1816 PXEBC_CACHED_DHCP4_PACKET *Packet;
1817 UINT16 Value;
1818
1819 PxeBc = &Private->PxeBc;
1820 Mode = PxeBc->Mode;
1821 Type = EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP;
1822 Layer = EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL;
1823
1824 //
1825 // do DHCP.
1826 //
1827 Status = PxeBc->Dhcp (PxeBc, TRUE);
1828 if (EFI_ERROR (Status)) {
1829 return Status;
1830 }
1831
1832 //
1833 // Select a boot server
1834 //
1835 Status = PxeBcSelectBootPrompt (Private);
1836
1837 if (Status == EFI_SUCCESS) {
1838 Status = PxeBcSelectBootMenu (Private, &Type, TRUE);
1839 } else if (Status == EFI_TIMEOUT) {
1840 Status = PxeBcSelectBootMenu (Private, &Type, FALSE);
1841 }
1842
1843 if (!EFI_ERROR (Status)) {
1844
1845 if (Type == EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP) {
1846 //
1847 // Local boot(PXE bootstrap server) need abort
1848 //
1849 return EFI_ABORTED;
1850 }
1851
1852 UseBis = (BOOLEAN) (Mode->BisSupported && Mode->BisDetected);
1853 Status = PxeBc->Discover (PxeBc, Type, &Layer, UseBis, NULL);
1854 if (EFI_ERROR (Status)) {
1855 return Status;
1856 }
1857 }
1858
1859 *BufferSize = 0;
1860 BlockSize = 0x8000;
1861
1862 //
1863 // Get bootfile name and (m)tftp server ip addresss
1864 //
1865 if (Mode->PxeReplyReceived) {
1866 Packet = &Private->PxeReply;
1867 } else if (Mode->ProxyOfferReceived) {
1868 Packet = &Private->ProxyOffer;
1869 } else {
1870 Packet = &Private->Dhcp4Ack;
1871 }
1872
1873 CopyMem (&Private->ServerIp, &Packet->Packet.Offer.Dhcp4.Header.ServerAddr, sizeof (EFI_IPv4_ADDRESS));
1874 if (Private->ServerIp.Addr[0] == 0) {
1875 //
1876 // next server ip address is zero, use option 54 instead
1877 //
1878 CopyMem (
1879 &Private->ServerIp,
1880 Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->Data,
1881 sizeof (EFI_IPv4_ADDRESS)
1882 );
1883 }
1884
1885 ASSERT (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL);
1886
1887 //
1888 // bootlfile name
1889 //
1890 Private->BootFileName = (CHAR8 *) (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data);
1891
1892 if (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN] != NULL) {
1893 //
1894 // Already have the bootfile length option, compute the file size
1895 //
1896 CopyMem (&Value, Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN]->Data, sizeof (Value));
1897 Value = NTOHS (Value);
1898 *BufferSize = 512 * Value;
1899 Status = EFI_BUFFER_TOO_SMALL;
1900 } else {
1901 //
1902 // Get the bootfile size from tftp
1903 //
1904 Status = PxeBc->Mtftp (
1905 PxeBc,
1906 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
1907 Buffer,
1908 FALSE,
1909 BufferSize,
1910 &BlockSize,
1911 &Private->ServerIp,
1912 (UINT8 *) Private->BootFileName,
1913 NULL,
1914 FALSE
1915 );
1916 }
1917
1918 Private->FileSize = (UINTN) *BufferSize;
1919
1920 return Status;
1921 }
1922
1923
1924 /**
1925 GC_NOTO: Add function description
1926
1927 @param This GC_NOTO: add argument
1928 description
1929 @param FilePath GC_NOTO: add argument
1930 description
1931 @param BootPolicy GC_NOTO: add argument
1932 description
1933 @param BufferSize GC_NOTO: add argument
1934 description
1935 @param Buffer GC_NOTO: add argument
1936 description
1937
1938 @retval EFI_INVALID_PARAMETER GC_NOTO: Add description for
1939 return value
1940 @retval EFI_UNSUPPORTED GC_NOTO: Add description for
1941 return value
1942
1943 **/
1944 EFI_STATUS
1945 EFIAPI
1946 EfiPxeLoadFile (
1947 IN EFI_LOAD_FILE_PROTOCOL * This,
1948 IN EFI_DEVICE_PATH_PROTOCOL * FilePath,
1949 IN BOOLEAN BootPolicy,
1950 IN OUT UINTN *BufferSize,
1951 IN VOID *Buffer OPTIONAL
1952 )
1953 {
1954 PXEBC_PRIVATE_DATA *Private;
1955 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
1956 BOOLEAN NewMakeCallback;
1957 UINTN BlockSize;
1958 EFI_STATUS Status;
1959 UINT64 TmpBufSize;
1960
1961 Private = PXEBC_PRIVATE_DATA_FROM_LOADFILE (This);
1962 PxeBc = &Private->PxeBc;
1963 NewMakeCallback = FALSE;
1964 BlockSize = 0x8000;
1965 Status = EFI_DEVICE_ERROR;
1966
1967 if (This == NULL || BufferSize == NULL) {
1968
1969 return EFI_INVALID_PARAMETER;
1970 }
1971
1972 //
1973 // Only support BootPolicy
1974 //
1975 if (!BootPolicy) {
1976 return EFI_UNSUPPORTED;
1977 }
1978
1979 Status = PxeBc->Start (PxeBc, FALSE);
1980 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
1981 return Status;
1982 }
1983
1984 Status = gBS->HandleProtocol (
1985 Private->Controller,
1986 &gEfiPxeBaseCodeCallbackProtocolGuid,
1987 (VOID **) &Private->PxeBcCallback
1988 );
1989 if (Status == EFI_UNSUPPORTED) {
1990
1991 CopyMem (&Private->LoadFileCallback, &mPxeBcCallBackTemplate, sizeof (Private->LoadFileCallback));
1992
1993 Status = gBS->InstallProtocolInterface (
1994 &Private->Controller,
1995 &gEfiPxeBaseCodeCallbackProtocolGuid,
1996 EFI_NATIVE_INTERFACE,
1997 &Private->LoadFileCallback
1998 );
1999
2000 NewMakeCallback = (BOOLEAN) (Status == EFI_SUCCESS);
2001
2002 Status = PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, &NewMakeCallback);
2003 if (EFI_ERROR (Status)) {
2004 PxeBc->Stop (PxeBc);
2005 return Status;
2006 }
2007 }
2008
2009 if (Private->FileSize == 0) {
2010 TmpBufSize = 0;
2011 Status = DiscoverBootFile (Private, &TmpBufSize, Buffer);
2012
2013 if (sizeof (UINTN) < sizeof (UINT64) && (TmpBufSize > 0xFFFFFFFF)) {
2014 Status = EFI_DEVICE_ERROR;
2015 } else {
2016 *BufferSize = (UINTN) TmpBufSize;
2017 }
2018 } else if (Buffer == NULL) {
2019 *BufferSize = Private->FileSize;
2020 Status = EFI_BUFFER_TOO_SMALL;
2021 } else {
2022 //
2023 // Download the file.
2024 //
2025 TmpBufSize = (UINT64) (*BufferSize);
2026 Status = PxeBc->Mtftp (
2027 PxeBc,
2028 EFI_PXE_BASE_CODE_TFTP_READ_FILE,
2029 Buffer,
2030 FALSE,
2031 &TmpBufSize,
2032 &BlockSize,
2033 &Private->ServerIp,
2034 (UINT8 *) Private->BootFileName,
2035 NULL,
2036 FALSE
2037 );
2038 }
2039 //
2040 // If we added a callback protocol, now is the time to remove it.
2041 //
2042 if (NewMakeCallback) {
2043
2044 NewMakeCallback = FALSE;
2045
2046 PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, &NewMakeCallback);
2047
2048 gBS->UninstallProtocolInterface (
2049 Private->Controller,
2050 &gEfiPxeBaseCodeCallbackProtocolGuid,
2051 &Private->LoadFileCallback
2052 );
2053 }
2054 //
2055 // Check download status
2056 //
2057 switch (Status) {
2058
2059 case EFI_SUCCESS:
2060 break;
2061
2062 case EFI_BUFFER_TOO_SMALL:
2063 if (Buffer != NULL) {
2064 AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
2065 } else {
2066 return Status;
2067 }
2068 break;
2069
2070 case EFI_DEVICE_ERROR:
2071 AsciiPrint ("PXE-E07: Network device error.\n");
2072 break;
2073
2074 case EFI_OUT_OF_RESOURCES:
2075 AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
2076 break;
2077
2078 case EFI_NO_MEDIA:
2079 AsciiPrint ("PXE-E12: Could not detect network connection.\n");
2080 break;
2081
2082 case EFI_NO_RESPONSE:
2083 AsciiPrint ("PXE-E16: No offer received.\n");
2084 break;
2085
2086 case EFI_TIMEOUT:
2087 AsciiPrint ("PXE-E18: Server response timeout.\n");
2088 break;
2089
2090 case EFI_ABORTED:
2091 AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
2092 break;
2093
2094 case EFI_ICMP_ERROR:
2095 AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
2096 break;
2097
2098 case EFI_TFTP_ERROR:
2099 AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
2100 break;
2101
2102 default:
2103 AsciiPrint ("PXE-E99: Unexpected network error.\n");
2104 break;
2105 }
2106
2107 PxeBc->Stop (PxeBc);
2108
2109 return Status;
2110 }
2111
2112 EFI_LOAD_FILE_PROTOCOL mLoadFileProtocolTemplate = { EfiPxeLoadFile };
2113