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