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