]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c
Insert comments for functions/macros and add the file headers.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Option.c
1 /** @file
2 Routines to process MTFTP4 options.
3
4 Copyright (c) 2006 - 2007, Intel Corporation<BR>
5 All rights reserved. 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 Go through the packet to fill the Options array with the start
27 addresses of each MTFTP option name/value pair.
28
29 @param Packet The packet to check
30 @param PacketLen The packet's length
31 @param Count The size of the Options on input. The actual
32 options on output
33 @param Options The option array to fill in
34
35 @retval EFI_INVALID_PARAMETER The packet is mal-formated
36 @retval EFI_BUFFER_TOO_SMALL The Options array is too small
37 @retval EFI_SUCCESS The packet has been parsed into the Options array.
38
39 **/
40 EFI_STATUS
41 Mtftp4FillOptions (
42 IN EFI_MTFTP4_PACKET *Packet,
43 IN UINT32 PacketLen,
44 IN OUT UINT32 *Count,
45 OUT EFI_MTFTP4_OPTION *Options OPTIONAL
46 )
47 {
48 UINT8 *Cur;
49 UINT8 *Last;
50 UINT8 Num;
51 UINT8 *Name;
52 UINT8 *Value;
53
54 Num = 0;
55 Cur = (UINT8 *) Packet + MTFTP4_OPCODE_LEN;
56 Last = (UINT8 *) Packet + PacketLen - 1;
57
58 //
59 // process option name and value pairs. The last byte is always zero
60 //
61 while (Cur < Last) {
62 Name = Cur;
63
64 while (*Cur != 0) {
65 Cur++;
66 }
67
68 if (Cur == Last) {
69 return EFI_INVALID_PARAMETER;
70 }
71
72 Value = ++Cur;
73
74 while (*Cur != 0) {
75 Cur++;
76 }
77
78 Num++;
79
80 if ((Options != NULL) && (Num <= *Count)) {
81 Options[Num - 1].OptionStr = Name;
82 Options[Num - 1].ValueStr = Value;
83 }
84
85 Cur++;
86 }
87
88 if ((*Count < Num) || (Options == NULL)) {
89 *Count = Num;
90 return EFI_BUFFER_TOO_SMALL;
91 }
92
93 *Count = Num;
94 return EFI_SUCCESS;
95 }
96
97
98 /**
99 Allocate and fill in a array of Mtftp options from the Packet.
100
101 It first calls Mtftp4FillOption to get the option number, then allocate
102 the array, at last, call Mtftp4FillOption again to save the options.
103
104 @param Packet The packet to parse
105 @param PacketLen The length of the packet
106 @param OptionCount The number of options in the packet
107 @param OptionList The point to get the option array.
108
109 @retval EFI_INVALID_PARAMETER The parametera are invalid or packet isn't a
110 well-formated OACK packet.
111 @retval EFI_SUCCESS The option array is build
112 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array
113
114 **/
115 EFI_STATUS
116 Mtftp4ExtractOptions (
117 IN EFI_MTFTP4_PACKET *Packet,
118 IN UINT32 PacketLen,
119 OUT UINT32 *OptionCount,
120 OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL
121 )
122 {
123 EFI_STATUS Status;
124
125 *OptionCount = 0;
126
127 if (OptionList != NULL) {
128 *OptionList = NULL;
129 }
130
131 if (NTOHS (Packet->OpCode) != EFI_MTFTP4_OPCODE_OACK) {
132 return EFI_INVALID_PARAMETER;
133 }
134
135 if (PacketLen == MTFTP4_OPCODE_LEN) {
136 return EFI_SUCCESS;
137 }
138
139 //
140 // The last byte must be zero to terminate the options
141 //
142 if (*((UINT8 *) Packet + PacketLen - 1) != 0) {
143 return EFI_INVALID_PARAMETER;
144 }
145
146 //
147 // Get the number of options
148 //
149 Status = Mtftp4FillOptions (Packet, PacketLen, OptionCount, NULL);
150
151 if ((Status == EFI_SUCCESS) || (Status != EFI_BUFFER_TOO_SMALL)) {
152 return Status;
153 }
154
155 //
156 // Allocate memory for the options, then call Mtftp4FillOptions to
157 // fill it if caller want that.
158 //
159 if (OptionList == NULL) {
160 return EFI_SUCCESS;
161 }
162
163 *OptionList = AllocatePool (*OptionCount * sizeof (EFI_MTFTP4_OPTION));
164
165 if (*OptionList == NULL) {
166 return EFI_OUT_OF_RESOURCES;
167 }
168
169 Mtftp4FillOptions (Packet, PacketLen, OptionCount, *OptionList);
170 return EFI_SUCCESS;
171 }
172
173
174 /**
175 Check whether two ascii strings are equel, ignore the case.
176
177 @param Str1 The first ascii string
178 @param Str2 The second ascii string
179
180 @retval TRUE Two strings are equal when case is ignored.
181 @retval FALSE Two string are not equal.
182
183 **/
184 BOOLEAN
185 NetStringEqualNoCase (
186 IN UINT8 *Str1,
187 IN UINT8 *Str2
188 )
189 {
190 UINT8 Ch1;
191 UINT8 Ch2;
192
193 ASSERT ((Str1 != NULL) && (Str2 != NULL));
194
195 for (; (*Str1 != '\0') && (*Str2 != '\0'); Str1++, Str2++) {
196 Ch1 = *Str1;
197 Ch2 = *Str2;
198
199 //
200 // Convert them to lower case then compare two
201 //
202 if (('A' <= Ch1) && (Ch1 <= 'Z')) {
203 Ch1 += 'a' - 'A';
204 }
205
206 if (('A' <= Ch2) && (Ch2 <= 'Z')) {
207 Ch2 += 'a' - 'A';
208 }
209
210 if (Ch1 != Ch2) {
211 return FALSE;
212 }
213 }
214
215 return (BOOLEAN) (*Str1 == *Str2);
216 }
217
218
219 /**
220 Convert a string to a UINT32 number.
221
222 @param Str The string to convert from
223
224 @return The number get from the string
225
226 **/
227 UINT32
228 NetStringToU32 (
229 IN UINT8 *Str
230 )
231 {
232 UINT32 Num;
233
234 ASSERT (Str != NULL);
235
236 Num = 0;
237
238 for (; NET_IS_DIGIT (*Str); Str++) {
239 Num = Num * 10 + (*Str - '0');
240 }
241
242 return Num;
243 }
244
245
246 /**
247 Convert a string of the format "192.168.0.1" to an IP address.
248
249 @param Str The string representation of IP
250 @param Ip The varible to get IP.
251
252 @retval EFI_INVALID_PARAMETER The IP string is invalid.
253 @retval EFI_SUCCESS The IP is parsed into the Ip
254
255 **/
256 EFI_STATUS
257 NetStringToIp (
258 IN UINT8 *Str,
259 OUT IP4_ADDR *Ip
260 )
261 {
262 UINT32 Byte;
263 UINT32 Addr;
264 UINTN Index;
265
266 *Ip = 0;
267 Addr = 0;
268
269 for (Index = 0; Index < 4; Index++) {
270 if (!NET_IS_DIGIT (*Str)) {
271 return EFI_INVALID_PARAMETER;
272 }
273
274 Byte = NetStringToU32 (Str);
275
276 if (Byte > 255) {
277 return EFI_INVALID_PARAMETER;
278 }
279
280 Addr = (Addr << 8) | Byte;
281
282 //
283 // Skip all the digitals and check whether the sepeator is the dot
284 //
285 while (NET_IS_DIGIT (*Str)) {
286 Str++;
287 }
288
289 if ((Index < 3) && (*Str != '.')) {
290 return EFI_INVALID_PARAMETER;
291 }
292
293 Str++;
294 }
295
296 *Ip = Addr;
297
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
529 Status = Mtftp4ParseOption (OptionList, Count, FALSE, MtftpOption);
530
531 gBS->FreePool (OptionList);
532 return Status;
533 }