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