From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../Firmware/NetworkPkg/Mtftp4Dxe/Mtftp4Option.c | 549 +++++++++++++++++++++ 1 file changed, 549 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/NetworkPkg/Mtftp4Dxe/Mtftp4Option.c (limited to 'src/VBox/Devices/EFI/Firmware/NetworkPkg/Mtftp4Dxe/Mtftp4Option.c') diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Mtftp4Dxe/Mtftp4Option.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Mtftp4Dxe/Mtftp4Option.c new file mode 100644 index 00000000..04e4f393 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Mtftp4Dxe/Mtftp4Option.c @@ -0,0 +1,549 @@ +/** @file + Routines to process MTFTP4 options. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Mtftp4Impl.h" + +CHAR8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS] = { + "blksize", + "windowsize", + "timeout", + "tsize", + "multicast" +}; + + +/** + Check whether two ascii strings are equal, 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 strings 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 variable to get IP. + + @retval EFI_INVALID_PARAMETER The IP string is invalid. + @retval EFI_SUCCESS The IP is parsed into the Ip + +**/ +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 separator is the dot + // + while (NET_IS_DIGIT (*Str)) { + Str++; + } + + if ((Index < 3) && (*Str != '.')) { + return EFI_INVALID_PARAMETER; + } + + Str++; + } + + *Ip = Addr; + + return EFI_SUCCESS; +} + + +/** + 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 malformatted + @retval EFI_BUFFER_TOO_SMALL The Options array is too small + @retval EFI_SUCCESS The packet has been parsed into the Options array. + +**/ +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-formatted 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, + 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 = AllocatePool (*OptionCount * sizeof (EFI_MTFTP4_OPTION)); + + if (*OptionList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Mtftp4FillOptions (Packet, PacketLen, OptionCount, *OptionList); + 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 + +**/ +EFI_STATUS +Mtftp4ExtractMcast ( + IN UINT8 *Value, + IN OUT MTFTP4_OPTION *Option + ) +{ + EFI_STATUS Status; + UINT32 Num; + + // + // The multicast option is formatted 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 != 0) && (*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 Operation The current performed operation. + @param MtftpOption The MTFTP4_OPTION for easy access. + + @retval EFI_INVALID_PARAMETER The option is malformatted + @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, + IN UINT16 Operation, + 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, (UINT8 *) "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, (UINT8 *) "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, (UINT8 *) "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, (UINT8 *) "multicast")) { + // + // Multicast option, if it is a request, the value must be a zero + // length string, otherwise, it is formatted 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 (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "windowsize")) { + if (Operation == EFI_MTFTP4_OPCODE_WRQ) { + // + // Currently, windowsize is not supported in the write operation. + // + return EFI_UNSUPPORTED; + } + + Value = NetStringToU32 (This->ValueStr); + + if (Value < 1) { + return EFI_INVALID_PARAMETER; + } + + MtftpOption->WindowSize = (UINT16) Value; + MtftpOption->Exist |= MTFTP4_WINDOWSIZE_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 Operation The current performed operation. + @param MtftpOption The MTFTP_OPTION for easy access. + + @retval EFI_INVALID_PARAMETER The packet option is malformatted + @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, + IN UINT16 Operation, + 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; + } + ASSERT (OptionList != NULL); + + Status = Mtftp4ParseOption (OptionList, Count, FALSE, Operation, MtftpOption); + + FreePool (OptionList); + return Status; +} -- cgit v1.2.3