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