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