]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Mtftp6Dxe/Mtftp6Option.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / Mtftp6Dxe / Mtftp6Option.c
1 /** @file
2 Mtftp6 option parse functions implementation.
3
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "Mtftp6Impl.h"
11
12 CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = {
13 "blksize",
14 "windowsize",
15 "timeout",
16 "tsize",
17 "multicast"
18 };
19
20 /**
21 Parse the NULL terminated ASCII string of multicast option.
22
23 @param[in] Str The pointer to the Ascii string of multicast option.
24 @param[in] ExtInfo The pointer to the option information to be filled.
25
26 @retval EFI_SUCCESS Parse the multicast option successfully.
27 @retval EFI_INVALID_PARAMETER The string is malformatted.
28 @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of
29 resources.
30
31 **/
32 EFI_STATUS
33 Mtftp6ParseMcastOption (
34 IN UINT8 *Str,
35 IN MTFTP6_EXT_OPTION_INFO *ExtInfo
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
131 /**
132 Parse the MTFTP6 extension options.
133
134 @param[in] Options The pointer to the extension options list.
135 @param[in] Count The num of the extension options.
136 @param[in] IsRequest If FALSE, the extension options is included
137 by a request packet.
138 @param[in] Operation The current performed operation.
139 @param[in] ExtInfo The pointer to the option information to be filled.
140
141 @retval EFI_SUCCESS Parse the multicast option successfully.
142 @retval EFI_INVALID_PARAMETER There is one option is malformatted at least.
143 @retval EFI_UNSUPPORTED There is one option is not supported at least.
144
145 **/
146 EFI_STATUS
147 Mtftp6ParseExtensionOption (
148 IN EFI_MTFTP6_OPTION *Options,
149 IN UINT32 Count,
150 IN BOOLEAN IsRequest,
151 IN UINT16 Operation,
152 IN MTFTP6_EXT_OPTION_INFO *ExtInfo
153 )
154 {
155 EFI_STATUS Status;
156 EFI_MTFTP6_OPTION *Opt;
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
242 /**
243 Go through the packet to fill the options array with the start
244 addresses of each MTFTP option name/value pair.
245
246 @param[in] Packet The packet to be checked.
247 @param[in] PacketLen The length of the packet.
248 @param[in, out] Count The num of the Options on input.
249 The actual one on output.
250 @param[in] Options The option array to be filled.
251 It is optional.
252
253 @retval EFI_SUCCESS The packet has been parsed successfully.
254 @retval EFI_INVALID_PARAMETER The packet is malformatted.
255 @retval EFI_BUFFER_TOO_SMALL The Options array is too small.
256 @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.
257
258 **/
259 EFI_STATUS
260 Mtftp6ParsePacketOption (
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
320 /**
321 Go through the packet, generate option list array and fill it
322 by the result of parse options.
323
324 @param[in] Packet The packet to be checked.
325 @param[in] PacketLen The length of the packet.
326 @param[in, out] OptionCount The num of the Options on input.
327 The actual one on output.
328 @param[out] OptionList The option list array to be generated
329 and filled. It is optional.
330
331 @retval EFI_SUCCESS The packet has been parsed successfully.
332 @retval EFI_INVALID_PARAMETER The packet is malformatted.
333 @retval EFI_PROTOCOL_ERROR There is one option is malformatted at least.
334 @retval EFI_NOT_FOUND The packet has no options.
335 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.
336 @retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.
337
338 **/
339 EFI_STATUS
340 Mtftp6ParseStart (
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 }