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