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