]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeNetLib/NetBuffer.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Library / DxeNetLib / NetBuffer.c
1 /** @file
2 Network library functions providing net buffer operation support.
3
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 **/
13
14 #include <Uefi.h>
15
16 #include <Library/NetLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/MemoryAllocationLib.h>
22
23
24 /**
25 Allocate and build up the sketch for a NET_BUF.
26
27 The net buffer allocated has the BlockOpNum's NET_BLOCK_OP, and its associated
28 NET_VECTOR has the BlockNum's NET_BLOCK. But all the NET_BLOCK_OP and
29 NET_BLOCK remain un-initialized.
30
31 @param[in] BlockNum The number of NET_BLOCK in the vector of net buffer
32 @param[in] BlockOpNum The number of NET_BLOCK_OP in the net buffer
33
34 @return Pointer to the allocated NET_BUF, or NULL if the
35 allocation failed due to resource limit.
36
37 **/
38 NET_BUF *
39 NetbufAllocStruct (
40 IN UINT32 BlockNum,
41 IN UINT32 BlockOpNum
42 )
43 {
44 NET_BUF *Nbuf;
45 NET_VECTOR *Vector;
46
47 ASSERT (BlockOpNum >= 1);
48
49 //
50 // Allocate three memory blocks.
51 //
52 Nbuf = AllocateZeroPool (NET_BUF_SIZE (BlockOpNum));
53
54 if (Nbuf == NULL) {
55 return NULL;
56 }
57
58 Nbuf->Signature = NET_BUF_SIGNATURE;
59 Nbuf->RefCnt = 1;
60 Nbuf->BlockOpNum = BlockOpNum;
61 InitializeListHead (&Nbuf->List);
62
63 if (BlockNum != 0) {
64 Vector = AllocateZeroPool (NET_VECTOR_SIZE (BlockNum));
65
66 if (Vector == NULL) {
67 goto FreeNbuf;
68 }
69
70 Vector->Signature = NET_VECTOR_SIGNATURE;
71 Vector->RefCnt = 1;
72 Vector->BlockNum = BlockNum;
73 Nbuf->Vector = Vector;
74 }
75
76 return Nbuf;
77
78 FreeNbuf:
79
80 FreePool (Nbuf);
81 return NULL;
82 }
83
84
85 /**
86 Allocate a single block NET_BUF. Upon allocation, all the
87 free space is in the tail room.
88
89 @param[in] Len The length of the block.
90
91 @return Pointer to the allocated NET_BUF, or NULL if the
92 allocation failed due to resource limit.
93
94 **/
95 NET_BUF *
96 EFIAPI
97 NetbufAlloc (
98 IN UINT32 Len
99 )
100 {
101 NET_BUF *Nbuf;
102 NET_VECTOR *Vector;
103 UINT8 *Bulk;
104
105 ASSERT (Len > 0);
106
107 Nbuf = NetbufAllocStruct (1, 1);
108
109 if (Nbuf == NULL) {
110 return NULL;
111 }
112
113 Bulk = AllocatePool (Len);
114
115 if (Bulk == NULL) {
116 goto FreeNBuf;
117 }
118
119 Vector = Nbuf->Vector;
120 Vector->Len = Len;
121
122 Vector->Block[0].Bulk = Bulk;
123 Vector->Block[0].Len = Len;
124
125 Nbuf->BlockOp[0].BlockHead = Bulk;
126 Nbuf->BlockOp[0].BlockTail = Bulk + Len;
127
128 Nbuf->BlockOp[0].Head = Bulk;
129 Nbuf->BlockOp[0].Tail = Bulk;
130 Nbuf->BlockOp[0].Size = 0;
131
132 return Nbuf;
133
134 FreeNBuf:
135 FreePool (Nbuf);
136 return NULL;
137 }
138
139 /**
140 Free the net vector.
141
142 Decrease the reference count of the net vector by one. The real resource free
143 operation isn't performed until the reference count of the net vector is
144 decreased to 0.
145
146 @param[in] Vector Pointer to the NET_VECTOR to be freed.
147
148 **/
149 VOID
150 NetbufFreeVector (
151 IN NET_VECTOR *Vector
152 )
153 {
154 UINT32 Index;
155
156 ASSERT (Vector != NULL);
157 NET_CHECK_SIGNATURE (Vector, NET_VECTOR_SIGNATURE);
158 ASSERT (Vector->RefCnt > 0);
159
160 Vector->RefCnt--;
161
162 if (Vector->RefCnt > 0) {
163 return;
164 }
165
166 if (Vector->Free != NULL) {
167 //
168 // Call external free function to free the vector if it
169 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
170 // first block since it is allocated by us
171 //
172 if ((Vector->Flag & NET_VECTOR_OWN_FIRST) != 0) {
173 gBS->FreePool (Vector->Block[0].Bulk);
174 }
175
176 Vector->Free (Vector->Arg);
177
178 } else {
179 //
180 // Free each memory block associated with the Vector
181 //
182 for (Index = 0; Index < Vector->BlockNum; Index++) {
183 gBS->FreePool (Vector->Block[Index].Bulk);
184 }
185 }
186
187 FreePool (Vector);
188 }
189
190
191 /**
192 Free the net buffer and its associated NET_VECTOR.
193
194 Decrease the reference count of the net buffer by one. Free the associated net
195 vector and itself if the reference count of the net buffer is decreased to 0.
196 The net vector free operation just decrease the reference count of the net
197 vector by one and do the real resource free operation when the reference count
198 of the net vector is 0.
199
200 @param[in] Nbuf Pointer to the NET_BUF to be freed.
201
202 **/
203 VOID
204 EFIAPI
205 NetbufFree (
206 IN NET_BUF *Nbuf
207 )
208 {
209 ASSERT (Nbuf != NULL);
210 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
211 ASSERT (Nbuf->RefCnt > 0);
212
213 Nbuf->RefCnt--;
214
215 if (Nbuf->RefCnt == 0) {
216 //
217 // Update Vector only when NBuf is to be released. That is,
218 // all the sharing of Nbuf increse Vector's RefCnt by one
219 //
220 NetbufFreeVector (Nbuf->Vector);
221 FreePool (Nbuf);
222 }
223 }
224
225
226 /**
227 Create a copy of the net buffer that shares the associated net vector.
228
229 The reference count of the newly created net buffer is set to 1. The reference
230 count of the associated net vector is increased by one.
231
232 @param[in] Nbuf Pointer to the net buffer to be cloned.
233
234 @return Pointer to the cloned net buffer, or NULL if the
235 allocation failed due to resource limit.
236
237 **/
238 NET_BUF *
239 EFIAPI
240 NetbufClone (
241 IN NET_BUF *Nbuf
242 )
243 {
244 NET_BUF *Clone;
245
246 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
247
248 Clone = AllocatePool (NET_BUF_SIZE (Nbuf->BlockOpNum));
249
250 if (Clone == NULL) {
251 return NULL;
252 }
253
254 Clone->Signature = NET_BUF_SIGNATURE;
255 Clone->RefCnt = 1;
256 InitializeListHead (&Clone->List);
257
258 Clone->Ip = Nbuf->Ip;
259 Clone->Tcp = Nbuf->Tcp;
260
261 CopyMem (Clone->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);
262
263 NET_GET_REF (Nbuf->Vector);
264
265 Clone->Vector = Nbuf->Vector;
266 Clone->BlockOpNum = Nbuf->BlockOpNum;
267 Clone->TotalSize = Nbuf->TotalSize;
268 CopyMem (Clone->BlockOp, Nbuf->BlockOp, sizeof (NET_BLOCK_OP) * Nbuf->BlockOpNum);
269
270 return Clone;
271 }
272
273
274 /**
275 Create a duplicated copy of the net buffer with data copied and HeadSpace
276 bytes of head space reserved.
277
278 The duplicated net buffer will allocate its own memory to hold the data of the
279 source net buffer.
280
281 @param[in] Nbuf Pointer to the net buffer to be duplicated from.
282 @param[in, out] Duplicate Pointer to the net buffer to duplicate to, if
283 NULL a new net buffer is allocated.
284 @param[in] HeadSpace Length of the head space to reserve.
285
286 @return Pointer to the duplicated net buffer, or NULL if
287 the allocation failed due to resource limit.
288
289 **/
290 NET_BUF *
291 EFIAPI
292 NetbufDuplicate (
293 IN NET_BUF *Nbuf,
294 IN OUT NET_BUF *Duplicate OPTIONAL,
295 IN UINT32 HeadSpace
296 )
297 {
298 UINT8 *Dst;
299
300 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
301
302 if (Duplicate == NULL) {
303 Duplicate = NetbufAlloc (Nbuf->TotalSize + HeadSpace);
304 }
305
306 if (Duplicate == NULL) {
307 return NULL;
308 }
309
310 //
311 // Don't set the IP and TCP head point, since it is most
312 // like that they are pointing to the memory of Nbuf.
313 //
314 CopyMem (Duplicate->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);
315 NetbufReserve (Duplicate, HeadSpace);
316
317 Dst = NetbufAllocSpace (Duplicate, Nbuf->TotalSize, NET_BUF_TAIL);
318 NetbufCopy (Nbuf, 0, Nbuf->TotalSize, Dst);
319
320 return Duplicate;
321 }
322
323
324 /**
325 Free a list of net buffers.
326
327 @param[in, out] Head Pointer to the head of linked net buffers.
328
329 **/
330 VOID
331 EFIAPI
332 NetbufFreeList (
333 IN OUT LIST_ENTRY *Head
334 )
335 {
336 LIST_ENTRY *Entry;
337 LIST_ENTRY *Next;
338 NET_BUF *Nbuf;
339
340 Entry = Head->ForwardLink;
341
342 NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
343 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
344 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
345
346 RemoveEntryList (Entry);
347 NetbufFree (Nbuf);
348 }
349
350 ASSERT (IsListEmpty (Head));
351 }
352
353
354 /**
355 Get the index of NET_BLOCK_OP that contains the byte at Offset in the net
356 buffer.
357
358 This can be used to, for example, retrieve the IP header in the packet. It
359 also can be used to get the fragment that contains the byte which is used
360 mainly by the library implementation itself.
361
362 @param[in] Nbuf Pointer to the net buffer.
363 @param[in] Offset The offset of the byte.
364 @param[out] Index Index of the NET_BLOCK_OP that contains the byte at
365 Offset.
366
367 @return Pointer to the Offset'th byte of data in the net buffer, or NULL
368 if there is no such data in the net buffer.
369
370 **/
371 UINT8 *
372 EFIAPI
373 NetbufGetByte (
374 IN NET_BUF *Nbuf,
375 IN UINT32 Offset,
376 OUT UINT32 *Index OPTIONAL
377 )
378 {
379 NET_BLOCK_OP *BlockOp;
380 UINT32 Loop;
381 UINT32 Len;
382
383 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
384
385 if (Offset >= Nbuf->TotalSize) {
386 return NULL;
387 }
388
389 BlockOp = Nbuf->BlockOp;
390 Len = 0;
391
392 for (Loop = 0; Loop < Nbuf->BlockOpNum; Loop++) {
393
394 if (Len + BlockOp[Loop].Size <= Offset) {
395 Len += BlockOp[Loop].Size;
396 continue;
397 }
398
399 if (Index != NULL) {
400 *Index = Loop;
401 }
402
403 return BlockOp[Loop].Head + (Offset - Len);
404 }
405
406 return NULL;
407 }
408
409
410
411 /**
412 Set the NET_BLOCK and corresponding NET_BLOCK_OP in the net buffer and
413 corresponding net vector according to the bulk pointer and bulk length.
414
415 All the pointers in the Index'th NET_BLOCK and NET_BLOCK_OP are set to the
416 bulk's head and tail respectively. So, this function alone can't be used by
417 NetbufAlloc.
418
419 @param[in, out] Nbuf Pointer to the net buffer.
420 @param[in] Bulk Pointer to the data.
421 @param[in] Len Length of the bulk data.
422 @param[in] Index The data block index in the net buffer the bulk
423 data should belong to.
424
425 **/
426 VOID
427 NetbufSetBlock (
428 IN OUT NET_BUF *Nbuf,
429 IN UINT8 *Bulk,
430 IN UINT32 Len,
431 IN UINT32 Index
432 )
433 {
434 NET_BLOCK_OP *BlockOp;
435 NET_BLOCK *Block;
436
437 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
438 NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
439 ASSERT (Index < Nbuf->BlockOpNum);
440
441 Block = &(Nbuf->Vector->Block[Index]);
442 BlockOp = &(Nbuf->BlockOp[Index]);
443 Block->Len = Len;
444 Block->Bulk = Bulk;
445 BlockOp->BlockHead = Bulk;
446 BlockOp->BlockTail = Bulk + Len;
447 BlockOp->Head = Bulk;
448 BlockOp->Tail = Bulk + Len;
449 BlockOp->Size = Len;
450 }
451
452
453
454 /**
455 Set the NET_BLOCK_OP in the net buffer. The corresponding NET_BLOCK
456 structure is left untouched.
457
458 Some times, there is no 1:1 relationship between NET_BLOCK and NET_BLOCK_OP.
459 For example, that in NetbufGetFragment.
460
461 @param[in, out] Nbuf Pointer to the net buffer.
462 @param[in] Bulk Pointer to the data.
463 @param[in] Len Length of the bulk data.
464 @param[in] Index The data block index in the net buffer the bulk
465 data should belong to.
466
467 **/
468 VOID
469 NetbufSetBlockOp (
470 IN OUT NET_BUF *Nbuf,
471 IN UINT8 *Bulk,
472 IN UINT32 Len,
473 IN UINT32 Index
474 )
475 {
476 NET_BLOCK_OP *BlockOp;
477
478 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
479 ASSERT (Index < Nbuf->BlockOpNum);
480
481 BlockOp = &(Nbuf->BlockOp[Index]);
482 BlockOp->BlockHead = Bulk;
483 BlockOp->BlockTail = Bulk + Len;
484 BlockOp->Head = Bulk;
485 BlockOp->Tail = Bulk + Len;
486 BlockOp->Size = Len;
487 }
488
489
490 /**
491 Helper function for NetbufGetFragment. NetbufGetFragment may allocate the
492 first block to reserve HeadSpace bytes header space. So it needs to create a
493 new net vector for the first block and can avoid copy for the remaining data
494 by sharing the old net vector.
495
496 @param[in] Arg Point to the old NET_VECTOR.
497
498 **/
499 VOID
500 EFIAPI
501 NetbufGetFragmentFree (
502 IN VOID *Arg
503 )
504 {
505 NET_VECTOR *Vector;
506
507 Vector = (NET_VECTOR *)Arg;
508 NetbufFreeVector (Vector);
509 }
510
511
512 /**
513 Create a NET_BUF structure which contains Len byte data of Nbuf starting from
514 Offset.
515
516 A new NET_BUF structure will be created but the associated data in NET_VECTOR
517 is shared. This function exists to do IP packet fragmentation.
518
519 @param[in] Nbuf Pointer to the net buffer to be extracted.
520 @param[in] Offset Starting point of the data to be included in the new
521 net buffer.
522 @param[in] Len Bytes of data to be included in the new net buffer.
523 @param[in] HeadSpace Bytes of head space to reserve for protocol header.
524
525 @return Pointer to the cloned net buffer, or NULL if the
526 allocation failed due to resource limit.
527
528 **/
529 NET_BUF *
530 EFIAPI
531 NetbufGetFragment (
532 IN NET_BUF *Nbuf,
533 IN UINT32 Offset,
534 IN UINT32 Len,
535 IN UINT32 HeadSpace
536 )
537 {
538 NET_BUF *Child;
539 NET_VECTOR *Vector;
540 NET_BLOCK_OP *BlockOp;
541 UINT32 CurBlockOp;
542 UINT32 BlockOpNum;
543 UINT8 *FirstBulk;
544 UINT32 Index;
545 UINT32 First;
546 UINT32 Last;
547 UINT32 FirstSkip;
548 UINT32 FirstLen;
549 UINT32 LastLen;
550 UINT32 Cur;
551
552 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
553
554 if ((Len == 0) || (Offset + Len > Nbuf->TotalSize)) {
555 return NULL;
556 }
557
558 //
559 // First find the first and last BlockOp that contains
560 // the valid data, and compute the offset of the first
561 // BlockOp and length of the last BlockOp
562 //
563 BlockOp = Nbuf->BlockOp;
564 Cur = 0;
565
566 for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
567 if (Offset < Cur + BlockOp[Index].Size) {
568 break;
569 }
570
571 Cur += BlockOp[Index].Size;
572 }
573
574 //
575 // First is the index of the first BlockOp, FirstSkip is
576 // the offset of the first byte in the first BlockOp.
577 //
578 First = Index;
579 FirstSkip = Offset - Cur;
580 FirstLen = BlockOp[Index].Size - FirstSkip;
581
582 Last = 0;
583 LastLen = 0;
584
585 if (Len > FirstLen) {
586 Cur += BlockOp[Index].Size;
587 Index++;
588
589 for (; Index < Nbuf->BlockOpNum; Index++) {
590 if (Offset + Len <= Cur + BlockOp[Index].Size) {
591 Last = Index;
592 LastLen = Offset + Len - Cur;
593 break;
594 }
595
596 Cur += BlockOp[Index].Size;
597 }
598
599 } else {
600 Last = First;
601 LastLen = Len;
602 FirstLen = Len;
603 }
604
605 ASSERT (Last >= First);
606 BlockOpNum = Last - First + 1;
607 CurBlockOp = 0;
608
609 if (HeadSpace != 0) {
610 //
611 // Allocate an extra block to accomdate the head space.
612 //
613 BlockOpNum++;
614
615 Child = NetbufAllocStruct (1, BlockOpNum);
616
617 if (Child == NULL) {
618 return NULL;
619 }
620
621 FirstBulk = AllocatePool (HeadSpace);
622
623 if (FirstBulk == NULL) {
624 goto FreeChild;
625 }
626
627 Vector = Child->Vector;
628 Vector->Free = NetbufGetFragmentFree;
629 Vector->Arg = Nbuf->Vector;
630 Vector->Flag = NET_VECTOR_OWN_FIRST;
631 Vector->Len = HeadSpace;
632
633 //
634 // Reserve the head space in the first block
635 //
636 NetbufSetBlock (Child, FirstBulk, HeadSpace, 0);
637 Child->BlockOp[0].Head += HeadSpace;
638 Child->BlockOp[0].Size = 0;
639 CurBlockOp++;
640
641 } else {
642 Child = NetbufAllocStruct (0, BlockOpNum);
643
644 if (Child == NULL) {
645 return NULL;
646 }
647
648 Child->Vector = Nbuf->Vector;
649 }
650
651 NET_GET_REF (Nbuf->Vector);
652 Child->TotalSize = Len;
653
654 //
655 // Set all the BlockOp up, the first and last one are special
656 // and need special process.
657 //
658 NetbufSetBlockOp (
659 Child,
660 Nbuf->BlockOp[First].Head + FirstSkip,
661 FirstLen,
662 CurBlockOp++
663 );
664
665 for (Index = First + 1; Index < Last; Index++) {
666 NetbufSetBlockOp (
667 Child,
668 BlockOp[Index].Head,
669 BlockOp[Index].Size,
670 CurBlockOp++
671 );
672 }
673
674 if (First != Last) {
675 NetbufSetBlockOp (
676 Child,
677 BlockOp[Last].Head,
678 LastLen,
679 CurBlockOp
680 );
681 }
682
683 CopyMem (Child->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);
684 return Child;
685
686 FreeChild:
687
688 FreePool (Child);
689 return NULL;
690 }
691
692
693
694 /**
695 Build a NET_BUF from external blocks.
696
697 A new NET_BUF structure will be created from external blocks. Additional block
698 of memory will be allocated to hold reserved HeadSpace bytes of header room
699 and existing HeadLen bytes of header but the external blocks are shared by the
700 net buffer to avoid data copying.
701
702 @param[in] ExtFragment Pointer to the data block.
703 @param[in] ExtNum The number of the data blocks.
704 @param[in] HeadSpace The head space to be reserved.
705 @param[in] HeadLen The length of the protocol header, This function
706 will pull that number of data into a linear block.
707 @param[in] ExtFree Pointer to the caller provided free function.
708 @param[in] Arg The argument passed to ExtFree when ExtFree is
709 called.
710
711 @return Pointer to the net buffer built from the data blocks,
712 or NULL if the allocation failed due to resource
713 limit.
714
715 **/
716 NET_BUF *
717 EFIAPI
718 NetbufFromExt (
719 IN NET_FRAGMENT *ExtFragment,
720 IN UINT32 ExtNum,
721 IN UINT32 HeadSpace,
722 IN UINT32 HeadLen,
723 IN NET_VECTOR_EXT_FREE ExtFree,
724 IN VOID *Arg OPTIONAL
725 )
726 {
727 NET_BUF *Nbuf;
728 NET_VECTOR *Vector;
729 NET_FRAGMENT SavedFragment;
730 UINT32 SavedIndex;
731 UINT32 TotalLen;
732 UINT32 BlockNum;
733 UINT8 *FirstBlock;
734 UINT32 FirstBlockLen;
735 UINT8 *Header;
736 UINT32 CurBlock;
737 UINT32 Index;
738 UINT32 Len;
739 UINT32 Copied;
740
741 ASSERT ((ExtFragment != NULL) && (ExtNum > 0) && (ExtFree != NULL));
742
743 SavedFragment.Bulk = NULL;
744 SavedFragment.Len = 0;
745
746 FirstBlockLen = 0;
747 FirstBlock = NULL;
748 BlockNum = ExtNum;
749 Index = 0;
750 TotalLen = 0;
751 SavedIndex = 0;
752 Len = 0;
753 Copied = 0;
754
755 //
756 // No need to consolidate the header if the first block is
757 // longer than the header length or there is only one block.
758 //
759 if ((ExtFragment[0].Len >= HeadLen) || (ExtNum == 1)) {
760 HeadLen = 0;
761 }
762
763 //
764 // Allocate an extra block if we need to:
765 // 1. Allocate some header space
766 // 2. aggreate the packet header
767 //
768 if ((HeadSpace != 0) || (HeadLen != 0)) {
769 FirstBlockLen = HeadLen + HeadSpace;
770 FirstBlock = AllocatePool (FirstBlockLen);
771
772 if (FirstBlock == NULL) {
773 return NULL;
774 }
775
776 BlockNum++;
777 }
778
779 //
780 // Copy the header to the first block, reduce the NET_BLOCK
781 // to allocate by one for each block that is completely covered
782 // by the first bulk.
783 //
784 if (HeadLen != 0) {
785 Len = HeadLen;
786 Header = FirstBlock + HeadSpace;
787
788 for (Index = 0; Index < ExtNum; Index++) {
789 if (Len >= ExtFragment[Index].Len) {
790 CopyMem (Header, ExtFragment[Index].Bulk, ExtFragment[Index].Len);
791
792 Copied += ExtFragment[Index].Len;
793 Len -= ExtFragment[Index].Len;
794 Header += ExtFragment[Index].Len;
795 TotalLen += ExtFragment[Index].Len;
796 BlockNum--;
797
798 if (Len == 0) {
799 //
800 // Increament the index number to point to the next
801 // non-empty fragment.
802 //
803 Index++;
804 break;
805 }
806
807 } else {
808 CopyMem (Header, ExtFragment[Index].Bulk, Len);
809
810 Copied += Len;
811 TotalLen += Len;
812
813 //
814 // Adjust the block structure to exclude the data copied,
815 // So, the left-over block can be processed as other blocks.
816 // But it must be recovered later. (SavedIndex > 0) always
817 // holds since we don't aggreate the header if the first block
818 // is bigger enough that the header is continuous
819 //
820 SavedIndex = Index;
821 SavedFragment = ExtFragment[Index];
822 ExtFragment[Index].Bulk += Len;
823 ExtFragment[Index].Len -= Len;
824 break;
825 }
826 }
827 }
828
829 Nbuf = NetbufAllocStruct (BlockNum, BlockNum);
830
831 if (Nbuf == NULL) {
832 goto FreeFirstBlock;
833 }
834
835 Vector = Nbuf->Vector;
836 Vector->Free = ExtFree;
837 Vector->Arg = Arg;
838 Vector->Flag = ((FirstBlockLen != 0) ? NET_VECTOR_OWN_FIRST : 0);
839
840 //
841 // Set the first block up which may contain
842 // some head space and aggregated header
843 //
844 CurBlock = 0;
845
846 if (FirstBlockLen != 0) {
847 NetbufSetBlock (Nbuf, FirstBlock, HeadSpace + Copied, 0);
848 Nbuf->BlockOp[0].Head += HeadSpace;
849 Nbuf->BlockOp[0].Size = Copied;
850
851 CurBlock++;
852 }
853
854 for (; Index < ExtNum; Index++) {
855 NetbufSetBlock (Nbuf, ExtFragment[Index].Bulk, ExtFragment[Index].Len, CurBlock);
856 TotalLen += ExtFragment[Index].Len;
857 CurBlock++;
858 }
859
860 Vector->Len = TotalLen + HeadSpace;
861 Nbuf->TotalSize = TotalLen;
862
863 if (SavedIndex != 0) {
864 ExtFragment[SavedIndex] = SavedFragment;
865 }
866
867 return Nbuf;
868
869 FreeFirstBlock:
870 if (FirstBlock != NULL) {
871 FreePool (FirstBlock);
872 }
873 return NULL;
874 }
875
876
877 /**
878 Build a fragment table to contain the fragments in the net buffer. This is the
879 opposite operation of the NetbufFromExt.
880
881 @param[in] Nbuf Point to the net buffer.
882 @param[in, out] ExtFragment Pointer to the data block.
883 @param[in, out] ExtNum The number of the data blocks.
884
885 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than
886 ExtNum.
887 @retval EFI_SUCCESS Fragment table is built successfully.
888
889 **/
890 EFI_STATUS
891 EFIAPI
892 NetbufBuildExt (
893 IN NET_BUF *Nbuf,
894 IN OUT NET_FRAGMENT *ExtFragment,
895 IN OUT UINT32 *ExtNum
896 )
897 {
898 UINT32 Index;
899 UINT32 Current;
900
901 Current = 0;
902
903 for (Index = 0; (Index < Nbuf->BlockOpNum); Index++) {
904 if (Nbuf->BlockOp[Index].Size == 0) {
905 continue;
906 }
907
908 if (Current < *ExtNum) {
909 ExtFragment[Current].Bulk = Nbuf->BlockOp[Index].Head;
910 ExtFragment[Current].Len = Nbuf->BlockOp[Index].Size;
911 Current++;
912 } else {
913 return EFI_BUFFER_TOO_SMALL;
914 }
915 }
916
917 *ExtNum = Current;
918 return EFI_SUCCESS;
919 }
920
921
922 /**
923 Build a net buffer from a list of net buffers.
924
925 All the fragments will be collected from the list of NEW_BUF and then a new
926 net buffer will be created through NetbufFromExt.
927
928 @param[in] BufList A List of the net buffer.
929 @param[in] HeadSpace The head space to be reserved.
930 @param[in] HeaderLen The length of the protocol header, This function
931 will pull that number of data into a linear block.
932 @param[in] ExtFree Pointer to the caller provided free function.
933 @param[in] Arg The argument passed to ExtFree when ExtFree is called.
934
935 @return Pointer to the net buffer built from the list of net
936 buffers.
937
938 **/
939 NET_BUF *
940 EFIAPI
941 NetbufFromBufList (
942 IN LIST_ENTRY *BufList,
943 IN UINT32 HeadSpace,
944 IN UINT32 HeaderLen,
945 IN NET_VECTOR_EXT_FREE ExtFree,
946 IN VOID *Arg OPTIONAL
947 )
948 {
949 NET_FRAGMENT *Fragment;
950 UINT32 FragmentNum;
951 LIST_ENTRY *Entry;
952 NET_BUF *Nbuf;
953 UINT32 Index;
954 UINT32 Current;
955
956 //
957 //Compute how many blocks are there
958 //
959 FragmentNum = 0;
960
961 NET_LIST_FOR_EACH (Entry, BufList) {
962 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
963 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
964 FragmentNum += Nbuf->BlockOpNum;
965 }
966
967 //
968 //Allocate and copy block points
969 //
970 Fragment = AllocatePool (sizeof (NET_FRAGMENT) * FragmentNum);
971
972 if (Fragment == NULL) {
973 return NULL;
974 }
975
976 Current = 0;
977
978 NET_LIST_FOR_EACH (Entry, BufList) {
979 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
980 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
981
982 for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
983 if (Nbuf->BlockOp[Index].Size != 0) {
984 Fragment[Current].Bulk = Nbuf->BlockOp[Index].Head;
985 Fragment[Current].Len = Nbuf->BlockOp[Index].Size;
986 Current++;
987 }
988 }
989 }
990
991 Nbuf = NetbufFromExt (Fragment, Current, HeadSpace, HeaderLen, ExtFree, Arg);
992 FreePool (Fragment);
993
994 return Nbuf;
995 }
996
997
998 /**
999 Reserve some space in the header room of the net buffer.
1000
1001 Upon allocation, all the space are in the tail room of the buffer. Call this
1002 function to move some space to the header room. This function is quite limited
1003 in that it can only reserve space from the first block of an empty NET_BUF not
1004 built from the external. But it should be enough for the network stack.
1005
1006 @param[in, out] Nbuf Pointer to the net buffer.
1007 @param[in] Len The length of buffer to be reserved from the header.
1008
1009 **/
1010 VOID
1011 EFIAPI
1012 NetbufReserve (
1013 IN OUT NET_BUF *Nbuf,
1014 IN UINT32 Len
1015 )
1016 {
1017 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1018 NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
1019
1020 ASSERT ((Nbuf->BlockOpNum == 1) && (Nbuf->TotalSize == 0));
1021 ASSERT ((Nbuf->Vector->Free == NULL) && (Nbuf->Vector->Len >= Len));
1022
1023 Nbuf->BlockOp[0].Head += Len;
1024 Nbuf->BlockOp[0].Tail += Len;
1025
1026 ASSERT (Nbuf->BlockOp[0].Tail <= Nbuf->BlockOp[0].BlockTail);
1027 }
1028
1029
1030 /**
1031 Allocate Len bytes of space from the header or tail of the buffer.
1032
1033 @param[in, out] Nbuf Pointer to the net buffer.
1034 @param[in] Len The length of the buffer to be allocated.
1035 @param[in] FromHead The flag to indicate whether reserve the data
1036 from head (TRUE) or tail (FALSE).
1037
1038 @return Pointer to the first byte of the allocated buffer,
1039 or NULL if there is no sufficient space.
1040
1041 **/
1042 UINT8*
1043 EFIAPI
1044 NetbufAllocSpace (
1045 IN OUT NET_BUF *Nbuf,
1046 IN UINT32 Len,
1047 IN BOOLEAN FromHead
1048 )
1049 {
1050 NET_BLOCK_OP *BlockOp;
1051 UINT32 Index;
1052 UINT8 *SavedTail;
1053
1054 Index = 0;
1055
1056 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1057 NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
1058
1059 ASSERT (Len > 0);
1060
1061 if (FromHead) {
1062 //
1063 // Allocate some space from head. If the buffer is empty,
1064 // allocate from the first block. If it isn't, allocate
1065 // from the first non-empty block, or the block before that.
1066 //
1067 if (Nbuf->TotalSize == 0) {
1068 Index = 0;
1069 } else {
1070 NetbufGetByte (Nbuf, 0, &Index);
1071
1072 if ((NET_HEADSPACE(&(Nbuf->BlockOp[Index])) < Len) && (Index > 0)) {
1073 Index--;
1074 }
1075 }
1076
1077 BlockOp = &(Nbuf->BlockOp[Index]);
1078
1079 if (NET_HEADSPACE (BlockOp) < Len) {
1080 return NULL;
1081 }
1082
1083 BlockOp->Head -= Len;
1084 BlockOp->Size += Len;
1085 Nbuf->TotalSize += Len;
1086
1087 return BlockOp->Head;
1088
1089 } else {
1090 //
1091 // Allocate some space from the tail. If the buffer is empty,
1092 // allocate from the first block. If it isn't, allocate
1093 // from the last non-empty block, or the block after that.
1094 //
1095 if (Nbuf->TotalSize == 0) {
1096 Index = 0;
1097 } else {
1098 NetbufGetByte (Nbuf, Nbuf->TotalSize - 1, &Index);
1099
1100 if ((NET_TAILSPACE(&(Nbuf->BlockOp[Index])) < Len) &&
1101 (Index < Nbuf->BlockOpNum - 1)) {
1102
1103 Index++;
1104 }
1105 }
1106
1107 BlockOp = &(Nbuf->BlockOp[Index]);
1108
1109 if (NET_TAILSPACE (BlockOp) < Len) {
1110 return NULL;
1111 }
1112
1113 SavedTail = BlockOp->Tail;
1114
1115 BlockOp->Tail += Len;
1116 BlockOp->Size += Len;
1117 Nbuf->TotalSize += Len;
1118
1119 return SavedTail;
1120 }
1121 }
1122
1123
1124 /**
1125 Trim a single NET_BLOCK by Len bytes from the header or tail.
1126
1127 @param[in, out] BlockOp Pointer to the NET_BLOCK.
1128 @param[in] Len The length of the data to be trimmed.
1129 @param[in] FromHead The flag to indicate whether trim data from head
1130 (TRUE) or tail (FALSE).
1131
1132 **/
1133 VOID
1134 NetblockTrim (
1135 IN OUT NET_BLOCK_OP *BlockOp,
1136 IN UINT32 Len,
1137 IN BOOLEAN FromHead
1138 )
1139 {
1140 ASSERT ((BlockOp != NULL) && (BlockOp->Size >= Len));
1141
1142 BlockOp->Size -= Len;
1143
1144 if (FromHead) {
1145 BlockOp->Head += Len;
1146 } else {
1147 BlockOp->Tail -= Len;
1148 }
1149 }
1150
1151
1152 /**
1153 Trim Len bytes from the header or tail of the net buffer.
1154
1155 @param[in, out] Nbuf Pointer to the net buffer.
1156 @param[in] Len The length of the data to be trimmed.
1157 @param[in] FromHead The flag to indicate whether trim data from head
1158 (TRUE) or tail (FALSE).
1159
1160 @return Length of the actually trimmed data, which is possible to be less
1161 than Len because the TotalSize of Nbuf is less than Len.
1162
1163 **/
1164 UINT32
1165 EFIAPI
1166 NetbufTrim (
1167 IN OUT NET_BUF *Nbuf,
1168 IN UINT32 Len,
1169 IN BOOLEAN FromHead
1170 )
1171 {
1172 NET_BLOCK_OP *BlockOp;
1173 UINT32 Index;
1174 UINT32 Trimmed;
1175
1176 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1177
1178 if (Len == 0 || Nbuf->TotalSize == 0) {
1179 return 0;
1180 }
1181
1182 if (Len > Nbuf->TotalSize) {
1183 Len = Nbuf->TotalSize;
1184 }
1185
1186 //
1187 // If FromTail is true, iterate backward. That
1188 // is, init Index to NBuf->BlockNum - 1, and
1189 // decrease it by 1 during each loop. Otherwise,
1190 // iterate forward. That is, init Index to 0, and
1191 // increase it by 1 during each loop.
1192 //
1193 Trimmed = 0;
1194 Nbuf->TotalSize -= Len;
1195
1196 Index = (FromHead ? 0 : Nbuf->BlockOpNum - 1);
1197 BlockOp = Nbuf->BlockOp;
1198
1199 for (;;) {
1200 if (BlockOp[Index].Size == 0) {
1201 Index += (FromHead ? 1 : -1);
1202 continue;
1203 }
1204
1205 if (Len > BlockOp[Index].Size) {
1206 Len -= BlockOp[Index].Size;
1207 Trimmed += BlockOp[Index].Size;
1208 NetblockTrim (&BlockOp[Index], BlockOp[Index].Size, FromHead);
1209 } else {
1210 Trimmed += Len;
1211 NetblockTrim (&BlockOp[Index], Len, FromHead);
1212 break;
1213 }
1214
1215 Index += (FromHead ? 1 : -1);
1216 }
1217
1218 return Trimmed;
1219 }
1220
1221
1222 /**
1223 Copy Len bytes of data from the specific offset of the net buffer to the
1224 destination memory.
1225
1226 The Len bytes of data may cross the several fragments of the net buffer.
1227
1228 @param[in] Nbuf Pointer to the net buffer.
1229 @param[in] Offset The sequence number of the first byte to copy.
1230 @param[in] Len Length of the data to copy.
1231 @param[in] Dest The destination of the data to copy to.
1232
1233 @return The length of the actual copied data, or 0 if the offset
1234 specified exceeds the total size of net buffer.
1235
1236 **/
1237 UINT32
1238 EFIAPI
1239 NetbufCopy (
1240 IN NET_BUF *Nbuf,
1241 IN UINT32 Offset,
1242 IN UINT32 Len,
1243 IN UINT8 *Dest
1244 )
1245 {
1246 NET_BLOCK_OP *BlockOp;
1247 UINT32 Skip;
1248 UINT32 Left;
1249 UINT32 Copied;
1250 UINT32 Index;
1251 UINT32 Cur;
1252
1253 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1254 ASSERT (Dest);
1255
1256 if ((Len == 0) || (Nbuf->TotalSize <= Offset)) {
1257 return 0;
1258 }
1259
1260 if (Nbuf->TotalSize - Offset < Len) {
1261 Len = Nbuf->TotalSize - Offset;
1262 }
1263
1264 BlockOp = Nbuf->BlockOp;
1265
1266 //
1267 // Skip to the offset. Don't make "Offset-By-One" error here.
1268 // Cur + BLOCK.SIZE is the first sequence number of next block.
1269 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1270 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1271 // first byte is the next block's first byte.
1272 //
1273 Cur = 0;
1274
1275 for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
1276 if (BlockOp[Index].Size == 0) {
1277 continue;
1278 }
1279
1280 if (Offset < Cur + BlockOp[Index].Size) {
1281 break;
1282 }
1283
1284 Cur += BlockOp[Index].Size;
1285 }
1286
1287 //
1288 // Cur is the sequence number of the first byte in the block
1289 // Offset - Cur is the number of bytes before first byte to
1290 // to copy in the current block.
1291 //
1292 Skip = Offset - Cur;
1293 Left = BlockOp[Index].Size - Skip;
1294
1295 if (Len <= Left) {
1296 CopyMem (Dest, BlockOp[Index].Head + Skip, Len);
1297 return Len;
1298 }
1299
1300 CopyMem (Dest, BlockOp[Index].Head + Skip, Left);
1301
1302 Dest += Left;
1303 Len -= Left;
1304 Copied = Left;
1305
1306 Index++;
1307
1308 for (; Index < Nbuf->BlockOpNum; Index++) {
1309 if (Len > BlockOp[Index].Size) {
1310 Len -= BlockOp[Index].Size;
1311 Copied += BlockOp[Index].Size;
1312
1313 CopyMem (Dest, BlockOp[Index].Head, BlockOp[Index].Size);
1314 Dest += BlockOp[Index].Size;
1315 } else {
1316 Copied += Len;
1317 CopyMem (Dest, BlockOp[Index].Head, Len);
1318 break;
1319 }
1320 }
1321
1322 return Copied;
1323 }
1324
1325
1326 /**
1327 Initiate the net buffer queue.
1328
1329 @param[in, out] NbufQue Pointer to the net buffer queue to be initialized.
1330
1331 **/
1332 VOID
1333 EFIAPI
1334 NetbufQueInit (
1335 IN OUT NET_BUF_QUEUE *NbufQue
1336 )
1337 {
1338 NbufQue->Signature = NET_QUE_SIGNATURE;
1339 NbufQue->RefCnt = 1;
1340 InitializeListHead (&NbufQue->List);
1341
1342 InitializeListHead (&NbufQue->BufList);
1343 NbufQue->BufSize = 0;
1344 NbufQue->BufNum = 0;
1345 }
1346
1347
1348 /**
1349 Allocate and initialize a net buffer queue.
1350
1351 @return Pointer to the allocated net buffer queue, or NULL if the
1352 allocation failed due to resource limit.
1353
1354 **/
1355 NET_BUF_QUEUE *
1356 EFIAPI
1357 NetbufQueAlloc (
1358 VOID
1359 )
1360 {
1361 NET_BUF_QUEUE *NbufQue;
1362
1363 NbufQue = AllocatePool (sizeof (NET_BUF_QUEUE));
1364 if (NbufQue == NULL) {
1365 return NULL;
1366 }
1367
1368 NetbufQueInit (NbufQue);
1369
1370 return NbufQue;
1371 }
1372
1373
1374 /**
1375 Free a net buffer queue.
1376
1377 Decrease the reference count of the net buffer queue by one. The real resource
1378 free operation isn't performed until the reference count of the net buffer
1379 queue is decreased to 0.
1380
1381 @param[in] NbufQue Pointer to the net buffer queue to be freed.
1382
1383 **/
1384 VOID
1385 EFIAPI
1386 NetbufQueFree (
1387 IN NET_BUF_QUEUE *NbufQue
1388 )
1389 {
1390 ASSERT (NbufQue != NULL);
1391 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
1392
1393 NbufQue->RefCnt--;
1394
1395 if (NbufQue->RefCnt == 0) {
1396 NetbufQueFlush (NbufQue);
1397 FreePool (NbufQue);
1398 }
1399 }
1400
1401
1402 /**
1403 Append a net buffer to the net buffer queue.
1404
1405 @param[in, out] NbufQue Pointer to the net buffer queue.
1406 @param[in, out] Nbuf Pointer to the net buffer to be appended.
1407
1408 **/
1409 VOID
1410 EFIAPI
1411 NetbufQueAppend (
1412 IN OUT NET_BUF_QUEUE *NbufQue,
1413 IN OUT NET_BUF *Nbuf
1414 )
1415 {
1416 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
1417 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1418
1419 InsertTailList (&NbufQue->BufList, &Nbuf->List);
1420
1421 NbufQue->BufSize += Nbuf->TotalSize;
1422 NbufQue->BufNum++;
1423 }
1424
1425
1426 /**
1427 Remove a net buffer from the head in the specific queue and return it.
1428
1429 @param[in, out] NbufQue Pointer to the net buffer queue.
1430
1431 @return Pointer to the net buffer removed from the specific queue,
1432 or NULL if there is no net buffer in the specific queue.
1433
1434 **/
1435 NET_BUF *
1436 EFIAPI
1437 NetbufQueRemove (
1438 IN OUT NET_BUF_QUEUE *NbufQue
1439 )
1440 {
1441 NET_BUF *First;
1442
1443 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
1444
1445 if (NbufQue->BufNum == 0) {
1446 return NULL;
1447 }
1448
1449 First = NET_LIST_USER_STRUCT (NbufQue->BufList.ForwardLink, NET_BUF, List);
1450
1451 NetListRemoveHead (&NbufQue->BufList);
1452
1453 NbufQue->BufSize -= First->TotalSize;
1454 NbufQue->BufNum--;
1455 return First;
1456 }
1457
1458
1459 /**
1460 Copy Len bytes of data from the net buffer queue at the specific offset to the
1461 destination memory.
1462
1463 The copying operation is the same as NetbufCopy but applies to the net buffer
1464 queue instead of the net buffer.
1465
1466 @param[in] NbufQue Pointer to the net buffer queue.
1467 @param[in] Offset The sequence number of the first byte to copy.
1468 @param[in] Len Length of the data to copy.
1469 @param[out] Dest The destination of the data to copy to.
1470
1471 @return The length of the actual copied data, or 0 if the offset
1472 specified exceeds the total size of net buffer queue.
1473
1474 **/
1475 UINT32
1476 EFIAPI
1477 NetbufQueCopy (
1478 IN NET_BUF_QUEUE *NbufQue,
1479 IN UINT32 Offset,
1480 IN UINT32 Len,
1481 OUT UINT8 *Dest
1482 )
1483 {
1484 LIST_ENTRY *Entry;
1485 NET_BUF *Nbuf;
1486 UINT32 Skip;
1487 UINT32 Left;
1488 UINT32 Cur;
1489 UINT32 Copied;
1490
1491 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
1492 ASSERT (Dest != NULL);
1493
1494 if ((Len == 0) || (NbufQue->BufSize <= Offset)) {
1495 return 0;
1496 }
1497
1498 if (NbufQue->BufSize - Offset < Len) {
1499 Len = NbufQue->BufSize - Offset;
1500 }
1501
1502 //
1503 // skip to the Offset
1504 //
1505 Cur = 0;
1506 Nbuf = NULL;
1507
1508 NET_LIST_FOR_EACH (Entry, &NbufQue->BufList) {
1509 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
1510
1511 if (Offset < Cur + Nbuf->TotalSize) {
1512 break;
1513 }
1514
1515 Cur += Nbuf->TotalSize;
1516 }
1517
1518 ASSERT (Nbuf != NULL);
1519
1520 //
1521 // Copy the data in the first buffer.
1522 //
1523 Skip = Offset - Cur;
1524 Left = Nbuf->TotalSize - Skip;
1525
1526 if (Len < Left) {
1527 return NetbufCopy (Nbuf, Skip, Len, Dest);
1528 }
1529
1530 NetbufCopy (Nbuf, Skip, Left, Dest);
1531 Dest += Left;
1532 Len -= Left;
1533 Copied = Left;
1534
1535 //
1536 // Iterate over the others
1537 //
1538 Entry = Entry->ForwardLink;
1539
1540 while ((Len > 0) && (Entry != &NbufQue->BufList)) {
1541 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
1542
1543 if (Len > Nbuf->TotalSize) {
1544 Len -= Nbuf->TotalSize;
1545 Copied += Nbuf->TotalSize;
1546
1547 NetbufCopy (Nbuf, 0, Nbuf->TotalSize, Dest);
1548 Dest += Nbuf->TotalSize;
1549
1550 } else {
1551 NetbufCopy (Nbuf, 0, Len, Dest);
1552 Copied += Len;
1553 break;
1554 }
1555
1556 Entry = Entry->ForwardLink;
1557 }
1558
1559 return Copied;
1560 }
1561
1562
1563 /**
1564 Trim Len bytes of data from the buffer queue and free any net buffer
1565 that is completely trimmed.
1566
1567 The trimming operation is the same as NetbufTrim but applies to the net buffer
1568 queue instead of the net buffer.
1569
1570 @param[in, out] NbufQue Pointer to the net buffer queue.
1571 @param[in] Len Length of the data to trim.
1572
1573 @return The actual length of the data trimmed.
1574
1575 **/
1576 UINT32
1577 EFIAPI
1578 NetbufQueTrim (
1579 IN OUT NET_BUF_QUEUE *NbufQue,
1580 IN UINT32 Len
1581 )
1582 {
1583 LIST_ENTRY *Entry;
1584 LIST_ENTRY *Next;
1585 NET_BUF *Nbuf;
1586 UINT32 Trimmed;
1587
1588 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
1589
1590 if (Len == 0) {
1591 return 0;
1592 }
1593
1594 if (Len > NbufQue->BufSize) {
1595 Len = NbufQue->BufSize;
1596 }
1597
1598 NbufQue->BufSize -= Len;
1599 Trimmed = 0;
1600
1601 NET_LIST_FOR_EACH_SAFE (Entry, Next, &NbufQue->BufList) {
1602 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
1603
1604 if (Len >= Nbuf->TotalSize) {
1605 Trimmed += Nbuf->TotalSize;
1606 Len -= Nbuf->TotalSize;
1607
1608 RemoveEntryList (Entry);
1609 NetbufFree (Nbuf);
1610
1611 NbufQue->BufNum--;
1612
1613 if (Len == 0) {
1614 break;
1615 }
1616
1617 } else {
1618 Trimmed += NetbufTrim (Nbuf, Len, NET_BUF_HEAD);
1619 break;
1620 }
1621 }
1622
1623 return Trimmed;
1624 }
1625
1626
1627 /**
1628 Flush the net buffer queue.
1629
1630 @param[in, out] NbufQue Pointer to the queue to be flushed.
1631
1632 **/
1633 VOID
1634 EFIAPI
1635 NetbufQueFlush (
1636 IN OUT NET_BUF_QUEUE *NbufQue
1637 )
1638 {
1639 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
1640
1641 NetbufFreeList (&NbufQue->BufList);
1642
1643 NbufQue->BufNum = 0;
1644 NbufQue->BufSize = 0;
1645 }
1646
1647
1648 /**
1649 Compute the checksum for a bulk of data.
1650
1651 @param[in] Bulk Pointer to the data.
1652 @param[in] Len Length of the data, in bytes.
1653
1654 @return The computed checksum.
1655
1656 **/
1657 UINT16
1658 EFIAPI
1659 NetblockChecksum (
1660 IN UINT8 *Bulk,
1661 IN UINT32 Len
1662 )
1663 {
1664 register UINT32 Sum;
1665
1666 Sum = 0;
1667
1668 //
1669 // Add left-over byte, if any
1670 //
1671 if (Len % 2 != 0) {
1672 Sum += *(Bulk + Len - 1);
1673 }
1674
1675 while (Len > 1) {
1676 Sum += *(UINT16 *) Bulk;
1677 Bulk += 2;
1678 Len -= 2;
1679 }
1680
1681 //
1682 // Fold 32-bit sum to 16 bits
1683 //
1684 while ((Sum >> 16) != 0) {
1685 Sum = (Sum & 0xffff) + (Sum >> 16);
1686
1687 }
1688
1689 return (UINT16) Sum;
1690 }
1691
1692
1693 /**
1694 Add two checksums.
1695
1696 @param[in] Checksum1 The first checksum to be added.
1697 @param[in] Checksum2 The second checksum to be added.
1698
1699 @return The new checksum.
1700
1701 **/
1702 UINT16
1703 EFIAPI
1704 NetAddChecksum (
1705 IN UINT16 Checksum1,
1706 IN UINT16 Checksum2
1707 )
1708 {
1709 UINT32 Sum;
1710
1711 Sum = Checksum1 + Checksum2;
1712
1713 //
1714 // two UINT16 can only add up to a carry of 1.
1715 //
1716 if ((Sum >> 16) != 0) {
1717 Sum = (Sum & 0xffff) + 1;
1718
1719 }
1720
1721 return (UINT16) Sum;
1722 }
1723
1724
1725 /**
1726 Compute the checksum for a NET_BUF.
1727
1728 @param[in] Nbuf Pointer to the net buffer.
1729
1730 @return The computed checksum.
1731
1732 **/
1733 UINT16
1734 EFIAPI
1735 NetbufChecksum (
1736 IN NET_BUF *Nbuf
1737 )
1738 {
1739 NET_BLOCK_OP *BlockOp;
1740 UINT32 Offset;
1741 UINT16 TotalSum;
1742 UINT16 BlockSum;
1743 UINT32 Index;
1744
1745 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1746
1747 TotalSum = 0;
1748 Offset = 0;
1749 BlockOp = Nbuf->BlockOp;
1750
1751 for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
1752 if (BlockOp[Index].Size == 0) {
1753 continue;
1754 }
1755
1756 BlockSum = NetblockChecksum (BlockOp[Index].Head, BlockOp[Index].Size);
1757
1758 if ((Offset & 0x01) != 0) {
1759 //
1760 // The checksum starts with an odd byte, swap
1761 // the checksum before added to total checksum
1762 //
1763 BlockSum = SwapBytes16 (BlockSum);
1764 }
1765
1766 TotalSum = NetAddChecksum (BlockSum, TotalSum);
1767 Offset += BlockOp[Index].Size;
1768 }
1769
1770 return TotalSum;
1771 }
1772
1773
1774 /**
1775 Compute the checksum for TCP/UDP pseudo header.
1776
1777 Src and Dst are in network byte order, and Len is in host byte order.
1778
1779 @param[in] Src The source address of the packet.
1780 @param[in] Dst The destination address of the packet.
1781 @param[in] Proto The protocol type of the packet.
1782 @param[in] Len The length of the packet.
1783
1784 @return The computed checksum.
1785
1786 **/
1787 UINT16
1788 EFIAPI
1789 NetPseudoHeadChecksum (
1790 IN IP4_ADDR Src,
1791 IN IP4_ADDR Dst,
1792 IN UINT8 Proto,
1793 IN UINT16 Len
1794 )
1795 {
1796 NET_PSEUDO_HDR Hdr;
1797
1798 //
1799 // Zero the memory to relieve align problems
1800 //
1801 ZeroMem (&Hdr, sizeof (Hdr));
1802
1803 Hdr.SrcIp = Src;
1804 Hdr.DstIp = Dst;
1805 Hdr.Protocol = Proto;
1806 Hdr.Len = HTONS (Len);
1807
1808 return NetblockChecksum ((UINT8 *) &Hdr, sizeof (Hdr));
1809 }
1810
1811 /**
1812 Compute the checksum for TCP6/UDP6 pseudo header.
1813
1814 Src and Dst are in network byte order, and Len is in host byte order.
1815
1816 @param[in] Src The source address of the packet.
1817 @param[in] Dst The destination address of the packet.
1818 @param[in] NextHeader The protocol type of the packet.
1819 @param[in] Len The length of the packet.
1820
1821 @return The computed checksum.
1822
1823 **/
1824 UINT16
1825 EFIAPI
1826 NetIp6PseudoHeadChecksum (
1827 IN EFI_IPv6_ADDRESS *Src,
1828 IN EFI_IPv6_ADDRESS *Dst,
1829 IN UINT8 NextHeader,
1830 IN UINT32 Len
1831 )
1832 {
1833 NET_IP6_PSEUDO_HDR Hdr;
1834
1835 //
1836 // Zero the memory to relieve align problems
1837 //
1838 ZeroMem (&Hdr, sizeof (Hdr));
1839
1840 IP6_COPY_ADDRESS (&Hdr.SrcIp, Src);
1841 IP6_COPY_ADDRESS (&Hdr.DstIp, Dst);
1842
1843 Hdr.NextHeader = NextHeader;
1844 Hdr.Len = HTONL (Len);
1845
1846 return NetblockChecksum ((UINT8 *) &Hdr, sizeof (Hdr));
1847 }
1848
1849 /**
1850 The function frees the net buffer which allocated by the IP protocol. It releases
1851 only the net buffer and doesn't call the external free function.
1852
1853 This function should be called after finishing the process of mIpSec->ProcessExt()
1854 for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new
1855 buffer for the ESP, so there needs a function to free the old net buffer.
1856
1857 @param[in] Nbuf The network buffer to be freed.
1858
1859 **/
1860 VOID
1861 NetIpSecNetbufFree (
1862 NET_BUF *Nbuf
1863 )
1864 {
1865 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1866 ASSERT (Nbuf->RefCnt > 0);
1867
1868 Nbuf->RefCnt--;
1869
1870 if (Nbuf->RefCnt == 0) {
1871
1872 //
1873 // Update Vector only when NBuf is to be released. That is,
1874 // all the sharing of Nbuf increse Vector's RefCnt by one
1875 //
1876 NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
1877 ASSERT (Nbuf->Vector->RefCnt > 0);
1878
1879 Nbuf->Vector->RefCnt--;
1880
1881 if (Nbuf->Vector->RefCnt > 0) {
1882 return;
1883 }
1884
1885 //
1886 // If NET_VECTOR_OWN_FIRST is set, release the first block since it is
1887 // allocated by us
1888 //
1889 if ((Nbuf->Vector->Flag & NET_VECTOR_OWN_FIRST) != 0) {
1890 FreePool (Nbuf->Vector->Block[0].Bulk);
1891 }
1892 FreePool (Nbuf->Vector);
1893 FreePool (Nbuf);
1894 }
1895 }
1896