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