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