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