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