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