]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_udp.c
Clean up Network Components to support GCC build.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / PxeBcDxe / Pxe_bc_udp.c
CommitLineData
772db4bb 1/** @file\r
2\r
3Copyright (c) 2004 - 2007, 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_udp.c\r
14\r
15Abstract:\r
16\r
17\r
18**/\r
19\r
20#include "Bc.h"\r
21\r
22//\r
23// //////////////////////////////////////////////////////////////////////\r
24//\r
25// Udp Write Routine - called by base code - e.g. TFTP - already locked\r
26//\r
27\r
28/**\r
29\r
30 @return EFI_SUCCESS :=\r
31 @return EFI_INVALID_PARAMETER :=\r
32 @return other :=\r
33\r
34**/\r
35EFI_STATUS\r
36UdpWrite (\r
37 IN PXE_BASECODE_DEVICE *Private,\r
38 IN UINT16 OpFlags,\r
39 IN EFI_IP_ADDRESS *DestIpPtr,\r
40 IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr,\r
41 IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL\r
42 IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL\r
43 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL\r
44 IN UINTN *HeaderSizePtr, OPTIONAL\r
45 IN VOID *HeaderPtr, OPTIONAL\r
46 IN UINTN *BufferSizeptr,\r
47 IN VOID *BufferPtr\r
48 )\r
49{\r
50 UINTN TotalLength;\r
51 UINTN HeaderSize;\r
52 EFI_PXE_BASE_CODE_UDP_PORT DefaultSrcPort;\r
53\r
54 //\r
55 //\r
56 //\r
57 HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0;\r
58 DefaultSrcPort = 0;\r
59\r
60 //\r
61 // check parameters\r
62 //\r
63 if (BufferSizeptr == NULL ||\r
64 BufferPtr == NULL ||\r
65 DestIpPtr == NULL ||\r
66 DestPortPtr == NULL ||\r
67 (HeaderSizePtr != NULL && *HeaderSizePtr == 0) ||\r
68 (HeaderSize != 0 && HeaderPtr == NULL) ||\r
69 (GatewayIpPtr != NULL && !IS_INADDR_UNICAST(GatewayIpPtr)) ||\r
70 (OpFlags &~(EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT))\r
71 ) {\r
72 DEBUG (\r
73 (DEBUG_WARN,\r
74 "\nUdpWrite() Exit #1 %xh (%r)",\r
75 EFI_INVALID_PARAMETER,\r
76 EFI_INVALID_PARAMETER)\r
77 );\r
78\r
79 return EFI_INVALID_PARAMETER;\r
80 }\r
81\r
82 TotalLength = *BufferSizeptr + HeaderSize + sizeof (UDPV4_HEADER);\r
83\r
84 if (TotalLength > 0x0000ffff) {\r
85 DEBUG (\r
86 (DEBUG_WARN,\r
87 "\nUdpWrite() Exit #2 %xh (%r)",\r
88 EFI_BAD_BUFFER_SIZE,\r
89 EFI_BAD_BUFFER_SIZE)\r
90 );\r
91\r
92 return EFI_BAD_BUFFER_SIZE;\r
93 }\r
94\r
95 if (SrcIpPtr == NULL) {\r
96 SrcIpPtr = &Private->EfiBc.Mode->StationIp;\r
97 }\r
98\r
99 if (SrcPortPtr == NULL) {\r
100 SrcPortPtr = &DefaultSrcPort;\r
101 OpFlags |= EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT;\r
102 }\r
103\r
104 if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) {\r
105 *SrcPortPtr = Private->RandomPort;\r
106\r
107 if (++Private->RandomPort == 0) {\r
108 Private->RandomPort = PXE_RND_PORT_LOW;\r
109 }\r
110 }\r
111\r
112#define IpTxBuffer ((IPV4_BUFFER *) Private->TransmitBufferPtr)\r
113 //\r
114 // build pseudo header and udp header in transmit buffer\r
115 //\r
116#define Udpv4Base ((UDPV4_HEADERS *) (IpTxBuffer->u.Data - sizeof (UDPV4_PSEUDO_HEADER)))\r
117\r
118 Udpv4Base->Udpv4PseudoHeader.SrcAddr.L = SrcIpPtr->Addr[0];\r
119 Udpv4Base->Udpv4PseudoHeader.DestAddr.L = DestIpPtr->Addr[0];\r
120 Udpv4Base->Udpv4PseudoHeader.Zero = 0;\r
121 Udpv4Base->Udpv4PseudoHeader.Protocol = PROT_UDP;\r
122 Udpv4Base->Udpv4PseudoHeader.TotalLength = HTONS (TotalLength);\r
123 Udpv4Base->Udpv4Header.SrcPort = HTONS (*SrcPortPtr);\r
124 Udpv4Base->Udpv4Header.DestPort = HTONS (*DestPortPtr);\r
125 Udpv4Base->Udpv4Header.TotalLength = Udpv4Base->Udpv4PseudoHeader.TotalLength;\r
126 Udpv4Base->Udpv4Header.Checksum = 0;\r
127\r
128 if (HeaderSize != 0) {\r
129 CopyMem (IpTxBuffer->u.Udp.Data, HeaderPtr, HeaderSize);\r
130 }\r
131\r
132 HeaderSize += sizeof (UDPV4_HEADER);\r
133\r
134 Udpv4Base->Udpv4Header.Checksum = IpChecksum2 (\r
135 (UINT16 *) Udpv4Base,\r
136 HeaderSize + sizeof (UDPV4_PSEUDO_HEADER),\r
137 (UINT16 *) BufferPtr,\r
138 (UINT16) *BufferSizeptr\r
139 );\r
140\r
141 if (Udpv4Base->Udpv4Header.Checksum == 0) {\r
142 Udpv4Base->Udpv4Header.Checksum = 0xffff;\r
143 //\r
144 // transmit zero checksum as ones complement\r
145 //\r
146 }\r
147\r
148 return Ip4Send (\r
149 Private,\r
150 OpFlags,\r
151 PROT_UDP,\r
152 Udpv4Base->Udpv4PseudoHeader.SrcAddr.L,\r
153 Udpv4Base->Udpv4PseudoHeader.DestAddr.L,\r
154 (GatewayIpPtr) ? GatewayIpPtr->Addr[0] : 0,\r
155 HeaderSize,\r
156 BufferPtr,\r
157 *BufferSizeptr\r
158 );\r
159}\r
160//\r
161// //////////////////////////////////////////////////////////\r
162//\r
163// BC Udp Write Routine\r
164//\r
165\r
166/**\r
167\r
168 @return EFI_SUCCESS :=\r
169 @return other :=\r
170\r
171**/\r
172EFI_STATUS\r
173EFIAPI\r
174BcUdpWrite (\r
175 IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
176 IN UINT16 OpFlags,\r
177 IN EFI_IP_ADDRESS *DestIpPtr,\r
178 IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr,\r
179 IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL\r
180 IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL\r
181 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL\r
182 IN UINTN *HeaderSizePtr, OPTIONAL\r
183 IN VOID *HeaderPtr, OPTIONAL\r
184 IN UINTN *BufferSizeptr,\r
185 IN VOID *BufferPtr\r
186 )\r
187{\r
188 EFI_STATUS StatCode;\r
189 PXE_BASECODE_DEVICE *Private;\r
190\r
191 //\r
192 // Lock the instance data and make sure started\r
193 //\r
194 StatCode = EFI_SUCCESS;\r
195\r
196 if (This == NULL) {\r
197 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
198 return EFI_INVALID_PARAMETER;\r
199 }\r
200\r
201 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
202\r
203 if (Private == NULL) {\r
204 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
205 return EFI_INVALID_PARAMETER;\r
206 }\r
207\r
208 EfiAcquireLock (&Private->Lock);\r
209\r
210 if (This->Mode == NULL || !This->Mode->Started) {\r
211 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
212 EfiReleaseLock (&Private->Lock);\r
213 return EFI_NOT_STARTED;\r
214 }\r
215\r
216 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE;\r
217\r
218 //\r
219 // Issue BC command\r
220 //\r
221 StatCode = UdpWrite (\r
222 Private,\r
223 OpFlags,\r
224 DestIpPtr,\r
225 DestPortPtr,\r
226 GatewayIpPtr,\r
227 SrcIpPtr,\r
228 SrcPortPtr,\r
229 HeaderSizePtr,\r
230 HeaderPtr,\r
231 BufferSizeptr,\r
232 BufferPtr\r
233 );\r
234\r
235 //\r
236 // Unlock the instance data\r
237 //\r
238 EfiReleaseLock (&Private->Lock);\r
239 return StatCode;\r
240}\r
241//\r
242// /////////////////////////////////////////////////////////////////////\r
243//\r
244// Udp Read Routine - called by base code - e.g. TFTP - already locked\r
245//\r
246\r
247/**\r
248\r
249 @return EFI_SUCCESS :=\r
250 @return EFI_INVALID_PARAMETER :=\r
251 @return other :=\r
252\r
253**/\r
254EFI_STATUS\r
255UdpRead (\r
256 IN PXE_BASECODE_DEVICE *Private,\r
257 IN UINT16 OpFlags,\r
258 IN OUT EFI_IP_ADDRESS *DestIpPtr, OPTIONAL\r
259 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr, OPTIONAL\r
260 IN OUT EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL\r
261 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL\r
262 IN UINTN *HeaderSizePtr, OPTIONAL\r
263 IN VOID *HeaderPtr, OPTIONAL\r
264 IN OUT UINTN *BufferSizeptr,\r
265 IN VOID *BufferPtr,\r
266 EFI_EVENT TimeoutEvent\r
267 )\r
268{\r
269 EFI_STATUS StatCode;\r
270 EFI_IP_ADDRESS TmpSrcIp;\r
271 EFI_IP_ADDRESS TmpDestIp;\r
272 UINTN BufferSize;\r
273 UINTN HeaderSize;\r
274\r
275 //\r
276 // combination structure of pseudo header/udp header\r
277 //\r
278#pragma pack (1)\r
279 struct {\r
280 UDPV4_PSEUDO_HEADER Udpv4PseudoHeader;\r
281 UDPV4_HEADER Udpv4Header;\r
282 UINT8 ProtHdr[64];\r
283 } Hdrs;\r
284#pragma pack ()\r
285\r
286 HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0;\r
287 //\r
288 // read [with filtering]\r
289 // check parameters\r
290 //\r
291 if (BufferSizeptr == NULL ||\r
292 BufferPtr == NULL ||\r
293 (HeaderSize != 0 && HeaderPtr == NULL) ||\r
294 (OpFlags &~UDP_FILTER_MASK)\r
295 //\r
296 // if filtering on a particular IP/Port, need it\r
297 //\r
298 ||\r
299 (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr == NULL) ||\r
300 (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && SrcPortPtr == NULL) ||\r
301 (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && DestPortPtr == NULL)\r
302 ) {\r
303 DEBUG ((DEBUG_INFO, "\nUdpRead() Exit #1 Invalid Parameter"));\r
304 return EFI_INVALID_PARAMETER;\r
305 }\r
306\r
307 //\r
308 // in case we loop\r
309 //\r
310 BufferSize = *BufferSizeptr;\r
311 //\r
312 // we need source and dest IPs for pseudo header\r
313 //\r
314 if (SrcIpPtr == NULL) {\r
315 SrcIpPtr = &TmpSrcIp;\r
316 }\r
317\r
318 if (DestIpPtr == NULL) {\r
319 DestIpPtr = &TmpDestIp;\r
67a58d0f 320 CopyMem (&TmpDestIp, &Private->EfiBc.Mode->StationIp, sizeof (EFI_IP_ADDRESS));\r
772db4bb 321 }\r
322\r
323#if SUPPORT_IPV6\r
324 if (Private->EfiBc.Mode->UsingIpv6) {\r
325 //\r
326 // %%TBD\r
327 //\r
328 }\r
329#endif\r
330\r
331 for (;;) {\r
332 *BufferSizeptr = BufferSize;\r
333\r
334 StatCode = IpReceive (\r
335 Private,\r
336 OpFlags,\r
337 SrcIpPtr,\r
338 DestIpPtr,\r
339 PROT_UDP,\r
340 &Hdrs.Udpv4Header,\r
341 HeaderSize + sizeof Hdrs.Udpv4Header,\r
342 BufferPtr,\r
343 BufferSizeptr,\r
344 TimeoutEvent\r
345 );\r
346\r
347 if (StatCode == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) {\r
348 UINT16 SPort;\r
349 UINT16 DPort;\r
350\r
351 SPort = NTOHS (Hdrs.Udpv4Header.SrcPort);\r
352 DPort = NTOHS (Hdrs.Udpv4Header.DestPort);\r
353\r
354 //\r
355 // do filtering\r
356 //\r
357 if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && *SrcPortPtr != SPort) {\r
358 continue;\r
359 }\r
360\r
361 if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && *DestPortPtr != DPort) {\r
362 continue;\r
363 }\r
364 //\r
365 // check checksum\r
366 //\r
367 if (StatCode == EFI_SUCCESS && Hdrs.Udpv4Header.Checksum) {\r
368 Hdrs.Udpv4PseudoHeader.SrcAddr.L = SrcIpPtr->Addr[0];\r
369 Hdrs.Udpv4PseudoHeader.DestAddr.L = DestIpPtr->Addr[0];\r
370 Hdrs.Udpv4PseudoHeader.Zero = 0;\r
371 Hdrs.Udpv4PseudoHeader.Protocol = PROT_UDP;\r
372 Hdrs.Udpv4PseudoHeader.TotalLength = Hdrs.Udpv4Header.TotalLength;\r
373\r
374 if (Hdrs.Udpv4Header.Checksum == 0xffff) {\r
375 Hdrs.Udpv4Header.Checksum = 0;\r
376 }\r
377\r
378 if (IpChecksum2 (\r
379 (UINT16 *) &Hdrs.Udpv4PseudoHeader,\r
380 HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader) + sizeof (Hdrs.Udpv4Header),\r
381 (UINT16 *) BufferPtr,\r
382 *BufferSizeptr\r
383 )) {\r
384 DEBUG (\r
385 (DEBUG_INFO,\r
386 "\nUdpRead() Hdrs.Udpv4PseudoHeader == %Xh",\r
67a58d0f 387 &Hdrs.Udpv4PseudoHeader)\r
772db4bb 388 );\r
389 DEBUG (\r
390 (DEBUG_INFO,\r
391 "\nUdpRead() Header size == %d",\r
392 HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader))\r
393 );\r
394 DEBUG (\r
395 (DEBUG_INFO,\r
396 "\nUdpRead() BufferPtr == %Xh",\r
397 BufferPtr)\r
398 );\r
399 DEBUG (\r
400 (DEBUG_INFO,\r
401 "\nUdpRead() Buffer size == %d",\r
402 *BufferSizeptr)\r
403 );\r
404 DEBUG ((DEBUG_INFO, "\nUdpRead() Exit #2 Device Error"));\r
405 return EFI_DEVICE_ERROR;\r
406 }\r
407 }\r
408 //\r
409 // all passed\r
410 //\r
411 if (SrcPortPtr != NULL) {\r
412 *SrcPortPtr = SPort;\r
413 }\r
414\r
415 if (DestPortPtr != NULL) {\r
416 *DestPortPtr = DPort;\r
417 }\r
418\r
419 if (HeaderSize != 0) {\r
420 CopyMem (HeaderPtr, Hdrs.ProtHdr, HeaderSize);\r
421 }\r
422 }\r
423\r
424 if ((StatCode != EFI_SUCCESS) && (StatCode != EFI_TIMEOUT)) {\r
425 DEBUG (\r
426 (DEBUG_INFO,\r
427 "\nUdpRead() Exit #3 %Xh %r",\r
428 StatCode,\r
429 StatCode)\r
430 );\r
431 }\r
432\r
433 return StatCode;\r
434 }\r
435}\r
436//\r
437// //////////////////////////////////////////////////////////\r
438//\r
439// BC Udp Read Routine\r
440//\r
441\r
442/**\r
443\r
444 @return EFI_SUCCESS :=\r
445 @return other :=\r
446\r
447**/\r
448EFI_STATUS\r
449EFIAPI\r
450BcUdpRead (\r
451 IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
452 IN UINT16 OpFlags,\r
453 IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL\r
454 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL\r
455 IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL\r
456 IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL\r
457 IN UINTN *HeaderSize, OPTIONAL\r
458 IN VOID *HeaderPtr, OPTIONAL\r
459 IN OUT UINTN *BufferSize,\r
460 IN VOID *BufferPtr\r
461 )\r
462{\r
463 EFI_STATUS StatCode;\r
464 PXE_BASECODE_DEVICE *Private;\r
465\r
466 //\r
467 // Lock the instance data and make sure started\r
468 //\r
469 StatCode = EFI_SUCCESS;\r
470\r
471 if (This == NULL) {\r
472 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
473 return EFI_INVALID_PARAMETER;\r
474 }\r
475\r
476 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
477\r
478 if (Private == NULL) {\r
479 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
480 return EFI_INVALID_PARAMETER;\r
481 }\r
482\r
483 EfiAcquireLock (&Private->Lock);\r
484\r
485 if (This->Mode == NULL || !This->Mode->Started) {\r
486 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
487 EfiReleaseLock (&Private->Lock);\r
488 return EFI_NOT_STARTED;\r
489 }\r
490\r
491 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_READ;\r
492\r
493 //\r
494 // Issue BC command\r
495 //\r
496 StatCode = UdpRead (\r
497 Private,\r
498 OpFlags,\r
499 DestIp,\r
500 DestPort,\r
501 SrcIp,\r
502 SrcPort,\r
503 HeaderSize,\r
504 HeaderPtr,\r
505 BufferSize,\r
506 BufferPtr,\r
507 0\r
508 );\r
509\r
510 //\r
511 // Unlock the instance data and return\r
512 //\r
513 EfiReleaseLock (&Private->Lock);\r
514 return StatCode;\r
515}\r
516\r
517/* eof - pxe_bc_udp.c */\r