netbuffer.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,942 行 · 第 1/3 页
C
1,942 行
/*++
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
NetBuffer.c
Abstract:
--*/
#include "NetBuffer.h"
STATIC
NET_BUF *
NetbufAllocStruct (
IN UINT32 BlockNum,
IN UINT32 BlockOpNum
)
/*++
Routine Description:
Allocate and build up the sketch for a NET_BUF. The net buffer allocated
has the BlockOpNum's NET_BLOCK_OP, and its associated NET_VECTOR has the
BlockNum's NET_BLOCK.
Arguments:
BlockNum - The number of NET_BLOCK in the Vector of net buffer
BlockOpNum - The number of NET_BLOCK_OP in the net buffer
Returns:
NET_BUF * - Pointer to the allocated NET_BUF. If NULL
the allocation failed due to resource limit.
--*/
{
NET_BUF *Nbuf;
NET_VECTOR *Vector;
ASSERT (BlockOpNum >= 1);
//
// Allocate three memory blocks.
//
Nbuf = NetAllocateZeroPool (NET_BUF_SIZE (BlockOpNum));
if (Nbuf == NULL) {
return NULL;
}
Nbuf->Signature = NET_BUF_SIGNATURE;
Nbuf->RefCnt = 1;
Nbuf->BlockOpNum = BlockOpNum;
NetListInit (&Nbuf->List);
if (BlockNum != 0) {
Vector = NetAllocateZeroPool (NET_VECTOR_SIZE (BlockNum));
if (Vector == NULL) {
goto FreeNbuf;
}
Vector->Signature = NET_VECTOR_SIGNATURE;
Vector->RefCnt = 1;
Vector->BlockNum = BlockNum;
Nbuf->Vector = Vector;
}
return Nbuf;
FreeNbuf:
NetFreePool (Nbuf);
return NULL;
}
NET_BUF *
NetbufAlloc (
IN UINT32 Len
)
/*++
Routine Description:
Allocate a single block NET_BUF. Upon allocation, all the
free space is in the tail room.
Arguments:
Len - The length of the block.
Returns:
NET_BUF * - Pointer to the allocated NET_BUF. If NULL
the allocation failed due to resource limit.
--*/
{
NET_BUF *Nbuf;
NET_VECTOR *Vector;
UINT8 *Bulk;
ASSERT (Len > 0);
Nbuf = NetbufAllocStruct (1, 1);
if (Nbuf == NULL) {
return NULL;
}
Bulk = NetAllocatePool (Len);
if (Bulk == NULL) {
goto FreeNBuf;
}
Vector = Nbuf->Vector;
Vector->Len = Len;
Vector->Block[0].Bulk = Bulk;
Vector->Block[0].Len = Len;
Nbuf->BlockOp[0].BlockHead = Bulk;
Nbuf->BlockOp[0].BlockTail = Bulk + Len;
Nbuf->BlockOp[0].Head = Bulk;
Nbuf->BlockOp[0].Tail = Bulk;
Nbuf->BlockOp[0].Size = 0;
return Nbuf;
FreeNBuf:
NetFreePool (Nbuf);
return NULL;
}
STATIC
VOID
NetbufFreeVector (
IN NET_VECTOR *Vector
)
/*++
Routine Description:
Free the vector
Arguments:
Vector - Pointer to the NET_VECTOR to be freed.
Returns:
None.
--*/
{
UINT32 Index;
NET_CHECK_SIGNATURE (Vector, NET_VECTOR_SIGNATURE);
ASSERT (Vector->RefCnt > 0);
Vector->RefCnt--;
if (Vector->RefCnt > 0) {
return;
}
if (Vector->Free != NULL) {
//
// Call external free function to free the vector if it
// isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
// first block since it is allocated by us
//
if (Vector->Flag & NET_VECTOR_OWN_FIRST) {
NetFreePool (Vector->Block[0].Bulk);
}
Vector->Free (Vector->Arg);
} else {
//
// Free each memory block associated with the Vector
//
for (Index = 0; Index < Vector->BlockNum; Index++) {
NetFreePool (Vector->Block[Index].Bulk);
}
}
NetFreePool (Vector);
}
VOID
NetbufFree (
IN NET_BUF *Nbuf
)
/*++
Routine Description:
Free the buffer and its associated NET_VECTOR.
Arguments:
Nbuf - Pointer to the NET_BUF to be freed.
Returns:
None.
--*/
{
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
ASSERT (Nbuf->RefCnt > 0);
Nbuf->RefCnt--;
if (Nbuf->RefCnt == 0) {
//
// Update Vector only when NBuf is to be released. That is,
// all the sharing of Nbuf increse Vector's RefCnt by one
//
NetbufFreeVector (Nbuf->Vector);
NetFreePool (Nbuf);
}
}
NET_BUF *
NetbufClone (
IN NET_BUF *Nbuf
)
/*++
Routine Description:
Create a copy of NET_BUF that share the associated NET_DATA.
Arguments:
Nbuf - Pointer to the net buffer to be cloned.
Returns:
NET_BUF * - Pointer to the cloned net buffer.
--*/
{
NET_BUF *Clone;
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
Clone = NetAllocatePool (NET_BUF_SIZE (Nbuf->BlockOpNum));
if (Clone == NULL) {
return NULL;
}
Clone->Signature = NET_BUF_SIGNATURE;
Clone->RefCnt = 1;
NetListInit (&Clone->List);
Clone->Ip = Nbuf->Ip;
Clone->Tcp = Nbuf->Tcp;
NetCopyMem (Clone->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);
NET_GET_REF (Nbuf->Vector);
Clone->Vector = Nbuf->Vector;
Clone->BlockOpNum = Nbuf->BlockOpNum;
Clone->TotalSize = Nbuf->TotalSize;
NetCopyMem (Clone->BlockOp, Nbuf->BlockOp, sizeof (NET_BLOCK_OP) * Nbuf->BlockOpNum);
return Clone;
}
NET_BUF *
NetbufDuplicate (
IN NET_BUF *Nbuf,
IN NET_BUF *Duplicate OPTIONAL,
IN UINT32 HeadSpace
)
/*++
Routine Description:
Create a duplicated copy of Nbuf, data is copied. Also leave some
head space before the data.
Arguments:
Nbuf - Pointer to the net buffer to be cloned.
Duplicate - Pointer to the net buffer to duplicate to, if NULL a new net
buffer is allocated.
HeadSpace - Length of the head space to reserve
Returns:
NET_BUF * - Pointer to the duplicated net buffer.
--*/
{
UINT8 *Dst;
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
if (Duplicate == NULL) {
Duplicate = NetbufAlloc (Nbuf->TotalSize + HeadSpace);
}
if (Duplicate == NULL) {
return NULL;
}
//
// Don't set the IP and TCP head point, since it is most
// like that they are pointing to the memory of Nbuf.
//
NetCopyMem (Duplicate->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);
NetbufReserve (Duplicate, HeadSpace);
Dst = NetbufAllocSpace (Duplicate, Nbuf->TotalSize, NET_BUF_TAIL);
NetbufCopy (Nbuf, 0, Nbuf->TotalSize, Dst);
return Duplicate;
}
VOID
NetbufFreeList (
IN NET_LIST_ENTRY *Head
)
/*++
Routine Description:
Free a list of net buffers.
Arguments:
Head - Pointer to the head of linked net buffers.
Returns:
None.
--*/
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *Next;
NET_BUF *Nbuf;
Entry = Head->ForwardLink;
NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
NetListRemoveEntry (Entry);
NetbufFree (Nbuf);
}
ASSERT (NetListIsEmpty (Head));
}
UINT8 *
NetbufGetByte (
IN NET_BUF *Nbuf,
IN UINT32 Offset,
OUT UINT32 *Index OPTIONAL
)
/*++
Routine Description:
Get the position of some byte in the net buffer. This can be used
to, for example, retrieve the IP header in the packet. It also
returns the fragment that contains the byte which is used mainly by
the buffer implementation itself.
Arguments:
Nbuf - Pointer to the net buffer.
Offset - The index or offset of the byte
Index - Index of the fragment that contains the block
Returns:
UINT8 * - Pointer to the nth byte of data in the net buffer.
If NULL, there is no such data in the net buffer.
--*/
{
NET_BLOCK_OP *BlockOp;
UINT32 Loop;
UINT32 Len;
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
if (Offset >= Nbuf->TotalSize) {
return NULL;
}
BlockOp = Nbuf->BlockOp;
Len = 0;
for (Loop = 0; Loop < Nbuf->BlockOpNum; Loop++) {
if (Len + BlockOp[Loop].Size <= Offset) {
Len += BlockOp[Loop].Size;
continue;
}
if (Index != NULL) {
*Index = Loop;
}
return BlockOp[Loop].Head + (Offset - Len);
}
return NULL;
}
STATIC
VOID
NetbufSetBlock (
IN NET_BUF *Nbuf,
IN UINT8 *Bulk,
IN UINT32 Len,
IN UINT32 Index
)
/*++
Routine Description:
Set the NET_BLOCK and corresponding NET_BLOCK_OP in
the buffer. All the pointers in NET_BLOCK and NET_BLOCK_OP
are set to the bulk's head and tail respectively. So, this
function alone can't be used by NetbufAlloc.
Arguments:
Nbuf - Pointer to the net buffer.
Bulk - Pointer to the data.
Len - Length of the bulk data.
Index - The data block index in the net buffer the bulk data
should belong to.
Returns:
None.
--*/
{
NET_BLOCK_OP *BlockOp;
NET_BLOCK *Block;
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
ASSERT (Index < Nbuf->BlockOpNum);
Block = &(Nbuf->Vector->Block[Index]);
BlockOp = &(Nbuf->BlockOp[Index]);
Block->Len = Len;
Block->Bulk = Bulk;
BlockOp->BlockHead = Bulk;
BlockOp->BlockTail = Bulk + Len;
BlockOp->Head = Bulk;
BlockOp->Tail = Bulk + Len;
BlockOp->Size = Len;
}
STATIC
VOID
NetbufSetBlockOp (
IN NET_BUF *Nbuf,
IN UINT8 *Bulk,
IN UINT32 Len,
IN UINT32 Index
)
/*++
Routine Description:
Set the NET_BLOCK_OP in the buffer. The corresponding NET_BLOCK
structure is left untouched. Some times, there is no 1:1 relationship
between NET_BLOCK and NET_BLOCK_OP. For example, that in NetbufGetFragment.
Arguments:
Nbuf - Pointer to the net buffer.
Bulk - Pointer to the data.
Len - Length of the bulk data.
Index - The data block index in the net buffer the bulk data
should belong to.
Returns:
None.
--*/
{
NET_BLOCK_OP *BlockOp;
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
ASSERT (Index < Nbuf->BlockOpNum);
BlockOp = &(Nbuf->BlockOp[Index]);
BlockOp->BlockHead = Bulk;
BlockOp->BlockTail = Bulk + Len;
BlockOp->Head = Bulk;
BlockOp->Tail = Bulk + Len;
BlockOp->Size = Len;
}
STATIC
VOID
NetbufGetFragmentFree (
IN VOID *Arg
)
/*++
Routine Description:
Helper function for NetbufClone. It is necessary because NetbufGetFragment
may allocate the first block to accomodate the HeadSpace and HeadLen. So, it
need to create a new NET_VECTOR. But, we want to avoid data copy by sharing
the old NET_VECTOR.
Arguments:
Arg - Point to the old NET_VECTOR
Returns:
NONE
--*/
{
NET_VECTOR *Vector;
Vector = (NET_VECTOR *)Arg;
NetbufFreeVector (Vector);
}
NET_BUF *
NetbufGetFragment (
IN NET_BUF *Nbuf,
IN UINT32 Offset,
IN UINT32 Len,
IN UINT32 HeadSpace
)
/*++
Routine Description:
Create a NET_BUF structure which contains Len byte data of
Nbuf starting from Offset. A new NET_BUF structure will be
created but the associated data in NET_VECTOR is shared.
This function exists to do IP packet fragmentation.
Arguments:
Nbuf - Pointer to the net buffer to be cloned.
Offset - Starting point of the data to be included in new buffer.
Len - How many data to include in new data
HeadSpace - How many bytes of head space to reserve for protocol header
Returns:
NET_BUF * - Pointer to the cloned net buffer.
--*/
{
NET_BUF *Child;
NET_VECTOR *Vector;
NET_BLOCK_OP *BlockOp;
UINT32 CurBlockOp;
UINT32 BlockOpNum;
UINT8 *FirstBulk;
UINT32 Index;
UINT32 First;
UINT32 Last;
UINT32 FirstSkip;
UINT32 FirstLen;
UINT32 LastLen;
UINT32 Cur;
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
if ((Len == 0) || (Offset + Len > Nbuf->TotalSize)) {
return NULL;
}
//
// First find the first and last BlockOp that contains
// the valid data, and compute the offset of the first
// BlockOp and length of the last BlockOp
//
BlockOp = Nbuf->BlockOp;
Cur = 0;
for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
if (Offset < Cur + BlockOp[Index].Size) {
break;
}
Cur += BlockOp[Index].Size;
}
//
// First is the index of the first BlockOp, FirstSkip is
// the offset of the first byte in the first BlockOp.
//
First = Index;
FirstSkip = Offset - Cur;
FirstLen = BlockOp[Index].Size - FirstSkip;
//
//redundant assignment to make compiler happy.
//
Last = 0;
LastLen = 0;
if (Len > FirstLen) {
Cur += BlockOp[Index].Size;
Index++;
for (; Index < Nbuf->BlockOpNum; Index++) {
if (Offset + Len <= Cur + BlockOp[Index].Size) {
Last = Index;
LastLen = Offset + Len - Cur;
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?