]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_arp.c
Clean up the following module msa files, they are three networt and two PCD modules.
[mirror_edk2.git] / EdkModulePkg / Universal / Network / PxeBc / Dxe / pxe_bc_arp.c
CommitLineData
878ddf1f 1/*++\r
2\r
26aa0c2f 3Copyright (c) 2006 - 2007, Intel Corporation \r
878ddf1f 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 pxe_bc_arp.c\r
14\r
15Abstract:\r
16\r
17--*/\r
18\r
19\r
4cbd855e 20#include "Bc.h"\r
878ddf1f 21\r
22//\r
23// Definitions for ARP\r
24// Per RFC 826\r
25//\r
26STATIC ARP_HEADER ArpHeader;\r
27\r
28#pragma pack(1)\r
29STATIC struct {\r
30 UINT8 MediaHeader[14];\r
31 ARP_HEADER ArpHeader;\r
32 UINT8 ArpData[64];\r
33} ArpReplyPacket;\r
34#pragma pack()\r
35\r
36/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
37VOID\r
38InitArpHeader (\r
39 VOID\r
40 )\r
41/*++\r
42Routine description:\r
43 Initialize ARP packet header.\r
44\r
45Parameters:\r
46 none\r
47\r
48Returns:\r
49 none\r
50\r
51--*/\r
52{\r
53 ArpHeader.HwType = HTONS (ETHERNET_ADD_SPC);\r
54 ArpHeader.ProtType = HTONS (ETHER_TYPE_IP);\r
55 ArpHeader.HwAddLen = ENET_HWADDLEN;\r
56 ArpHeader.ProtAddLen = IPV4_PROTADDLEN;\r
57 ArpHeader.OpCode = HTONS (ARP_REQUEST);\r
58\r
59 CopyMem (&ArpReplyPacket.ArpHeader, &ArpHeader, sizeof (ARP_HEADER));\r
60}\r
61\r
62/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
63VOID\r
64HandleArpReceive (\r
65 IN PXE_BASECODE_DEVICE *Private,\r
66 IN ARP_PACKET *ArpPacketPtr,\r
67 IN VOID *MediaHeader\r
68 )\r
69/*++\r
70Routine description:\r
71 Process ARP packet.\r
72\r
73Parameters:\r
74 Private := Pointer to PxeBc interface\r
75 ArpPacketPtr := Pointer to ARP packet\r
76 MediaHeader := Pointer to media header.\r
77Returns:\r
78--*/\r
79{\r
80 EFI_PXE_BASE_CODE_MODE *PxeBcMode;\r
81 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
82 EFI_MAC_ADDRESS TmpMacAddr;\r
83 UINTN Index;\r
84 UINT8 *SrcHwAddr;\r
85 UINT8 *SrcPrAddr;\r
86 UINT8 *DstHwAddr;\r
87 UINT8 *DstPrAddr;\r
88 UINT8 *TmpPtr;\r
89\r
90 //\r
91 //\r
92 //\r
93 PxeBcMode = Private->EfiBc.Mode;\r
94 SnpMode = Private->SimpleNetwork->Mode;\r
95\r
96 //\r
97 // For now only ethernet addresses are supported.\r
98 // This will need to be updated when other media\r
99 // layers are supported by PxeBc, Snp and UNDI.\r
100 //\r
101 if (ArpPacketPtr->ArpHeader.HwType != HTONS (ETHERNET_ADD_SPC)) {\r
102 return ;\r
103 }\r
104 //\r
105 // For now only IP protocol addresses are supported.\r
106 // This will need to be updated when other protocol\r
107 // types are supported by PxeBc, Snp and UNDI.\r
108 //\r
109 if (ArpPacketPtr->ArpHeader.ProtType != HTONS (ETHER_TYPE_IP)) {\r
110 return ;\r
111 }\r
112 //\r
113 // For now only SNP hardware address sizes are supported.\r
114 //\r
115 if (ArpPacketPtr->ArpHeader.HwAddLen != SnpMode->HwAddressSize) {\r
116 return ;\r
117 }\r
118 //\r
119 // For now only PxeBc protocol address sizes are supported.\r
120 //\r
121 if (ArpPacketPtr->ArpHeader.ProtAddLen != Private->IpLength) {\r
122 return ;\r
123 }\r
124 //\r
125 // Ignore out of range opcodes\r
126 //\r
127 switch (ArpPacketPtr->ArpHeader.OpCode) {\r
128 case HTONS (ARP_REPLY):\r
129 case HTONS (ARP_REQUEST):\r
130 break;\r
131\r
132 default:\r
133 return ;\r
134 }\r
135 //\r
136 // update entry in our ARP cache if we have it\r
137 //\r
138 SrcHwAddr = (UINT8 *) &ArpPacketPtr->SrcHardwareAddr;\r
139 SrcPrAddr = SrcHwAddr + SnpMode->HwAddressSize;\r
140\r
141 for (Index = 0; Index < PxeBcMode->ArpCacheEntries; ++Index) {\r
142 if (CompareMem (\r
143 &PxeBcMode->ArpCache[Index].IpAddr,\r
144 SrcPrAddr,\r
145 Private->IpLength\r
146 )) {\r
147 continue;\r
148 }\r
149\r
150 CopyMem (\r
151 &PxeBcMode->ArpCache[Index].MacAddr,\r
152 SrcHwAddr,\r
153 SnpMode->HwAddressSize\r
154 );\r
155\r
156 break;\r
157 }\r
158 //\r
159 // Done if ARP packet was not for us.\r
160 //\r
161 DstHwAddr = SrcPrAddr + Private->IpLength;\r
162 DstPrAddr = DstHwAddr + SnpMode->HwAddressSize;\r
163\r
164 if (CompareMem (DstPrAddr, &PxeBcMode->StationIp, Private->IpLength)) {\r
165 return ;\r
166 //\r
167 // not for us\r
168 //\r
169 }\r
170 //\r
171 // for us - if we did not update entry, add it\r
172 //\r
173 if (Index == PxeBcMode->ArpCacheEntries) {\r
174 //\r
175 // if we have a full table, get rid of oldest\r
176 //\r
177 if (Index == PXE_ARP_CACHE_SIZE) {\r
178 Index = Private->OldestArpEntry;\r
179\r
180 if (++Private->OldestArpEntry == PXE_ARP_CACHE_SIZE) {\r
181 Private->OldestArpEntry = 0;\r
182 }\r
183 } else {\r
184 ++PxeBcMode->ArpCacheEntries;\r
185 }\r
186\r
187 CopyMem (\r
188 &PxeBcMode->ArpCache[Index].MacAddr,\r
189 SrcHwAddr,\r
190 SnpMode->HwAddressSize\r
191 );\r
192\r
193 CopyMem (\r
194 &PxeBcMode->ArpCache[Index].IpAddr,\r
195 SrcPrAddr,\r
196 Private->IpLength\r
197 );\r
198 }\r
199 //\r
200 // if this is not a request or we don't yet have an IP, finished\r
201 //\r
202 if (ArpPacketPtr->ArpHeader.OpCode != HTONS (ARP_REQUEST) || !Private->GoodStationIp) {\r
203 return ;\r
204 }\r
205 //\r
206 // Assemble ARP reply.\r
207 //\r
208 //\r
209 // Create media header. [ dest mac | src mac | prot ]\r
210 //\r
211 CopyMem (\r
212 &ArpReplyPacket.MediaHeader[0],\r
213 SrcHwAddr,\r
214 SnpMode->HwAddressSize\r
215 );\r
216\r
217 CopyMem (\r
218 &ArpReplyPacket.MediaHeader[SnpMode->HwAddressSize],\r
219 &SnpMode->CurrentAddress,\r
220 SnpMode->HwAddressSize\r
221 );\r
222\r
223 CopyMem (\r
224 &ArpReplyPacket.MediaHeader[2 * SnpMode->HwAddressSize],\r
225 &((UINT8 *) MediaHeader)[2 * SnpMode->HwAddressSize],\r
226 sizeof (UINT16)\r
227 );\r
228\r
229 //\r
230 // ARP reply header is almost filled in,\r
231 // just insert the correct opcode.\r
232 //\r
233 ArpReplyPacket.ArpHeader.OpCode = HTONS (ARP_REPLY);\r
234\r
235 //\r
236 // Now fill in ARP data. [ src mac | src prot | dest mac | dest prot ]\r
237 //\r
238 TmpPtr = ArpReplyPacket.ArpData;\r
239 CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);\r
240\r
241 TmpPtr += SnpMode->HwAddressSize;\r
242 CopyMem (TmpPtr, &PxeBcMode->StationIp, Private->IpLength);\r
243\r
244 TmpPtr += Private->IpLength;\r
245 CopyMem (TmpPtr, SrcHwAddr, SnpMode->HwAddressSize);\r
246\r
247 TmpPtr += SnpMode->HwAddressSize;\r
248 CopyMem (TmpPtr, SrcPrAddr, Private->IpLength);\r
249\r
250 //\r
251 // Now send out the ARP reply.\r
252 //\r
253 CopyMem (&TmpMacAddr, SrcHwAddr, sizeof (EFI_MAC_ADDRESS));\r
254\r
255 SendPacket (\r
256 Private,\r
257 &ArpReplyPacket.MediaHeader,\r
258 &ArpReplyPacket.ArpHeader,\r
259 sizeof (ARP_HEADER) + 2 * (Private->IpLength + SnpMode->HwAddressSize),\r
260 &TmpMacAddr,\r
261 PXE_PROTOCOL_ETHERNET_ARP,\r
262 EFI_PXE_BASE_CODE_FUNCTION_ARP\r
263 );\r
264\r
265 //\r
266 // Give time (100 microseconds) for ARP reply to get onto wire.\r
267 //\r
268 gBS->Stall (1000);\r
269}\r
270\r
271/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
272BOOLEAN\r
273GetHwAddr (\r
274 IN PXE_BASECODE_DEVICE *Private,\r
275 IN EFI_IP_ADDRESS *ProtocolAddrPtr,\r
276 OUT EFI_MAC_ADDRESS *HardwareAddrPtr\r
277 )\r
278/*++\r
279Routine description:\r
280 Locate IP address in ARP cache and return MAC address.\r
281\r
282Parameters:\r
283 Private := Pointer to PxeBc interface\r
284 ProtocolAddrPtr := Pointer to IP address\r
285 HardwareAddrPtr := Pointer to MAC address storage\r
286\r
287Returns:\r
288 TRUE := If IP address was found and MAC address was stored\r
289 FALSE := If IP address was not found\r
290--*/\r
291{\r
292 EFI_PXE_BASE_CODE_MODE *PxeBcMode;\r
293 UINTN HardwareAddrLength;\r
294 UINTN Index;\r
295\r
296 PxeBcMode = Private->EfiBc.Mode;\r
297 HardwareAddrLength = Private->SimpleNetwork->Mode->HwAddressSize;\r
298\r
299 for (Index = 0; Index < PxeBcMode->ArpCacheEntries; ++Index) {\r
300 if (!CompareMem (\r
301 ProtocolAddrPtr,\r
302 &PxeBcMode->ArpCache[Index].IpAddr,\r
303 Private->IpLength\r
304 )) {\r
305 CopyMem (\r
306 HardwareAddrPtr,\r
307 &PxeBcMode->ArpCache[Index].MacAddr,\r
308 HardwareAddrLength\r
309 );\r
310\r
311 return TRUE;\r
312 }\r
313 }\r
314\r
315 return FALSE;\r
316}\r
317\r
318/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
319STATIC\r
320EFI_STATUS\r
321SendRequest (\r
322 IN PXE_BASECODE_DEVICE *Private,\r
323 IN EFI_IP_ADDRESS *ProtocolAddrPtr,\r
324 IN EFI_MAC_ADDRESS *HardwareAddrPtr\r
325 )\r
326/*++\r
327Routine description:\r
328 Transmit ARP request packet\r
329\r
330Parameters:\r
331 Private := Pointer to PxeBc interface\r
332 ProtocolAddrPtr := Pointer IP address to find\r
333 HardwareAddrPtr := Pointer to MAC address to find\r
334\r
335Returns:\r
336 EFI_SUCCESS := ARP request sent\r
337 other := ARP request could not be sent\r
338--*/\r
339{\r
340 EFI_PXE_BASE_CODE_MODE *PxeBcMode;\r
341 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
342 ARP_PACKET *ArpPacket;\r
878ddf1f 343 UINTN HardwareAddrLength;\r
344 UINT8 *SrcProtocolAddrPtr;\r
345 UINT8 *DestHardwareAddrptr;\r
346 UINT8 *DestProtocolAddrPtr;\r
347\r
348 //\r
349 //\r
350 //\r
351 PxeBcMode = Private->EfiBc.Mode;\r
352 SnpMode = Private->SimpleNetwork->Mode;\r
353 HardwareAddrLength = SnpMode->HwAddressSize;\r
354\r
355 //\r
356 // Allocate ARP buffer\r
357 //\r
358 if (Private->ArpBuffer == NULL) {\r
26aa0c2f
LG
359 Private->ArpBuffer = AllocatePool (SnpMode->MediaHeaderSize + sizeof (ARP_PACKET));\r
360 if (Private->ArpBuffer == NULL) {\r
361 return EFI_OUT_OF_RESOURCES;\r
878ddf1f 362 }\r
363 }\r
364\r
365 ArpPacket = (VOID *) (Private->ArpBuffer + SnpMode->MediaHeaderSize);\r
366\r
367 //\r
368 // for now, only handle one kind of hw and pr address\r
369 //\r
370 ArpPacket->ArpHeader = ArpHeader;\r
371 ArpPacket->ArpHeader.HwAddLen = (UINT8) HardwareAddrLength;\r
372 ArpPacket->ArpHeader.ProtAddLen = (UINT8) Private->IpLength;\r
373\r
374 //\r
375 // rest more generic\r
376 //\r
377 SrcProtocolAddrPtr = (UINT8 *) (&ArpPacket->SrcHardwareAddr) + HardwareAddrLength;\r
378 DestHardwareAddrptr = SrcProtocolAddrPtr + Private->IpLength;\r
379 DestProtocolAddrPtr = DestHardwareAddrptr + HardwareAddrLength;\r
380\r
381 CopyMem (DestProtocolAddrPtr, ProtocolAddrPtr, Private->IpLength);\r
382 CopyMem (DestHardwareAddrptr, HardwareAddrPtr, HardwareAddrLength);\r
383 CopyMem (SrcProtocolAddrPtr, &PxeBcMode->StationIp, Private->IpLength);\r
384 CopyMem (\r
385 &ArpPacket->SrcHardwareAddr,\r
386 &SnpMode->CurrentAddress,\r
387 HardwareAddrLength\r
388 );\r
389\r
390 return SendPacket (\r
391 Private,\r
392 Private->ArpBuffer,\r
393 ArpPacket,\r
394 sizeof (ARP_HEADER) + ((Private->IpLength + HardwareAddrLength) << 1),\r
395 &SnpMode->BroadcastAddress,\r
396 PXE_PROTOCOL_ETHERNET_ARP,\r
397 EFI_PXE_BASE_CODE_FUNCTION_ARP\r
398 );\r
399}\r
400\r
401/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
402\r
403//\r
404// check for address - if not there, send ARP request, wait and check again\r
405// not how it would be done in a full system\r
406//\r
407#define ARP_REQUEST_TIMEOUT_MS 500 // try for half a second\r
408 \r
409 ////////////////////////////////////////////////////////////\r
410//\r
411// BC Arp Routine\r
412//\r
413EFI_STATUS\r
414EFIAPI\r
415BcArp (\r
416 IN EFI_PXE_BASE_CODE_PROTOCOL * This,\r
417 IN EFI_IP_ADDRESS * ProtocolAddrPtr,\r
418 OUT EFI_MAC_ADDRESS * HardwareAddrPtr OPTIONAL\r
419 )\r
420/*++\r
421Routine description:\r
422 PxeBc ARP API.\r
423\r
424Parameters:\r
425 This := Pointer to PxeBc interface\r
426 ProtocolAddrPtr := Pointer to IP address to find\r
427 HardwareAddrPtr := Pointer to MAC address found.\r
428\r
429Returns:\r
430--*/\r
431{\r
432 EFI_MAC_ADDRESS Mac;\r
433 EFI_STATUS StatCode;\r
434 PXE_BASECODE_DEVICE *Private;\r
435\r
436 //\r
437 // Lock the instance data and make sure started\r
438 //\r
439 StatCode = EFI_SUCCESS;\r
440\r
441 if (This == NULL) {\r
442 DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
443 return EFI_INVALID_PARAMETER;\r
444 }\r
445\r
446 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
447\r
448 if (Private == NULL) {\r
449 DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
450 return EFI_INVALID_PARAMETER;\r
451 }\r
452\r
453 EfiAcquireLock (&Private->Lock);\r
454\r
455 if (This->Mode == NULL || !This->Mode->Started) {\r
456 DEBUG ((EFI_D_ERROR, "BC was not started."));\r
457 EfiReleaseLock (&Private->Lock);\r
458 return EFI_NOT_STARTED;\r
459 }\r
460\r
461 DEBUG ((EFI_D_INFO, "\nBcArp()"));\r
462\r
463 //\r
464 // Issue BC command\r
465 //\r
466 if (ProtocolAddrPtr == NULL) {\r
467 DEBUG (\r
468 (EFI_D_INFO,\r
469 "\nBcArp() Exit #1 %Xh (%r)",\r
470 EFI_INVALID_PARAMETER,\r
471 EFI_INVALID_PARAMETER)\r
472 );\r
473\r
474 EfiReleaseLock (&Private->Lock);\r
475 return EFI_INVALID_PARAMETER;\r
476 }\r
477\r
478 if (HardwareAddrPtr == NULL) {\r
479 HardwareAddrPtr = &Mac;\r
480 }\r
481\r
482 ZeroMem (HardwareAddrPtr, Private->SimpleNetwork->Mode->HwAddressSize);\r
483\r
484 if (GetHwAddr (Private, ProtocolAddrPtr, HardwareAddrPtr)) {\r
485 DEBUG (\r
486 (EFI_D_INFO,\r
487 "\nBcArp() Exit #2 %Xh (%r)",\r
488 EFI_SUCCESS,\r
489 EFI_SUCCESS)\r
490 );\r
491\r
492 EfiReleaseLock (&Private->Lock);\r
493 return EFI_SUCCESS;\r
494 }\r
495\r
496 StatCode = DoArp (Private, ProtocolAddrPtr, HardwareAddrPtr);\r
497\r
498 DEBUG ((EFI_D_INFO, "\nBcArp() Exit #3 %Xh (%r)", StatCode, StatCode));\r
499\r
500 EfiReleaseLock (&Private->Lock);\r
501 return StatCode;\r
502}\r
503\r
504/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
505EFI_STATUS\r
506DoArp (\r
507 IN PXE_BASECODE_DEVICE *Private,\r
508 IN EFI_IP_ADDRESS *ProtocolAddrPtr,\r
509 OUT EFI_MAC_ADDRESS *HardwareAddrPtr\r
510 )\r
511/*++\r
512Routine description:\r
513 Internal ARP implementation.\r
514\r
515Parameters:\r
516 Private := Pointer to PxeBc interface\r
517 ProtocolAddrPtr := Pointer to IP address to find\r
518 HardwareAddrPtr := Pointer to MAC address found\r
519\r
520Returns:\r
521 EFI_SUCCESS := MAC address found\r
522 other := MAC address could not be found\r
523--*/\r
524{\r
525 EFI_STATUS StatCode;\r
526 EFI_EVENT TimeoutEvent;\r
527 UINTN HeaderSize;\r
528 UINTN BufferSize;\r
529 UINT16 Protocol;\r
530\r
531 DEBUG ((EFI_D_INFO, "\nDoArp()"));\r
532\r
533 //\r
534 //\r
535 //\r
536 StatCode = SendRequest (Private, ProtocolAddrPtr, HardwareAddrPtr);\r
537\r
538 if (EFI_ERROR (StatCode)) {\r
539 DEBUG ((EFI_D_INFO, "\nDoArp() Exit #1 %Xh (%r)", StatCode, StatCode));\r
540 return StatCode;\r
541 }\r
542 //\r
543 //\r
544 //\r
545 StatCode = gBS->CreateEvent (\r
546 EFI_EVENT_TIMER,\r
547 EFI_TPL_CALLBACK,\r
548 NULL,\r
549 NULL,\r
550 &TimeoutEvent\r
551 );\r
552\r
553 if (EFI_ERROR (StatCode)) {\r
554 return StatCode;\r
555 }\r
556\r
557 StatCode = gBS->SetTimer (\r
558 TimeoutEvent,\r
559 TimerRelative,\r
560 ARP_REQUEST_TIMEOUT_MS * 10000\r
561 );\r
562\r
563 if (EFI_ERROR (StatCode)) {\r
564 gBS->CloseEvent (TimeoutEvent);\r
565 return StatCode;\r
566 }\r
567 //\r
568 //\r
569 //\r
570 for (;;) {\r
571 StatCode = WaitForReceive (\r
572 Private,\r
573 EFI_PXE_BASE_CODE_FUNCTION_ARP,\r
574 TimeoutEvent,\r
575 &HeaderSize,\r
576 &BufferSize,\r
577 &Protocol\r
578 );\r
579\r
580 if (EFI_ERROR (StatCode)) {\r
581 break;\r
582 }\r
583\r
584 if (Protocol != PXE_PROTOCOL_ETHERNET_ARP) {\r
585 continue;\r
586 }\r
587\r
588 HandleArpReceive (\r
589 Private,\r
590 (ARP_PACKET *) (Private->ReceiveBufferPtr + HeaderSize),\r
591 Private->ReceiveBufferPtr\r
592 );\r
593\r
594 if (GetHwAddr (Private, ProtocolAddrPtr, HardwareAddrPtr)) {\r
595 break;\r
596 }\r
597 }\r
598\r
599 DEBUG (\r
600 (EFI_D_INFO,\r
601 "\nDoArp() Exit #2 %Xh, (%r)",\r
602 StatCode,\r
603 StatCode)\r
604 );\r
605\r
606 gBS->CloseEvent (TimeoutEvent);\r
607\r
608 return StatCode;\r
609}\r
610\r
611/* eof - pxe_bc_arp.c */\r