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