netbuffer.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,942 行 · 第 1/3 页
C
1,942 行
UINT32
NetbufCopy (
IN NET_BUF *Nbuf,
IN UINT32 Offset,
IN UINT32 Len,
IN UINT8 *Dest
)
/*++
Routine Description:
Copy the data from the specific offset to the destination.
Arguments:
Nbuf - Pointer to the net buffer.
Offset - The sequence number of the first byte to copy.
Len - Length of the data to copy.
Dest - The destination of the data to copy to.
Returns:
UINTN - The length of the copied data.
--*/
{
NET_BLOCK_OP *BlockOp;
UINT32 Skip;
UINT32 Left;
UINT32 Copied;
UINT32 Index;
UINT32 Cur;
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
ASSERT (Dest);
if ((Len == 0) || (Nbuf->TotalSize <= Offset)) {
return 0;
}
if (Nbuf->TotalSize - Offset < Len) {
Len = Nbuf->TotalSize - Offset;
}
BlockOp = Nbuf->BlockOp;
//
// Skip to the offset. Don't make "Offset-By-One" error here.
// Cur + BLOCK.SIZE is the first sequence number of next block.
// So, (Offset < Cur + BLOCK.SIZE) means that the first byte
// is in the current block. if (Offset == Cur + BLOCK.SIZE), the
// first byte is the next block's first byte.
//
Cur = 0;
for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
if (BlockOp[Index].Size == 0) {
continue;
}
if (Offset < Cur + BlockOp[Index].Size) {
break;
}
Cur += BlockOp[Index].Size;
}
//
// Cur is the sequence number of the first byte in the block
// Offset - Cur is the number of bytes before first byte to
// to copy in the current block.
//
Skip = Offset - Cur;
Left = BlockOp[Index].Size - Skip;
if (Len <= Left) {
NetCopyMem (Dest, BlockOp[Index].Head + Skip, Len);
return Len;
}
NetCopyMem (Dest, BlockOp[Index].Head + Skip, Left);
Dest += Left;
Len -= Left;
Copied = Left;
Index++;
for (; Index < Nbuf->BlockOpNum; Index++) {
if (Len > BlockOp[Index].Size) {
Len -= BlockOp[Index].Size;
Copied += BlockOp[Index].Size;
NetCopyMem (Dest, BlockOp[Index].Head, BlockOp[Index].Size);
Dest += BlockOp[Index].Size;
} else {
Copied += Len;
NetCopyMem (Dest, BlockOp[Index].Head, Len);
break;
}
}
return Copied;
}
VOID
NetbufQueInit (
IN NET_BUF_QUEUE *NbufQue
)
/*++
Routine Description:
Initiate the net buffer queue.
Arguments:
NbufQue - Pointer to the net buffer queue to be initiated.
Returns:
None.
--*/
{
NbufQue->Signature = NET_QUE_SIGNATURE;
NbufQue->RefCnt = 1;
NetListInit (&NbufQue->List);
NetListInit (&NbufQue->BufList);
NbufQue->BufSize = 0;
NbufQue->BufNum = 0;
}
NET_BUF_QUEUE *
NetbufQueAlloc (
VOID
)
/*++
Routine Description:
Allocate an initialized net buffer queue.
Arguments:
None.
Returns:
NET_BUF_QUEUE * - Pointer to the allocated net buffer queue.
--*/
{
NET_BUF_QUEUE *NbufQue;
NbufQue = NetAllocatePool (sizeof (NET_BUF_QUEUE));
if (NbufQue == NULL) {
return NULL;
}
NetbufQueInit (NbufQue);
return NbufQue;
}
VOID
NetbufQueFree (
IN NET_BUF_QUEUE *NbufQue
)
/*++
Routine Description:
Free a net buffer queue.
Arguments:
NbufQue - Poitner to the net buffer queue to be freed.
Returns:
None.
--*/
{
NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
NbufQue->RefCnt--;
if (NbufQue->RefCnt == 0) {
NetbufQueFlush (NbufQue);
NetFreePool (NbufQue);
}
}
VOID
NetbufQueAppend (
IN NET_BUF_QUEUE *NbufQue,
IN NET_BUF *Nbuf
)
/*++
Routine Description:
Append a buffer to the end of the queue.
Arguments:
NbufQue - Pointer to the net buffer queue.
Nbuf - Pointer to the net buffer to be appended.
Returns:
None.
--*/
{
NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
NetListInsertTail (&NbufQue->BufList, &Nbuf->List);
NbufQue->BufSize += Nbuf->TotalSize;
NbufQue->BufNum++;
}
NET_BUF *
NetbufQueRemove (
IN NET_BUF_QUEUE *NbufQue
)
/*++
Routine Description:
Remove a net buffer from head in the specific queue.
Arguments:
NbufQue - Pointer to the net buffer queue.
Returns:
NET_BUF * - Pointer to the net buffer removed from
the specific queue.
--*/
{
NET_BUF *First;
NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
if (NbufQue->BufNum == 0) {
return NULL;
}
First = NET_LIST_USER_STRUCT (NbufQue->BufList.ForwardLink, NET_BUF, List);
NetListRemoveHead (&NbufQue->BufList);
NbufQue->BufSize -= First->TotalSize;
NbufQue->BufNum--;
return First;
}
UINT32
NetbufQueCopy (
IN NET_BUF_QUEUE *NbufQue,
IN UINT32 Offset,
IN UINT32 Len,
IN UINT8 *Dest
)
/*++
Routine Description:
Copy some data from the buffer queue to the destination.
Arguments:
NbufQue - Pointer to the net buffer queue.
Offset - The sequence number of the first byte to copy.
Len - Length of the data to copy.
Dest - The destination of the data to copy to.
Returns:
UINTN - The length of the copied data.
--*/
{
NET_LIST_ENTRY *Entry;
NET_BUF *Nbuf;
UINT32 Skip;
UINT32 Left;
UINT32 Cur;
UINT32 Copied;
NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
ASSERT (Dest != NULL);
if ((Len == 0) || (NbufQue->BufSize <= Offset)) {
return 0;
}
if (NbufQue->BufSize - Offset < Len) {
Len = NbufQue->BufSize - Offset;
}
//
// skip to the Offset
//
Cur = 0;
Nbuf = NULL;
NET_LIST_FOR_EACH (Entry, &NbufQue->BufList) {
Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
if (Offset < Cur + Nbuf->TotalSize) {
break;
}
Cur += Nbuf->TotalSize;
}
//
// Copy the data in the first buffer.
//
Skip = Offset - Cur;
Left = Nbuf->TotalSize - Skip;
if (Len < Left) {
return NetbufCopy (Nbuf, Skip, Len, Dest);
}
NetbufCopy (Nbuf, Skip, Left, Dest);
Dest += Left;
Len -= Left;
Copied = Left;
//
// Iterate over the others
//
Entry = Entry->ForwardLink;
while ((Len > 0) && (Entry != &NbufQue->BufList)) {
Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
if (Len > Nbuf->TotalSize) {
Len -= Nbuf->TotalSize;
Copied += Nbuf->TotalSize;
NetbufCopy (Nbuf, 0, Nbuf->TotalSize, Dest);
Dest += Nbuf->TotalSize;
} else {
NetbufCopy (Nbuf, 0, Len, Dest);
Copied += Len;
break;
}
Entry = Entry->ForwardLink;
}
return Copied;
}
UINT32
NetbufQueTrim (
IN NET_BUF_QUEUE *NbufQue,
IN UINT32 Len
)
/*++
Routine Description:
Trim some data from the queue header, release the buffer if
whole buffer is trimmed.
Arguments:
NbufQue - Pointer to the net buffer queue.
Len - Length of the data to trim.
Returns:
UINTN - The length of the data trimmed.
--*/
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *Next;
NET_BUF *Nbuf;
UINT32 Trimmed;
NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
if (Len == 0) {
return 0;
}
if (Len > NbufQue->BufSize) {
Len = NbufQue->BufSize;
}
NbufQue->BufSize -= Len;
Trimmed = 0;
NET_LIST_FOR_EACH_SAFE (Entry, Next, &NbufQue->BufList) {
Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
if (Len >= Nbuf->TotalSize) {
Trimmed += Nbuf->TotalSize;
Len -= Nbuf->TotalSize;
NetListRemoveEntry (Entry);
NetbufFree (Nbuf);
NbufQue->BufNum--;
if (Len == 0) {
break;
}
} else {
Trimmed += NetbufTrim (Nbuf, Len, NET_BUF_HEAD);
break;
}
}
return Trimmed;
}
VOID
NetbufQueFlush (
IN NET_BUF_QUEUE *NbufQue
)
/*++
Routine Description:
Flush the net buffer queue.
Arguments:
NbufQue - Pointer to the queue to be flushed.
Returns:
None.
--*/
{
NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
NetbufFreeList (&NbufQue->BufList);
NbufQue->BufNum = 0;
NbufQue->BufSize = 0;
}
UINT16
NetblockChecksum (
IN UINT8 *Bulk,
IN UINT32 Len
)
/*++
Routine Description:
Compute checksum for a bulk of data.
Arguments:
Bulk - Pointer to the data.
Len - Length of the data, in bytes.
Returns:
UINT16 - The computed checksum.
--*/
{
register UINT32 Sum;
Sum = 0;
while (Len > 1) {
Sum += *(UINT16 *) Bulk;
Bulk += 2;
Len -= 2;
}
//
// Add left-over byte, if any
//
if (Len > 0) {
Sum += *(UINT8 *) Bulk;
}
//
// Fold 32-bit sum to 16 bits
//
while (Sum >> 16) {
Sum = (Sum & 0xffff) + (Sum >> 16);
}
return (UINT16) Sum;
}
UINT16
NetAddChecksum (
IN UINT16 Checksum1,
IN UINT16 Checksum2
)
/*++
Routine Description:
Add two checksums.
Arguments:
Checksum1 - The first checksum to be added.
Checksum2 - The second checksum to be added.
Returns:
UINT16 - The new checksum.
--*/
{
UINT32 Sum;
Sum = Checksum1 + Checksum2;
//
// two UINT16 can only add up to a carry of 1.
//
if (Sum >> 16) {
Sum = (Sum & 0xffff) + 1;
}
return (UINT16) Sum;
}
UINT16
NetbufChecksum (
IN NET_BUF *Nbuf
)
/*++
Routine Description:
Compute the checksum for a NET_BUF.
Arguments:
Nbuf - Pointer to the net buffer.
Returns:
UINT16 - The computed checksum.
--*/
{
NET_BLOCK_OP *BlockOp;
UINT32 Offset;
UINT16 TotalSum;
UINT16 BlockSum;
UINT32 Index;
NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
TotalSum = 0;
Offset = 0;
BlockOp = Nbuf->BlockOp;
for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
if (BlockOp[Index].Size == 0) {
continue;
}
BlockSum = NetblockChecksum (BlockOp[Index].Head, BlockOp[Index].Size);
if (Offset & 0x01) {
//
// The checksum starts with an odd byte, swap
// the checksum before added to total checksum
//
BlockSum = NET_SWAP_SHORT (BlockSum);
}
TotalSum = NetAddChecksum (BlockSum, TotalSum);
Offset += BlockOp[Index].Size;
}
return TotalSum;
}
UINT16
NetPseudoHeadChecksum (
IN IP4_ADDR Src,
IN IP4_ADDR Dst,
IN UINT8 Proto,
IN UINT16 Len
)
/*++
Routine Description:
Compute the checksum for TCP/UDP pseudo header.
Src, Dst are in network byte order. and Len is
in host byte order.
Arguments:
Src - The source address of the packet.
Dst - The destination address of the packet.
Proto - The protocol type of the packet.
Len - The length of the packet.
Returns:
UINT16 - The computed checksum.
--*/
{
NET_PSEUDO_HDR Hdr;
//
// Zero the memory to relieve align problems
//
NetZeroMem (&Hdr, sizeof (Hdr));
Hdr.SrcIp = Src;
Hdr.DstIp = Dst;
Hdr.Protocol = Proto;
Hdr.Len = HTONS (Len);
return NetblockChecksum ((UINT8 *) &Hdr, sizeof (Hdr));
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?