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