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