TianoCore EDK2 master
Loading...
Searching...
No Matches
Mtftp4Option.c
Go to the documentation of this file.
1
9#include "Mtftp4Impl.h"
10
11CHAR8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS] = {
12 "blksize",
13 "windowsize",
14 "timeout",
15 "tsize",
16 "multicast"
17};
18
29BOOLEAN
31 IN UINT8 *Str1,
32 IN UINT8 *Str2
33 )
34{
35 UINT8 Ch1;
36 UINT8 Ch2;
37
38 ASSERT ((Str1 != NULL) && (Str2 != NULL));
39
40 for ( ; (*Str1 != '\0') && (*Str2 != '\0'); Str1++, Str2++) {
41 Ch1 = *Str1;
42 Ch2 = *Str2;
43
44 //
45 // Convert them to lower case then compare two
46 //
47 if (('A' <= Ch1) && (Ch1 <= 'Z')) {
48 Ch1 += 'a' - 'A';
49 }
50
51 if (('A' <= Ch2) && (Ch2 <= 'Z')) {
52 Ch2 += 'a' - 'A';
53 }
54
55 if (Ch1 != Ch2) {
56 return FALSE;
57 }
58 }
59
60 return (BOOLEAN)(*Str1 == *Str2);
61}
62
71UINT32
73 IN UINT8 *Str
74 )
75{
76 UINT32 Num;
77
78 ASSERT (Str != NULL);
79
80 Num = 0;
81
82 for ( ; NET_IS_DIGIT (*Str); Str++) {
83 Num = Num * 10 + (*Str - '0');
84 }
85
86 return Num;
87}
88
101 IN UINT8 *Str,
102 OUT IP4_ADDR *Ip
103 )
104{
105 UINT32 Byte;
106 UINT32 Addr;
107 UINTN Index;
108
109 *Ip = 0;
110 Addr = 0;
111
112 for (Index = 0; Index < 4; Index++) {
113 if (!NET_IS_DIGIT (*Str)) {
114 return EFI_INVALID_PARAMETER;
115 }
116
117 Byte = NetStringToU32 (Str);
118
119 if (Byte > 255) {
120 return EFI_INVALID_PARAMETER;
121 }
122
123 Addr = (Addr << 8) | Byte;
124
125 //
126 // Skip all the digitals and check whether the separator is the dot
127 //
128 while (NET_IS_DIGIT (*Str)) {
129 Str++;
130 }
131
132 if ((Index < 3) && (*Str != '.')) {
133 return EFI_INVALID_PARAMETER;
134 }
135
136 Str++;
137 }
138
139 *Ip = Addr;
140
141 return EFI_SUCCESS;
142}
143
161 IN EFI_MTFTP4_PACKET *Packet,
162 IN UINT32 PacketLen,
163 IN OUT UINT32 *Count,
164 OUT EFI_MTFTP4_OPTION *Options OPTIONAL
165 )
166{
167 UINT8 *Cur;
168 UINT8 *Last;
169 UINT8 Num;
170 UINT8 *Name;
171 UINT8 *Value;
172
173 Num = 0;
174 Cur = (UINT8 *)Packet + MTFTP4_OPCODE_LEN;
175 Last = (UINT8 *)Packet + PacketLen - 1;
176
177 //
178 // process option name and value pairs. The last byte is always zero
179 //
180 while (Cur < Last) {
181 Name = Cur;
182
183 while (*Cur != 0) {
184 Cur++;
185 }
186
187 if (Cur == Last) {
188 return EFI_INVALID_PARAMETER;
189 }
190
191 Value = ++Cur;
192
193 while (*Cur != 0) {
194 Cur++;
195 }
196
197 Num++;
198
199 if ((Options != NULL) && (Num <= *Count)) {
200 Options[Num - 1].OptionStr = Name;
201 Options[Num - 1].ValueStr = Value;
202 }
203
204 Cur++;
205 }
206
207 if ((*Count < Num) || (Options == NULL)) {
208 *Count = Num;
209 return EFI_BUFFER_TOO_SMALL;
210 }
211
212 *Count = Num;
213 return EFI_SUCCESS;
214}
215
235 IN EFI_MTFTP4_PACKET *Packet,
236 IN UINT32 PacketLen,
237 OUT UINT32 *OptionCount,
238 OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL
239 )
240{
241 EFI_STATUS Status;
242
243 *OptionCount = 0;
244
245 if (OptionList != NULL) {
246 *OptionList = NULL;
247 }
248
249 if (NTOHS (Packet->OpCode) != EFI_MTFTP4_OPCODE_OACK) {
250 return EFI_INVALID_PARAMETER;
251 }
252
253 if (PacketLen == MTFTP4_OPCODE_LEN) {
254 return EFI_SUCCESS;
255 }
256
257 //
258 // The last byte must be zero to terminate the options
259 //
260 if (*((UINT8 *)Packet + PacketLen - 1) != 0) {
261 return EFI_INVALID_PARAMETER;
262 }
263
264 //
265 // Get the number of options
266 //
267 Status = Mtftp4FillOptions (Packet, PacketLen, OptionCount, NULL);
268
269 if ((Status == EFI_SUCCESS) || (Status != EFI_BUFFER_TOO_SMALL)) {
270 return Status;
271 }
272
273 //
274 // Allocate memory for the options, then call Mtftp4FillOptions to
275 // fill it if caller want that.
276 //
277 if (OptionList == NULL) {
278 return EFI_SUCCESS;
279 }
280
281 *OptionList = AllocatePool (*OptionCount * sizeof (EFI_MTFTP4_OPTION));
282
283 if (*OptionList == NULL) {
284 return EFI_OUT_OF_RESOURCES;
285 }
286
287 Mtftp4FillOptions (Packet, PacketLen, OptionCount, *OptionList);
288 return EFI_SUCCESS;
289}
290
303 IN UINT8 *Value,
304 IN OUT MTFTP4_OPTION *Option
305 )
306{
307 EFI_STATUS Status;
308 UINT32 Num;
309
310 //
311 // The multicast option is formatted like "204.0.0.1,1857,1"
312 // The server can also omit the ip and port, use ",,1"
313 //
314 if (*Value == ',') {
315 Option->McastIp = 0;
316 } else {
317 Status = NetStringToIp (Value, &Option->McastIp);
318
319 if (EFI_ERROR (Status)) {
320 return Status;
321 }
322
323 while ((*Value != 0) && (*Value != ',')) {
324 Value++;
325 }
326 }
327
328 if (*Value != ',') {
329 return EFI_INVALID_PARAMETER;
330 }
331
332 Value++;
333
334 //
335 // Convert the port setting. the server can send us a port number or
336 // empty string. such as the port in ",,1"
337 //
338 if (*Value == ',') {
339 Option->McastPort = 0;
340 } else {
341 Num = NetStringToU32 (Value);
342
343 if (Num > 65535) {
344 return EFI_INVALID_PARAMETER;
345 }
346
347 Option->McastPort = (UINT16)Num;
348
349 while (NET_IS_DIGIT (*Value)) {
350 Value++;
351 }
352 }
353
354 if (*Value != ',') {
355 return EFI_INVALID_PARAMETER;
356 }
357
358 Value++;
359
360 //
361 // Check the master/slave setting, 1 for master, 0 for slave.
362 //
363 Num = NetStringToU32 (Value);
364
365 if ((Num != 0) && (Num != 1)) {
366 return EFI_INVALID_PARAMETER;
367 }
368
369 Option->Master = (BOOLEAN)(Num == 1);
370
371 while (NET_IS_DIGIT (*Value)) {
372 Value++;
373 }
374
375 if (*Value != '\0') {
376 return EFI_INVALID_PARAMETER;
377 }
378
379 return EFI_SUCCESS;
380}
381
401 IN EFI_MTFTP4_OPTION *Options,
402 IN UINT32 Count,
403 IN BOOLEAN Request,
404 IN UINT16 Operation,
405 OUT MTFTP4_OPTION *MtftpOption
406 )
407{
408 EFI_STATUS Status;
409 UINT32 Index;
410 UINT32 Value;
411 EFI_MTFTP4_OPTION *This;
412
413 MtftpOption->Exist = 0;
414
415 for (Index = 0; Index < Count; Index++) {
416 This = Options + Index;
417
418 if ((This->OptionStr == NULL) || (This->ValueStr == NULL)) {
419 return EFI_INVALID_PARAMETER;
420 }
421
422 if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"blksize")) {
423 //
424 // block size option, valid value is between [8, 65464]
425 //
426 Value = NetStringToU32 (This->ValueStr);
427
428 if ((Value < 8) || (Value > 65464)) {
429 return EFI_INVALID_PARAMETER;
430 }
431
432 MtftpOption->BlkSize = (UINT16)Value;
433 MtftpOption->Exist |= MTFTP4_BLKSIZE_EXIST;
434 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"timeout")) {
435 //
436 // timeout option, valid value is between [1, 255]
437 //
438 Value = NetStringToU32 (This->ValueStr);
439
440 if ((Value < 1) || (Value > 255)) {
441 return EFI_INVALID_PARAMETER;
442 }
443
444 MtftpOption->Timeout = (UINT8)Value;
445 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"tsize")) {
446 //
447 // tsize option, the biggest transfer supported is 4GB with block size option
448 //
449 MtftpOption->Tsize = NetStringToU32 (This->ValueStr);
450 MtftpOption->Exist |= MTFTP4_TSIZE_EXIST;
451 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"multicast")) {
452 //
453 // Multicast option, if it is a request, the value must be a zero
454 // length string, otherwise, it is formatted like "204.0.0.1,1857,1\0"
455 //
456 if (Request) {
457 if (*(This->ValueStr) != '\0') {
458 return EFI_INVALID_PARAMETER;
459 }
460 } else {
461 Status = Mtftp4ExtractMcast (This->ValueStr, MtftpOption);
462
463 if (EFI_ERROR (Status)) {
464 return Status;
465 }
466 }
467
468 MtftpOption->Exist |= MTFTP4_MCAST_EXIST;
469 } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *)"windowsize")) {
470 if (Operation == EFI_MTFTP4_OPCODE_WRQ) {
471 //
472 // Currently, windowsize is not supported in the write operation.
473 //
474 return EFI_UNSUPPORTED;
475 }
476
477 Value = NetStringToU32 (This->ValueStr);
478
479 if (Value < 1) {
480 return EFI_INVALID_PARAMETER;
481 }
482
483 MtftpOption->WindowSize = (UINT16)Value;
484 MtftpOption->Exist |= MTFTP4_WINDOWSIZE_EXIST;
485 } else if (Request) {
486 //
487 // Ignore the unsupported option if it is a reply, and return
488 // EFI_UNSUPPORTED if it's a request according to the UEFI spec.
489 //
490 return EFI_UNSUPPORTED;
491 }
492 }
493
494 return EFI_SUCCESS;
495}
496
513 IN EFI_MTFTP4_PACKET *Packet,
514 IN UINT32 PacketLen,
515 IN UINT16 Operation,
516 OUT MTFTP4_OPTION *MtftpOption
517 )
518{
519 EFI_MTFTP4_OPTION *OptionList;
520 EFI_STATUS Status;
521 UINT32 Count;
522
523 MtftpOption->Exist = 0;
524
525 Status = Mtftp4ExtractOptions (Packet, PacketLen, &Count, &OptionList);
526
527 if (EFI_ERROR (Status) || (Count == 0)) {
528 return Status;
529 }
530
531 ASSERT (OptionList != NULL);
532
533 Status = Mtftp4ParseOption (OptionList, Count, FALSE, Operation, MtftpOption);
534
535 FreePool (OptionList);
536 return Status;
537}
UINT64 UINTN
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
BOOLEAN NetStringEqualNoCase(IN UINT8 *Str1, IN UINT8 *Str2)
Definition: Mtftp4Option.c:30
EFI_STATUS Mtftp4ExtractOptions(IN EFI_MTFTP4_PACKET *Packet, IN UINT32 PacketLen, OUT UINT32 *OptionCount, OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL)
Definition: Mtftp4Option.c:234
EFI_STATUS Mtftp4ParseOption(IN EFI_MTFTP4_OPTION *Options, IN UINT32 Count, IN BOOLEAN Request, IN UINT16 Operation, OUT MTFTP4_OPTION *MtftpOption)
Definition: Mtftp4Option.c:400
UINT32 NetStringToU32(IN UINT8 *Str)
Definition: Mtftp4Option.c:72
EFI_STATUS NetStringToIp(IN UINT8 *Str, OUT IP4_ADDR *Ip)
Definition: Mtftp4Option.c:100
EFI_STATUS Mtftp4ExtractMcast(IN UINT8 *Value, IN OUT MTFTP4_OPTION *Option)
Definition: Mtftp4Option.c:302
EFI_STATUS Mtftp4FillOptions(IN EFI_MTFTP4_PACKET *Packet, IN UINT32 PacketLen, IN OUT UINT32 *Count, OUT EFI_MTFTP4_OPTION *Options OPTIONAL)
Definition: Mtftp4Option.c:160
EFI_STATUS Mtftp4ParseOptionOack(IN EFI_MTFTP4_PACKET *Packet, IN UINT32 PacketLen, IN UINT16 Operation, OUT MTFTP4_OPTION *MtftpOption)
Definition: Mtftp4Option.c:512
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112