TianoCore EDK2 master
Loading...
Searching...
No Matches
Mtftp6Option.c
Go to the documentation of this file.
1
10#include "Mtftp6Impl.h"
11
12CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = {
13 "blksize",
14 "windowsize",
15 "timeout",
16 "tsize",
17 "multicast"
18};
19
34 IN UINT8 *Str,
36 )
37{
38 EFI_STATUS Status;
39 UINT32 Num;
40 CHAR8 *Ip6Str;
41 CHAR8 *TempStr;
42
43 //
44 // The multicast option is formatted like "addr,port,mc"
45 // The server can also omit the ip and port, use ",,1"
46 //
47 if (*Str == ',') {
48 ZeroMem (&ExtInfo->McastIp, sizeof (EFI_IPv6_ADDRESS));
49 } else {
50 Ip6Str = (CHAR8 *)AllocateCopyPool (AsciiStrSize ((CHAR8 *)Str), Str);
51 if (Ip6Str == NULL) {
52 return EFI_OUT_OF_RESOURCES;
53 }
54
55 //
56 // The IPv6 address locates before comma in the input Str.
57 //
58 TempStr = Ip6Str;
59 while ((*TempStr != '\0') && (*TempStr != ',')) {
60 TempStr++;
61 }
62
63 *TempStr = '\0';
64
65 Status = NetLibAsciiStrToIp6 (Ip6Str, &ExtInfo->McastIp);
66 FreePool (Ip6Str);
67
68 if (EFI_ERROR (Status)) {
69 return Status;
70 }
71
72 while ((*Str != '\0') && (*Str != ',')) {
73 Str++;
74 }
75 }
76
77 if (*Str != ',') {
78 return EFI_INVALID_PARAMETER;
79 }
80
81 Str++;
82
83 //
84 // Convert the port setting. the server can send us a port number or
85 // empty string. such as the port in ",,1"
86 //
87 if (*Str == ',') {
88 ExtInfo->McastPort = 0;
89 } else {
90 Num = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Str);
91
92 if (Num > 65535) {
93 return EFI_INVALID_PARAMETER;
94 }
95
96 ExtInfo->McastPort = (UINT16)Num;
97
98 while (NET_IS_DIGIT (*Str)) {
99 Str++;
100 }
101 }
102
103 if (*Str != ',') {
104 return EFI_INVALID_PARAMETER;
105 }
106
107 Str++;
108
109 //
110 // Check the master/slave setting, 1 for master, 0 for slave.
111 //
112 Num = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Str);
113
114 if ((Num != 0) && (Num != 1)) {
115 return EFI_INVALID_PARAMETER;
116 }
117
118 ExtInfo->IsMaster = (BOOLEAN)(Num == 1);
119
120 while (NET_IS_DIGIT (*Str)) {
121 Str++;
122 }
123
124 if (*Str != '\0') {
125 return EFI_INVALID_PARAMETER;
126 }
127
128 return EFI_SUCCESS;
129}
130
148 IN EFI_MTFTP6_OPTION *Options,
149 IN UINT32 Count,
150 IN BOOLEAN IsRequest,
151 IN UINT16 Operation,
153 )
154{
155 EFI_STATUS Status;
157 UINT32 Index;
158 UINT32 Value;
159
160 ExtInfo->BitMap = 0;
161
162 for (Index = 0; Index < Count; Index++) {
163 Opt = Options + Index;
164
165 if ((Opt->OptionStr == NULL) || (Opt->ValueStr == NULL)) {
166 return EFI_INVALID_PARAMETER;
167 }
168
169 if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "blksize") == 0) {
170 //
171 // block size option, valid value is between [8, 65464]
172 //
173 Value = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);
174
175 if ((Value < 8) || (Value > 65464)) {
176 return EFI_INVALID_PARAMETER;
177 }
178
179 ExtInfo->BlkSize = (UINT16)Value;
180 ExtInfo->BitMap |= MTFTP6_OPT_BLKSIZE_BIT;
181 } else if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "timeout") == 0) {
182 //
183 // timeout option, valid value is between [1, 255]
184 //
185 Value = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);
186
187 if ((Value < 1) || (Value > 255)) {
188 return EFI_INVALID_PARAMETER;
189 }
190
191 ExtInfo->Timeout = (UINT8)Value;
192 ExtInfo->BitMap |= MTFTP6_OPT_TIMEOUT_BIT;
193 } else if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "tsize") == 0) {
194 //
195 // tsize option, the biggest transfer supported is 4GB with block size option
196 //
197 ExtInfo->Tsize = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);
198 ExtInfo->BitMap |= MTFTP6_OPT_TSIZE_BIT;
199 } else if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "multicast") == 0) {
200 //
201 // Multicast option, if it is a request, the value must be a zero string,
202 // otherwise, it must be like "addr,port,mc" string, mc indicates master.
203 //
204 if (!IsRequest) {
205 Status = Mtftp6ParseMcastOption (Opt->ValueStr, ExtInfo);
206
207 if (EFI_ERROR (Status)) {
208 return Status;
209 }
210 } else if (*(Opt->ValueStr) != '\0') {
211 return EFI_INVALID_PARAMETER;
212 }
213
214 ExtInfo->BitMap |= MTFTP6_OPT_MCAST_BIT;
215 } else if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "windowsize") == 0) {
216 if (Operation == EFI_MTFTP6_OPCODE_WRQ) {
217 //
218 // Currently, windowsize is not supported in the write operation.
219 //
220 return EFI_UNSUPPORTED;
221 }
222
223 Value = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);
224
225 if ((Value < 1)) {
226 return EFI_INVALID_PARAMETER;
227 }
228
229 ExtInfo->WindowSize = (UINT16)Value;
230 ExtInfo->BitMap |= MTFTP6_OPT_WINDOWSIZE_BIT;
231 } else if (IsRequest) {
232 //
233 // If it's a request, unsupported; else if it's a reply, ignore.
234 //
235 return EFI_UNSUPPORTED;
236 }
237 }
238
239 return EFI_SUCCESS;
240}
241
261 IN EFI_MTFTP6_PACKET *Packet,
262 IN UINT32 PacketLen,
263 IN OUT UINT32 *Count,
264 IN EFI_MTFTP6_OPTION *Options OPTIONAL
265 )
266{
267 UINT8 *Cur;
268 UINT8 *Last;
269 UINT8 Num;
270 UINT8 *Name;
271 UINT8 *Value;
272
273 Num = 0;
274 Cur = (UINT8 *)Packet + MTFTP6_OPCODE_LEN;
275 Last = (UINT8 *)Packet + PacketLen - 1;
276
277 //
278 // process option name and value pairs.
279 // The last byte is always zero.
280 //
281 while (Cur < Last) {
282 Name = Cur;
283
284 while (*Cur != 0) {
285 Cur++;
286 }
287
288 if (Cur == Last) {
289 return EFI_PROTOCOL_ERROR;
290 }
291
292 Value = ++Cur;
293
294 while (*Cur != 0) {
295 Cur++;
296 }
297
298 Num++;
299
300 if ((Options != NULL) && (Num <= *Count)) {
301 Options[Num - 1].OptionStr = Name;
302 Options[Num - 1].ValueStr = Value;
303 }
304
305 Cur++;
306 }
307
308 //
309 // Return buffer too small if the buffer passed-in isn't enough.
310 //
311 if ((*Count < Num) || (Options == NULL)) {
312 *Count = Num;
313 return EFI_BUFFER_TOO_SMALL;
314 }
315
316 *Count = Num;
317 return EFI_SUCCESS;
318}
319
341 IN EFI_MTFTP6_PACKET *Packet,
342 IN UINT32 PacketLen,
343 IN OUT UINT32 *OptionCount,
344 OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
345 )
346{
347 EFI_STATUS Status;
348
349 if ((PacketLen == 0) || (Packet == NULL) || (OptionCount == NULL)) {
350 return EFI_INVALID_PARAMETER;
351 }
352
353 *OptionCount = 0;
354
355 if (OptionList != NULL) {
356 *OptionList = NULL;
357 }
358
359 if (NTOHS (Packet->OpCode) != EFI_MTFTP6_OPCODE_OACK) {
360 return EFI_INVALID_PARAMETER;
361 }
362
363 //
364 // The last byte must be zero to terminate the options.
365 //
366 if (*((UINT8 *)Packet + PacketLen - 1) != 0) {
367 return EFI_PROTOCOL_ERROR;
368 }
369
370 //
371 // Parse packet with NULL buffer for the first time to get the number
372 // of options in the packet.
373 //
374 Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, NULL);
375
376 if (Status != EFI_BUFFER_TOO_SMALL) {
377 return Status;
378 }
379
380 //
381 // Return not found if there is no option parsed.
382 //
383 if (*OptionCount == 0) {
384 return EFI_NOT_FOUND;
385 }
386
387 //
388 // Only need parse out the number of options.
389 //
390 if (OptionList == NULL) {
391 return EFI_SUCCESS;
392 }
393
394 //
395 // Allocate the buffer according to the option number parsed before.
396 //
397 *OptionList = AllocateZeroPool (*OptionCount * sizeof (EFI_MTFTP6_OPTION));
398
399 if (*OptionList == NULL) {
400 return EFI_OUT_OF_RESOURCES;
401 }
402
403 //
404 // Parse packet with allocated buffer for the second time to fill the pointer array
405 // of the options in the packet.
406 //
407 Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, *OptionList);
408
409 if (EFI_ERROR (Status)) {
410 return Status;
411 }
412
413 return EFI_SUCCESS;
414}
INTN EFIAPI AsciiStriCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:814
UINTN EFIAPI AsciiStrDecimalToUintn(IN CONST CHAR8 *String)
Definition: String.c:1006
UINTN EFIAPI AsciiStrSize(IN CONST CHAR8 *String)
Definition: String.c:681
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define EFI_MTFTP6_OPCODE_OACK
The MTFTPv6 packet is an option acknowledgement packet.
Definition: Mtftp6.h:40
#define EFI_MTFTP6_OPCODE_WRQ
The MTFTPv6 packet is a write request.
Definition: Mtftp6.h:36
EFI_STATUS Mtftp6ParsePacketOption(IN EFI_MTFTP6_PACKET *Packet, IN UINT32 PacketLen, IN OUT UINT32 *Count, IN EFI_MTFTP6_OPTION *Options OPTIONAL)
Definition: Mtftp6Option.c:260
EFI_STATUS Mtftp6ParseMcastOption(IN UINT8 *Str, IN MTFTP6_EXT_OPTION_INFO *ExtInfo)
Definition: Mtftp6Option.c:33
EFI_STATUS Mtftp6ParseExtensionOption(IN EFI_MTFTP6_OPTION *Options, IN UINT32 Count, IN BOOLEAN IsRequest, IN UINT16 Operation, IN MTFTP6_EXT_OPTION_INFO *ExtInfo)
Definition: Mtftp6Option.c:147
EFI_STATUS Mtftp6ParseStart(IN EFI_MTFTP6_PACKET *Packet, IN UINT32 PacketLen, IN OUT UINT32 *OptionCount, OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL)
Definition: Mtftp6Option.c:340
EFI_STATUS EFIAPI NetLibAsciiStrToIp6(IN CONST CHAR8 *String, OUT EFI_IPv6_ADDRESS *Ip6Address)
Definition: DxeNetLib.c:3097
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
UINT8 * ValueStr
Pointer to the null-terminated ASCII MTFTPv6 value string.
Definition: Mtftp6.h:303
UINT8 * OptionStr
Pointer to the null-terminated ASCII MTFTPv6 option string.
Definition: Mtftp6.h:302