mtftp4support.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 667 行 · 第 1/2 页
C
667 行
/*++
Copyright (c) 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:
Mtftp4Support.c
Abstract:
Support routines for Mtftp
--*/
#include "Mtftp4Impl.h"
STATIC
MTFTP4_BLOCK_RANGE *
Mtftp4AllocateRange (
IN UINT16 Start,
IN UINT16 End
)
/*++
Routine Description:
Allocate a MTFTP4 block range, then init it to the
range of [Start, End]
Arguments:
Start - The start block number
End - The last block number in the range
Returns:
NULL if failed to allocate memory, otherwise the created block range.
--*/
{
MTFTP4_BLOCK_RANGE *Range;
Range = NetAllocatePool (sizeof (MTFTP4_BLOCK_RANGE));
if (Range == NULL) {
return NULL;
}
NetListInit (&Range->Link);
Range->Start = Start;
Range->End = End;
return Range;
}
EFI_STATUS
Mtftp4InitBlockRange (
IN NET_LIST_ENTRY *Head,
IN UINT16 Start,
IN UINT16 End
)
/*++
Routine Description:
Initialize the block range for either RRQ or WRQ. RRQ and WRQ have
different requirements for Start and End. For example, during start
up, WRQ initializes its whole valid block range to [0, 0xffff]. This
is bacause the server will send us a ACK0 to inform us to start the
upload. When the client received ACK0, it will remove 0 from the range,
get the next block number, which is 1, then upload the BLOCK1. For RRQ
without option negotiation, the server will directly send us the BLOCK1
in response to the client's RRQ. When received BLOCK1, the client will
remove it from the block range and send an ACK. It also works if there
is option negotiation.
Arguments:
Head - The block range head to initialize
Start - The Start block number.
End - The last block number.
Returns:
EFI_OUT_OF_RESOURCES - Failed to allocate memory for initial block range
EFI_SUCCESS - The initial block range is created.
--*/
{
MTFTP4_BLOCK_RANGE *Range;
Range = Mtftp4AllocateRange (Start, End);
if (Range == NULL) {
return EFI_OUT_OF_RESOURCES;
}
NetListInsertTail (Head, &Range->Link);
return EFI_SUCCESS;
}
INTN
Mtftp4GetNextBlockNum (
IN NET_LIST_ENTRY *Head
)
/*++
Routine Description:
Get the first valid block number on the range list.
Arguments:
Head - The block range head
Returns:
-1: if the block range is empty. Otherwise the first valid block number.
--*/
{
MTFTP4_BLOCK_RANGE *Range;
if (NetListIsEmpty (Head)) {
return -1;
}
Range = NET_LIST_HEAD (Head, MTFTP4_BLOCK_RANGE, Link);
return Range->Start;
}
VOID
Mtftp4SetLastBlockNum (
IN NET_LIST_ENTRY *Head,
IN UINT16 Last
)
/*++
Routine Description:
Set the last block number of the block range list. It will
remove all the blocks after the Last. MTFTP initialize the
block range to the maximum possible range, such as [0, 0xffff]
for WRQ. When it gets the last block number, it will call
this function to set the last block number.
Arguments:
Head - The block range list
Last - The last block number
Returns:
None
--*/
{
MTFTP4_BLOCK_RANGE *Range;
//
// Iterate from the tail to head to remove the block number
// after the last.
//
while (!NetListIsEmpty (Head)) {
Range = NET_LIST_TAIL (Head, MTFTP4_BLOCK_RANGE, Link);
if (Range->Start > Last) {
NetListRemoveEntry (&Range->Link);
NetFreePool (Range);
continue;
}
if (Range->End > Last) {
Range->End = Last;
}
return ;
}
}
EFI_STATUS
Mtftp4RemoveBlockNum (
IN NET_LIST_ENTRY *Head,
IN UINT16 Num
)
/*++
Routine Description:
Remove the block number from the block range list.
Arguments:
Head - The block range list to remove from
Num - The block number to remove
Returns:
EFI_NOT_FOUND - The block number isn't in the block range list
EFI_SUCCESS - The block number has been removed from the list
EFI_OUT_OF_RESOURCES - Failed to allocate resource
--*/
{
MTFTP4_BLOCK_RANGE *Range;
MTFTP4_BLOCK_RANGE *NewRange;
NET_LIST_ENTRY *Entry;
NET_LIST_FOR_EACH (Entry, Head) {
//
// Each block represents a hole [Start, End] in the file,
// skip to the first range with End >= Num
//
Range = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);
if (Range->End < Num) {
continue;
}
//
// There are three different cases for Start
// 1. (Start > Num) && (End >= Num):
// because all the holes before this one has the condition of
// End < Num, so this block number has been removed.
//
// 2. (Start == Num) && (End >= Num):
// Need to increase the Start by one, and if End == Num, this
// hole has been removed completely, remove it.
//
// 3. (Start < Num) && (End >= Num):
// if End == Num, only need to decrease the End by one because
// we have (Start < Num) && (Num == End), so (Start <= End - 1).
// if (End > Num), the hold is splited into two holes, with
// [Start, Num - 1] and [Num + 1, End].
//
if (Range->Start > Num) {
return EFI_NOT_FOUND;
} else if (Range->Start == Num) {
Range->Start++;
if (Range->Start > Range->End) {
NetListRemoveEntry (&Range->Link);
NetFreePool (Range);
}
return EFI_SUCCESS;
} else {
if (Range->End == Num) {
Range->End--;
} else {
NewRange = Mtftp4AllocateRange (Num + 1, (UINT16) Range->End);
if (NewRange == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Range->End = Num - 1;
NetListInsertAfter (&Range->Link, &NewRange->Link);
}
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
Mtftp4SendRequest (
IN MTFTP4_PROTOCOL *Instance
)
/*++
Routine Description:
Build then transmit the request packet for the MTFTP session.
Arguments:
Instance - The Mtftp session
Returns:
EFI_OUT_OF_RESOURCES - Failed to allocate memory for the request
EFI_SUCCESS - The request is built and sent
Others - Failed to transmit the packet.
--*/
{
EFI_MTFTP4_PACKET *Packet;
EFI_MTFTP4_OPTION *Options;
EFI_MTFTP4_TOKEN *Token;
NET_BUF *Nbuf;
UINT8 *Mode;
UINT8 *Cur;
UINT32 Len;
UINTN Index;
Token = Instance->Token;
Options = Token->OptionList;
Mode = Instance->Token->ModeStr;
if (Mode == NULL) {
Mode = "octet";
}
//
// Compute the packet length
//
Len = (UINT32) (EfiAsciiStrLen (Token->Filename) + EfiAsciiStrLen (Mode) + 4);
for (Index = 0; Index < Token->OptionCount; Index++) {
Len += (UINT32) (EfiAsciiStrLen (Options[Index].OptionStr) +
EfiAsciiStrLen (Options[Index].ValueStr) + 2);
}
//
// Allocate a packet then copy the data over
//
if ((Nbuf = NetbufAlloc (Len)) == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Packet = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (Nbuf, Len, FALSE);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?