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