Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3492 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
542
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c
Normal file
542
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c
Normal file
@@ -0,0 +1,542 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Mtftp4Option.c
|
||||
|
||||
Abstract:
|
||||
routines to process MTFTP4 options
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp4Impl.h"
|
||||
|
||||
UINT8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS] = {
|
||||
"blksize",
|
||||
"timeout",
|
||||
"tsize",
|
||||
"multicast"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Go through the packet to fill the Options array with the start
|
||||
addresses of each MTFTP option name/value pair.
|
||||
|
||||
@param Packet The packet to check
|
||||
@param PacketLen The packet's length
|
||||
@param Count The size of the Options on input. The actual
|
||||
options on output
|
||||
@param Options The option array to fill in
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is mal-formated
|
||||
@retval EFI_BUFFER_TOO_SMALL The Options array is too small
|
||||
@retval EFI_SUCCESS The packet has been parsed into the Options array.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4FillOptions (
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *Count,
|
||||
OUT EFI_MTFTP4_OPTION *Options OPTIONAL
|
||||
)
|
||||
{
|
||||
UINT8 *Cur;
|
||||
UINT8 *Last;
|
||||
UINT8 Num;
|
||||
UINT8 *Name;
|
||||
UINT8 *Value;
|
||||
|
||||
Num = 0;
|
||||
Cur = (UINT8 *) Packet + MTFTP4_OPCODE_LEN;
|
||||
Last = (UINT8 *) Packet + PacketLen - 1;
|
||||
|
||||
//
|
||||
// process option name and value pairs. The last byte is always zero
|
||||
//
|
||||
while (Cur < Last) {
|
||||
Name = Cur;
|
||||
|
||||
while (*Cur != 0) {
|
||||
Cur++;
|
||||
}
|
||||
|
||||
if (Cur == Last) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Value = ++Cur;
|
||||
|
||||
while (*Cur != 0) {
|
||||
Cur++;
|
||||
}
|
||||
|
||||
Num++;
|
||||
|
||||
if ((Options != NULL) && (Num <= *Count)) {
|
||||
Options[Num - 1].OptionStr = Name;
|
||||
Options[Num - 1].ValueStr = Value;
|
||||
}
|
||||
|
||||
Cur++;
|
||||
}
|
||||
|
||||
if ((*Count < Num) || (Options == NULL)) {
|
||||
*Count = Num;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*Count = Num;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allocate and fill in a array of Mtftp options from the Packet. It
|
||||
first calls Mtftp4FillOption to get the option number, then allocate
|
||||
the array, at last, call Mtftp4FillOption again to save the options.
|
||||
|
||||
@param Packet The packet to parse
|
||||
@param PacketLen The length of the packet
|
||||
@param OptionCount The number of options in the packet
|
||||
@param OptionList The point to get the option array.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parametera are invalid or packet isn't a
|
||||
well-formated OACK packet.
|
||||
@retval EFI_SUCCESS The option array is build
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ExtractOptions (
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *OptionCount,
|
||||
OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
*OptionCount = 0;
|
||||
|
||||
if (OptionList != NULL) {
|
||||
*OptionList = NULL;
|
||||
}
|
||||
|
||||
if (NTOHS (Packet->OpCode) != EFI_MTFTP4_OPCODE_OACK) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (PacketLen == MTFTP4_OPCODE_LEN) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// The last byte must be zero to terminate the options
|
||||
//
|
||||
if (*((UINT8 *) Packet + PacketLen - 1) != 0) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the number of options
|
||||
//
|
||||
Status = Mtftp4FillOptions (Packet, PacketLen, OptionCount, NULL);
|
||||
|
||||
if ((Status == EFI_SUCCESS) || (Status != EFI_BUFFER_TOO_SMALL)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate memory for the options, then call Mtftp4FillOptions to
|
||||
// fill it if caller want that.
|
||||
//
|
||||
if (OptionList == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
*OptionList = NetAllocatePool (*OptionCount * sizeof (EFI_MTFTP4_OPTION));
|
||||
|
||||
if (*OptionList == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Mtftp4FillOptions (Packet, PacketLen, OptionCount, *OptionList);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check whether two ascii strings are equel, ignore the case.
|
||||
|
||||
@param Str1 The first ascii string
|
||||
@param Str2 The second ascii string
|
||||
|
||||
@retval TRUE Two strings are equal when case is ignored.
|
||||
@retval FALSE Two string are not equal.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
NetStringEqualNoCase (
|
||||
IN UINT8 *Str1,
|
||||
IN UINT8 *Str2
|
||||
)
|
||||
{
|
||||
UINT8 Ch1;
|
||||
UINT8 Ch2;
|
||||
|
||||
ASSERT ((Str1 != NULL) && (Str2 != NULL));
|
||||
|
||||
for (; (*Str1 != '\0') && (*Str2 != '\0'); Str1++, Str2++) {
|
||||
Ch1 = *Str1;
|
||||
Ch2 = *Str2;
|
||||
|
||||
//
|
||||
// Convert them to lower case then compare two
|
||||
//
|
||||
if (('A' <= Ch1) && (Ch1 <= 'Z')) {
|
||||
Ch1 += 'a' - 'A';
|
||||
}
|
||||
|
||||
if (('A' <= Ch2) && (Ch2 <= 'Z')) {
|
||||
Ch2 += 'a' - 'A';
|
||||
}
|
||||
|
||||
if (Ch1 != Ch2) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return (BOOLEAN) (*Str1 == *Str2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert a string to a UINT32 number.
|
||||
|
||||
@param Str The string to convert from
|
||||
|
||||
@return The number get from the string
|
||||
|
||||
**/
|
||||
UINT32
|
||||
NetStringToU32 (
|
||||
IN UINT8 *Str
|
||||
)
|
||||
{
|
||||
UINT32 Num;
|
||||
|
||||
ASSERT (Str != NULL);
|
||||
|
||||
Num = 0;
|
||||
|
||||
for (; NET_IS_DIGIT (*Str); Str++) {
|
||||
Num = Num * 10 + (*Str - '0');
|
||||
}
|
||||
|
||||
return Num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert a string of the format "192.168.0.1" to an IP address.
|
||||
|
||||
@param Str The string representation of IP
|
||||
@param Ip The varible to get IP.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The IP string is invalid.
|
||||
@retval EFI_SUCCESS The IP is parsed into the Ip
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
NetStringToIp (
|
||||
IN UINT8 *Str,
|
||||
OUT IP4_ADDR *Ip
|
||||
)
|
||||
{
|
||||
UINT32 Byte;
|
||||
UINT32 Addr;
|
||||
UINTN Index;
|
||||
|
||||
*Ip = 0;
|
||||
Addr = 0;
|
||||
|
||||
for (Index = 0; Index < 4; Index++) {
|
||||
if (!NET_IS_DIGIT (*Str)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Byte = NetStringToU32 (Str);
|
||||
|
||||
if (Byte > 255) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Addr = (Addr << 8) | Byte;
|
||||
|
||||
//
|
||||
// Skip all the digitals and check whether the sepeator is the dot
|
||||
//
|
||||
while (NET_IS_DIGIT (*Str)) {
|
||||
Str++;
|
||||
}
|
||||
|
||||
if ((Index < 3) && (*Str != '.')) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Str++;
|
||||
}
|
||||
|
||||
*Ip = Addr;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the MTFTP multicast option.
|
||||
|
||||
@param Value The Mtftp multicast value string
|
||||
@param Option The option to save the info into.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The multicast value string is invalid.
|
||||
@retval EFI_SUCCESS The multicast value is parsed into the Option
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4ExtractMcast (
|
||||
IN UINT8 *Value,
|
||||
IN MTFTP4_OPTION *Option
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Num;
|
||||
|
||||
//
|
||||
// The multicast option is formated like "204.0.0.1,1857,1"
|
||||
// The server can also omit the ip and port, use ",,1"
|
||||
//
|
||||
if (*Value == ',') {
|
||||
Option->McastIp = 0;
|
||||
} else {
|
||||
Status = NetStringToIp (Value, &Option->McastIp);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
while (*Value && (*Value != ',')) {
|
||||
Value++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*Value != ',') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Value++;
|
||||
|
||||
//
|
||||
// Convert the port setting. the server can send us a port number or
|
||||
// empty string. such as the port in ",,1"
|
||||
//
|
||||
if (*Value == ',') {
|
||||
Option->McastPort = 0;
|
||||
} else {
|
||||
Num = NetStringToU32 (Value);
|
||||
|
||||
if (Num > 65535) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Option->McastPort = (UINT16)Num;
|
||||
|
||||
while (NET_IS_DIGIT (*Value)) {
|
||||
Value++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*Value != ',') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Value++;
|
||||
|
||||
//
|
||||
// Check the master/slave setting, 1 for master, 0 for slave.
|
||||
//
|
||||
Num = NetStringToU32 (Value);
|
||||
|
||||
if ((Num != 0) && (Num != 1)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Option->Master = (BOOLEAN)(Num == 1);
|
||||
|
||||
while (NET_IS_DIGIT (*Value)) {
|
||||
Value++;
|
||||
}
|
||||
|
||||
if (*Value != '\0') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the option in Options array to MTFTP4_OPTION which program
|
||||
can access directly.
|
||||
|
||||
@param Options The option array, which contains addresses of each
|
||||
option's name/value string.
|
||||
@param Count The number of options in the Options
|
||||
@param Request Whether this is a request or OACK. The format of
|
||||
multicast is different according to this setting.
|
||||
@param MtftpOption The MTFTP4_OPTION for easy access.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The option is mal-formated
|
||||
@retval EFI_UNSUPPORTED Some option isn't supported
|
||||
@retval EFI_SUCCESS The option are OK and has been parsed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ParseOption (
|
||||
IN EFI_MTFTP4_OPTION *Options,
|
||||
IN UINT32 Count,
|
||||
IN BOOLEAN Request,
|
||||
OUT MTFTP4_OPTION *MtftpOption
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Index;
|
||||
UINT32 Value;
|
||||
EFI_MTFTP4_OPTION *This;
|
||||
|
||||
MtftpOption->Exist = 0;
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
This = Options + Index;
|
||||
|
||||
if ((This->OptionStr == NULL) || (This->ValueStr == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (NetStringEqualNoCase (This->OptionStr, "blksize")) {
|
||||
//
|
||||
// block size option, valid value is between [8, 65464]
|
||||
//
|
||||
Value = NetStringToU32 (This->ValueStr);
|
||||
|
||||
if ((Value < 8) || (Value > 65464)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MtftpOption->BlkSize = (UINT16) Value;
|
||||
MtftpOption->Exist |= MTFTP4_BLKSIZE_EXIST;
|
||||
|
||||
} else if (NetStringEqualNoCase (This->OptionStr, "timeout")) {
|
||||
//
|
||||
// timeout option, valid value is between [1, 255]
|
||||
//
|
||||
Value = NetStringToU32 (This->ValueStr);
|
||||
|
||||
if ((Value < 1) || (Value > 255)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MtftpOption->Timeout = (UINT8) Value;
|
||||
|
||||
} else if (NetStringEqualNoCase (This->OptionStr, "tsize")) {
|
||||
//
|
||||
// tsize option, the biggest transfer supported is 4GB with block size option
|
||||
//
|
||||
MtftpOption->Tsize = NetStringToU32 (This->ValueStr);
|
||||
MtftpOption->Exist |= MTFTP4_TSIZE_EXIST;
|
||||
|
||||
} else if (NetStringEqualNoCase (This->OptionStr, "multicast")) {
|
||||
//
|
||||
// Multicast option, if it is a request, the value must be a zero
|
||||
// length string, otherwise, it is formated like "204.0.0.1,1857,1\0"
|
||||
//
|
||||
if (Request) {
|
||||
if (*(This->ValueStr) != '\0') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
} else {
|
||||
Status = Mtftp4ExtractMcast (This->ValueStr, MtftpOption);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
MtftpOption->Exist |= MTFTP4_MCAST_EXIST;
|
||||
|
||||
} else if (Request) {
|
||||
//
|
||||
// Ignore the unsupported option if it is a reply, and return
|
||||
// EFI_UNSUPPORTED if it's a request according to the UEFI spec.
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the options in the OACK packet to MTFTP4_OPTION which program
|
||||
can access directly.
|
||||
|
||||
@param Packet The OACK packet to parse
|
||||
@param PacketLen The length of the packet
|
||||
@param MtftpOption The MTFTP_OPTION for easy access.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet option is mal-formated
|
||||
@retval EFI_UNSUPPORTED Some option isn't supported
|
||||
@retval EFI_SUCCESS The option are OK and has been parsed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ParseOptionOack (
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
OUT MTFTP4_OPTION *MtftpOption
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_OPTION *OptionList;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Count;
|
||||
|
||||
MtftpOption->Exist = 0;
|
||||
|
||||
Status = Mtftp4ExtractOptions (Packet, PacketLen, &Count, &OptionList);
|
||||
|
||||
if (EFI_ERROR (Status) || (Count == 0)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Mtftp4ParseOption (OptionList, Count, FALSE, MtftpOption);
|
||||
|
||||
NetFreePool (OptionList);
|
||||
return Status;
|
||||
}
|
Reference in New Issue
Block a user