1 /** @file 2 Routines to process MTFTP4 options. 3 4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php<BR> 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "Mtftp4Impl.h" 16 17 CHAR8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS] = { 18 "blksize", 19 "timeout", 20 "tsize", 21 "multicast" 22 }; 23 24 25 /** 26 Check whether two ascii strings are equel, ignore the case. 27 28 @param Str1 The first ascii string 29 @param Str2 The second ascii string 30 31 @retval TRUE Two strings are equal when case is ignored. 32 @retval FALSE Two string are not equal. 33 34 **/ 35 BOOLEAN 36 NetStringEqualNoCase ( 37 IN UINT8 *Str1, 38 IN UINT8 *Str2 39 ) 40 { 41 UINT8 Ch1; 42 UINT8 Ch2; 43 44 ASSERT ((Str1 != NULL) && (Str2 != NULL)); 45 46 for (; (*Str1 != '\0') && (*Str2 != '\0'); Str1++, Str2++) { 47 Ch1 = *Str1; 48 Ch2 = *Str2; 49 50 // 51 // Convert them to lower case then compare two 52 // 53 if (('A' <= Ch1) && (Ch1 <= 'Z')) { 54 Ch1 += 'a' - 'A'; 55 } 56 57 if (('A' <= Ch2) && (Ch2 <= 'Z')) { 58 Ch2 += 'a' - 'A'; 59 } 60 61 if (Ch1 != Ch2) { 62 return FALSE; 63 } 64 } 65 66 return (BOOLEAN) (*Str1 == *Str2); 67 } 68 69 70 /** 71 Convert a string to a UINT32 number. 72 73 @param Str The string to convert from 74 75 @return The number get from the string 76 77 **/ 78 UINT32 79 NetStringToU32 ( 80 IN UINT8 *Str 81 ) 82 { 83 UINT32 Num; 84 85 ASSERT (Str != NULL); 86 87 Num = 0; 88 89 for (; NET_IS_DIGIT (*Str); Str++) { 90 Num = Num * 10 + (*Str - '0'); 91 } 92 93 return Num; 94 } 95 96 97 /** 98 Convert a string of the format "192.168.0.1" to an IP address. 99 100 @param Str The string representation of IP 101 @param Ip The varible to get IP. 102 103 @retval EFI_INVALID_PARAMETER The IP string is invalid. 104 @retval EFI_SUCCESS The IP is parsed into the Ip 105 106 **/ 107 EFI_STATUS 108 NetStringToIp ( 109 IN UINT8 *Str, 110 OUT IP4_ADDR *Ip 111 ) 112 { 113 UINT32 Byte; 114 UINT32 Addr; 115 UINTN Index; 116 117 *Ip = 0; 118 Addr = 0; 119 120 for (Index = 0; Index < 4; Index++) { 121 if (!NET_IS_DIGIT (*Str)) { 122 return EFI_INVALID_PARAMETER; 123 } 124 125 Byte = NetStringToU32 (Str); 126 127 if (Byte > 255) { 128 return EFI_INVALID_PARAMETER; 129 } 130 131 Addr = (Addr << 8) | Byte; 132 133 // 134 // Skip all the digitals and check whether the sepeator is the dot 135 // 136 while (NET_IS_DIGIT (*Str)) { 137 Str++; 138 } 139 140 if ((Index < 3) && (*Str != '.')) { 141 return EFI_INVALID_PARAMETER; 142 } 143 144 Str++; 145 } 146 147 *Ip = Addr; 148 149 return EFI_SUCCESS; 150 } 151 152 153 /** 154 Go through the packet to fill the Options array with the start 155 addresses of each MTFTP option name/value pair. 156 157 @param Packet The packet to check 158 @param PacketLen The packet's length 159 @param Count The size of the Options on input. The actual 160 options on output 161 @param Options The option array to fill in 162 163 @retval EFI_INVALID_PARAMETER The packet is mal-formated 164 @retval EFI_BUFFER_TOO_SMALL The Options array is too small 165 @retval EFI_SUCCESS The packet has been parsed into the Options array. 166 167 **/ 168 EFI_STATUS 169 Mtftp4FillOptions ( 170 IN EFI_MTFTP4_PACKET *Packet, 171 IN UINT32 PacketLen, 172 IN OUT UINT32 *Count, 173 OUT EFI_MTFTP4_OPTION *Options OPTIONAL 174 ) 175 { 176 UINT8 *Cur; 177 UINT8 *Last; 178 UINT8 Num; 179 UINT8 *Name; 180 UINT8 *Value; 181 182 Num = 0; 183 Cur = (UINT8 *) Packet + MTFTP4_OPCODE_LEN; 184 Last = (UINT8 *) Packet + PacketLen - 1; 185 186 // 187 // process option name and value pairs. The last byte is always zero 188 // 189 while (Cur < Last) { 190 Name = Cur; 191 192 while (*Cur != 0) { 193 Cur++; 194 } 195 196 if (Cur == Last) { 197 return EFI_INVALID_PARAMETER; 198 } 199 200 Value = ++Cur; 201 202 while (*Cur != 0) { 203 Cur++; 204 } 205 206 Num++; 207 208 if ((Options != NULL) && (Num <= *Count)) { 209 Options[Num - 1].OptionStr = Name; 210 Options[Num - 1].ValueStr = Value; 211 } 212 213 Cur++; 214 } 215 216 if ((*Count < Num) || (Options == NULL)) { 217 *Count = Num; 218 return EFI_BUFFER_TOO_SMALL; 219 } 220 221 *Count = Num; 222 return EFI_SUCCESS; 223 } 224 225 226 /** 227 Allocate and fill in a array of Mtftp options from the Packet. 228 229 It first calls Mtftp4FillOption to get the option number, then allocate 230 the array, at last, call Mtftp4FillOption again to save the options. 231 232 @param Packet The packet to parse 233 @param PacketLen The length of the packet 234 @param OptionCount The number of options in the packet 235 @param OptionList The point to get the option array. 236 237 @retval EFI_INVALID_PARAMETER The parametera are invalid or packet isn't a 238 well-formated OACK packet. 239 @retval EFI_SUCCESS The option array is build 240 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array 241 242 **/ 243 EFI_STATUS 244 Mtftp4ExtractOptions ( 245 IN EFI_MTFTP4_PACKET *Packet, 246 IN UINT32 PacketLen, 247 OUT UINT32 *OptionCount, 248 OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL 249 ) 250 { 251 EFI_STATUS Status; 252 253 *OptionCount = 0; 254 255 if (OptionList != NULL) { 256 *OptionList = NULL; 257 } 258 259 if (NTOHS (Packet->OpCode) != EFI_MTFTP4_OPCODE_OACK) { 260 return EFI_INVALID_PARAMETER; 261 } 262 263 if (PacketLen == MTFTP4_OPCODE_LEN) { 264 return EFI_SUCCESS; 265 } 266 267 // 268 // The last byte must be zero to terminate the options 269 // 270 if (*((UINT8 *) Packet + PacketLen - 1) != 0) { 271 return EFI_INVALID_PARAMETER; 272 } 273 274 // 275 // Get the number of options 276 // 277 Status = Mtftp4FillOptions (Packet, PacketLen, OptionCount, NULL); 278 279 if ((Status == EFI_SUCCESS) || (Status != EFI_BUFFER_TOO_SMALL)) { 280 return Status; 281 } 282 283 // 284 // Allocate memory for the options, then call Mtftp4FillOptions to 285 // fill it if caller want that. 286 // 287 if (OptionList == NULL) { 288 return EFI_SUCCESS; 289 } 290 291 *OptionList = AllocatePool (*OptionCount * sizeof (EFI_MTFTP4_OPTION)); 292 293 if (*OptionList == NULL) { 294 return EFI_OUT_OF_RESOURCES; 295 } 296 297 Mtftp4FillOptions (Packet, PacketLen, OptionCount, *OptionList); 298 return EFI_SUCCESS; 299 } 300 301 302 /** 303 Parse the MTFTP multicast option. 304 305 @param Value The Mtftp multicast value string 306 @param Option The option to save the info into. 307 308 @retval EFI_INVALID_PARAMETER The multicast value string is invalid. 309 @retval EFI_SUCCESS The multicast value is parsed into the Option 310 311 **/ 312 EFI_STATUS 313 Mtftp4ExtractMcast ( 314 IN UINT8 *Value, 315 IN OUT MTFTP4_OPTION *Option 316 ) 317 { 318 EFI_STATUS Status; 319 UINT32 Num; 320 321 // 322 // The multicast option is formated like "204.0.0.1,1857,1" 323 // The server can also omit the ip and port, use ",,1" 324 // 325 if (*Value == ',') { 326 Option->McastIp = 0; 327 } else { 328 Status = NetStringToIp (Value, &Option->McastIp); 329 330 if (EFI_ERROR (Status)) { 331 return Status; 332 } 333 334 while ((*Value != 0) && (*Value != ',')) { 335 Value++; 336 } 337 } 338 339 if (*Value != ',') { 340 return EFI_INVALID_PARAMETER; 341 } 342 343 Value++; 344 345 // 346 // Convert the port setting. the server can send us a port number or 347 // empty string. such as the port in ",,1" 348 // 349 if (*Value == ',') { 350 Option->McastPort = 0; 351 } else { 352 Num = NetStringToU32 (Value); 353 354 if (Num > 65535) { 355 return EFI_INVALID_PARAMETER; 356 } 357 358 Option->McastPort = (UINT16) Num; 359 360 while (NET_IS_DIGIT (*Value)) { 361 Value++; 362 } 363 } 364 365 if (*Value != ',') { 366 return EFI_INVALID_PARAMETER; 367 } 368 369 Value++; 370 371 // 372 // Check the master/slave setting, 1 for master, 0 for slave. 373 // 374 Num = NetStringToU32 (Value); 375 376 if ((Num != 0) && (Num != 1)) { 377 return EFI_INVALID_PARAMETER; 378 } 379 380 Option->Master = (BOOLEAN) (Num == 1); 381 382 while (NET_IS_DIGIT (*Value)) { 383 Value++; 384 } 385 386 if (*Value != '\0') { 387 return EFI_INVALID_PARAMETER; 388 } 389 390 return EFI_SUCCESS; 391 } 392 393 394 /** 395 Parse the option in Options array to MTFTP4_OPTION which program 396 can access directly. 397 398 @param Options The option array, which contains addresses of each 399 option's name/value string. 400 @param Count The number of options in the Options 401 @param Request Whether this is a request or OACK. The format of 402 multicast is different according to this setting. 403 @param MtftpOption The MTFTP4_OPTION for easy access. 404 405 @retval EFI_INVALID_PARAMETER The option is mal-formated 406 @retval EFI_UNSUPPORTED Some option isn't supported 407 @retval EFI_SUCCESS The option are OK and has been parsed. 408 409 **/ 410 EFI_STATUS 411 Mtftp4ParseOption ( 412 IN EFI_MTFTP4_OPTION *Options, 413 IN UINT32 Count, 414 IN BOOLEAN Request, 415 OUT MTFTP4_OPTION *MtftpOption 416 ) 417 { 418 EFI_STATUS Status; 419 UINT32 Index; 420 UINT32 Value; 421 EFI_MTFTP4_OPTION *This; 422 423 MtftpOption->Exist = 0; 424 425 for (Index = 0; Index < Count; Index++) { 426 This = Options + Index; 427 428 if ((This->OptionStr == NULL) || (This->ValueStr == NULL)) { 429 return EFI_INVALID_PARAMETER; 430 } 431 432 if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "blksize")) { 433 // 434 // block size option, valid value is between [8, 65464] 435 // 436 Value = NetStringToU32 (This->ValueStr); 437 438 if ((Value < 8) || (Value > 65464)) { 439 return EFI_INVALID_PARAMETER; 440 } 441 442 MtftpOption->BlkSize = (UINT16) Value; 443 MtftpOption->Exist |= MTFTP4_BLKSIZE_EXIST; 444 445 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "timeout")) { 446 // 447 // timeout option, valid value is between [1, 255] 448 // 449 Value = NetStringToU32 (This->ValueStr); 450 451 if ((Value < 1) || (Value > 255)) { 452 return EFI_INVALID_PARAMETER; 453 } 454 455 MtftpOption->Timeout = (UINT8) Value; 456 457 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "tsize")) { 458 // 459 // tsize option, the biggest transfer supported is 4GB with block size option 460 // 461 MtftpOption->Tsize = NetStringToU32 (This->ValueStr); 462 MtftpOption->Exist |= MTFTP4_TSIZE_EXIST; 463 464 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "multicast")) { 465 // 466 // Multicast option, if it is a request, the value must be a zero 467 // length string, otherwise, it is formated like "204.0.0.1,1857,1\0" 468 // 469 if (Request) { 470 if (*(This->ValueStr) != '\0') { 471 return EFI_INVALID_PARAMETER; 472 } 473 474 } else { 475 Status = Mtftp4ExtractMcast (This->ValueStr, MtftpOption); 476 477 if (EFI_ERROR (Status)) { 478 return Status; 479 } 480 } 481 482 MtftpOption->Exist |= MTFTP4_MCAST_EXIST; 483 484 } else if (Request) { 485 // 486 // Ignore the unsupported option if it is a reply, and return 487 // EFI_UNSUPPORTED if it's a request according to the UEFI spec. 488 // 489 return EFI_UNSUPPORTED; 490 } 491 } 492 493 return EFI_SUCCESS; 494 } 495 496 497 /** 498 Parse the options in the OACK packet to MTFTP4_OPTION which program 499 can access directly. 500 501 @param Packet The OACK packet to parse 502 @param PacketLen The length of the packet 503 @param MtftpOption The MTFTP_OPTION for easy access. 504 505 @retval EFI_INVALID_PARAMETER The packet option is mal-formated 506 @retval EFI_UNSUPPORTED Some option isn't supported 507 @retval EFI_SUCCESS The option are OK and has been parsed. 508 509 **/ 510 EFI_STATUS 511 Mtftp4ParseOptionOack ( 512 IN EFI_MTFTP4_PACKET *Packet, 513 IN UINT32 PacketLen, 514 OUT MTFTP4_OPTION *MtftpOption 515 ) 516 { 517 EFI_MTFTP4_OPTION *OptionList; 518 EFI_STATUS Status; 519 UINT32 Count; 520 521 MtftpOption->Exist = 0; 522 523 Status = Mtftp4ExtractOptions (Packet, PacketLen, &Count, &OptionList); 524 525 if (EFI_ERROR (Status) || (Count == 0)) { 526 return Status; 527 } 528 ASSERT (OptionList != NULL); 529 530 Status = Mtftp4ParseOption (OptionList, Count, FALSE, MtftpOption); 531 532 FreePool (OptionList); 533 return Status; 534 } 535