]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Mtftp6Dxe/Mtftp6Option.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / Mtftp6Dxe / Mtftp6Option.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Mtftp6 option parse functions implementation.\r
3\r
f3427f12 4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
a3bcde70 5\r
ecf98fbc 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a3bcde70
HT
7\r
8**/\r
9\r
10#include "Mtftp6Impl.h"\r
11\r
d1050b9d 12CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = {\r
a3bcde70 13 "blksize",\r
f3427f12 14 "windowsize",\r
a3bcde70
HT
15 "timeout",\r
16 "tsize",\r
17 "multicast"\r
18};\r
19\r
a3bcde70
HT
20/**\r
21 Parse the NULL terminated ASCII string of multicast option.\r
22\r
23 @param[in] Str The pointer to the Ascii string of multicast option.\r
24 @param[in] ExtInfo The pointer to the option information to be filled.\r
25\r
26 @retval EFI_SUCCESS Parse the multicast option successfully.\r
27 @retval EFI_INVALID_PARAMETER The string is malformatted.\r
28 @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of\r
29 resources.\r
30\r
31**/\r
32EFI_STATUS\r
33Mtftp6ParseMcastOption (\r
d1050b9d
MK
34 IN UINT8 *Str,\r
35 IN MTFTP6_EXT_OPTION_INFO *ExtInfo\r
a3bcde70
HT
36 )\r
37{\r
d1050b9d
MK
38 EFI_STATUS Status;\r
39 UINT32 Num;\r
40 CHAR8 *Ip6Str;\r
41 CHAR8 *TempStr;\r
a3bcde70
HT
42\r
43 //\r
f6c8bbbe 44 // The multicast option is formatted like "addr,port,mc"\r
a3bcde70
HT
45 // The server can also omit the ip and port, use ",,1"\r
46 //\r
47 if (*Str == ',') {\r
a3bcde70
HT
48 ZeroMem (&ExtInfo->McastIp, sizeof (EFI_IPv6_ADDRESS));\r
49 } else {\r
d1050b9d 50 Ip6Str = (CHAR8 *)AllocateCopyPool (AsciiStrSize ((CHAR8 *)Str), Str);\r
a3bcde70
HT
51 if (Ip6Str == NULL) {\r
52 return EFI_OUT_OF_RESOURCES;\r
53 }\r
54\r
55 //\r
56 // The IPv6 address locates before comma in the input Str.\r
57 //\r
58 TempStr = Ip6Str;\r
59 while ((*TempStr != '\0') && (*TempStr != ',')) {\r
60 TempStr++;\r
61 }\r
62\r
63 *TempStr = '\0';\r
64\r
65 Status = NetLibAsciiStrToIp6 (Ip6Str, &ExtInfo->McastIp);\r
66 FreePool (Ip6Str);\r
67\r
68 if (EFI_ERROR (Status)) {\r
69 return Status;\r
70 }\r
71\r
72 while ((*Str != '\0') && (*Str != ',')) {\r
73 Str++;\r
74 }\r
75 }\r
76\r
77 if (*Str != ',') {\r
78 return EFI_INVALID_PARAMETER;\r
79 }\r
80\r
81 Str++;\r
82\r
83 //\r
84 // Convert the port setting. the server can send us a port number or\r
85 // empty string. such as the port in ",,1"\r
86 //\r
87 if (*Str == ',') {\r
a3bcde70
HT
88 ExtInfo->McastPort = 0;\r
89 } else {\r
d1050b9d 90 Num = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Str);\r
a3bcde70
HT
91\r
92 if (Num > 65535) {\r
93 return EFI_INVALID_PARAMETER;\r
94 }\r
95\r
d1050b9d 96 ExtInfo->McastPort = (UINT16)Num;\r
a3bcde70
HT
97\r
98 while (NET_IS_DIGIT (*Str)) {\r
99 Str++;\r
100 }\r
101 }\r
102\r
103 if (*Str != ',') {\r
104 return EFI_INVALID_PARAMETER;\r
105 }\r
106\r
107 Str++;\r
108\r
109 //\r
110 // Check the master/slave setting, 1 for master, 0 for slave.\r
111 //\r
d1050b9d 112 Num = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Str);\r
a3bcde70 113\r
d1050b9d 114 if ((Num != 0) && (Num != 1)) {\r
a3bcde70
HT
115 return EFI_INVALID_PARAMETER;\r
116 }\r
117\r
d1050b9d 118 ExtInfo->IsMaster = (BOOLEAN)(Num == 1);\r
a3bcde70
HT
119\r
120 while (NET_IS_DIGIT (*Str)) {\r
121 Str++;\r
122 }\r
123\r
124 if (*Str != '\0') {\r
125 return EFI_INVALID_PARAMETER;\r
126 }\r
127\r
128 return EFI_SUCCESS;\r
129}\r
130\r
a3bcde70 131/**\r
f6c8bbbe 132 Parse the MTFTP6 extension options.\r
a3bcde70
HT
133\r
134 @param[in] Options The pointer to the extension options list.\r
135 @param[in] Count The num of the extension options.\r
136 @param[in] IsRequest If FALSE, the extension options is included\r
137 by a request packet.\r
f3427f12 138 @param[in] Operation The current performed operation.\r
a3bcde70
HT
139 @param[in] ExtInfo The pointer to the option information to be filled.\r
140\r
141 @retval EFI_SUCCESS Parse the multicast option successfully.\r
142 @retval EFI_INVALID_PARAMETER There is one option is malformatted at least.\r
143 @retval EFI_UNSUPPORTED There is one option is not supported at least.\r
144\r
145**/\r
146EFI_STATUS\r
147Mtftp6ParseExtensionOption (\r
d1050b9d
MK
148 IN EFI_MTFTP6_OPTION *Options,\r
149 IN UINT32 Count,\r
150 IN BOOLEAN IsRequest,\r
151 IN UINT16 Operation,\r
152 IN MTFTP6_EXT_OPTION_INFO *ExtInfo\r
a3bcde70
HT
153 )\r
154{\r
d1050b9d
MK
155 EFI_STATUS Status;\r
156 EFI_MTFTP6_OPTION *Opt;\r
157 UINT32 Index;\r
158 UINT32 Value;\r
a3bcde70
HT
159\r
160 ExtInfo->BitMap = 0;\r
161\r
162 for (Index = 0; Index < Count; Index++) {\r
a3bcde70
HT
163 Opt = Options + Index;\r
164\r
d1050b9d 165 if ((Opt->OptionStr == NULL) || (Opt->ValueStr == NULL)) {\r
a3bcde70
HT
166 return EFI_INVALID_PARAMETER;\r
167 }\r
168\r
d1050b9d 169 if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "blksize") == 0) {\r
a3bcde70
HT
170 //\r
171 // block size option, valid value is between [8, 65464]\r
172 //\r
d1050b9d 173 Value = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);\r
a3bcde70
HT
174\r
175 if ((Value < 8) || (Value > 65464)) {\r
176 return EFI_INVALID_PARAMETER;\r
177 }\r
178\r
d1050b9d 179 ExtInfo->BlkSize = (UINT16)Value;\r
a3bcde70 180 ExtInfo->BitMap |= MTFTP6_OPT_BLKSIZE_BIT;\r
d1050b9d 181 } else if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "timeout") == 0) {\r
a3bcde70
HT
182 //\r
183 // timeout option, valid value is between [1, 255]\r
184 //\r
d1050b9d 185 Value = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);\r
a3bcde70 186\r
d1050b9d 187 if ((Value < 1) || (Value > 255)) {\r
a3bcde70
HT
188 return EFI_INVALID_PARAMETER;\r
189 }\r
190\r
d1050b9d 191 ExtInfo->Timeout = (UINT8)Value;\r
a3bcde70 192 ExtInfo->BitMap |= MTFTP6_OPT_TIMEOUT_BIT;\r
d1050b9d 193 } else if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "tsize") == 0) {\r
a3bcde70
HT
194 //\r
195 // tsize option, the biggest transfer supported is 4GB with block size option\r
196 //\r
d1050b9d 197 ExtInfo->Tsize = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);\r
a3bcde70 198 ExtInfo->BitMap |= MTFTP6_OPT_TSIZE_BIT;\r
d1050b9d 199 } else if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "multicast") == 0) {\r
a3bcde70
HT
200 //\r
201 // Multicast option, if it is a request, the value must be a zero string,\r
202 // otherwise, it must be like "addr,port,mc" string, mc indicates master.\r
203 //\r
204 if (!IsRequest) {\r
a3bcde70
HT
205 Status = Mtftp6ParseMcastOption (Opt->ValueStr, ExtInfo);\r
206\r
207 if (EFI_ERROR (Status)) {\r
208 return Status;\r
209 }\r
210 } else if (*(Opt->ValueStr) != '\0') {\r
a3bcde70
HT
211 return EFI_INVALID_PARAMETER;\r
212 }\r
213\r
214 ExtInfo->BitMap |= MTFTP6_OPT_MCAST_BIT;\r
d1050b9d 215 } else if (AsciiStriCmp ((CHAR8 *)Opt->OptionStr, "windowsize") == 0) {\r
f3427f12
JW
216 if (Operation == EFI_MTFTP6_OPCODE_WRQ) {\r
217 //\r
218 // Currently, windowsize is not supported in the write operation.\r
219 //\r
220 return EFI_UNSUPPORTED;\r
221 }\r
222\r
d1050b9d 223 Value = (UINT32)AsciiStrDecimalToUintn ((CHAR8 *)Opt->ValueStr);\r
f3427f12
JW
224\r
225 if ((Value < 1)) {\r
226 return EFI_INVALID_PARAMETER;\r
227 }\r
228\r
d1050b9d
MK
229 ExtInfo->WindowSize = (UINT16)Value;\r
230 ExtInfo->BitMap |= MTFTP6_OPT_WINDOWSIZE_BIT;\r
a3bcde70
HT
231 } else if (IsRequest) {\r
232 //\r
233 // If it's a request, unsupported; else if it's a reply, ignore.\r
234 //\r
235 return EFI_UNSUPPORTED;\r
236 }\r
237 }\r
238\r
239 return EFI_SUCCESS;\r
240}\r
241\r
a3bcde70
HT
242/**\r
243 Go through the packet to fill the options array with the start\r
244 addresses of each MTFTP option name/value pair.\r
245\r
246 @param[in] Packet The packet to be checked.\r
247 @param[in] PacketLen The length of the packet.\r
248 @param[in, out] Count The num of the Options on input.\r
249 The actual one on output.\r
250 @param[in] Options The option array to be filled.\r
251 It is optional.\r
252\r
253 @retval EFI_SUCCESS The packet has been parsed successfully.\r
254 @retval EFI_INVALID_PARAMETER The packet is malformatted.\r
255 @retval EFI_BUFFER_TOO_SMALL The Options array is too small.\r
256 @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.\r
257\r
258**/\r
259EFI_STATUS\r
260Mtftp6ParsePacketOption (\r
d1050b9d
MK
261 IN EFI_MTFTP6_PACKET *Packet,\r
262 IN UINT32 PacketLen,\r
263 IN OUT UINT32 *Count,\r
264 IN EFI_MTFTP6_OPTION *Options OPTIONAL\r
a3bcde70
HT
265 )\r
266{\r
d1050b9d
MK
267 UINT8 *Cur;\r
268 UINT8 *Last;\r
269 UINT8 Num;\r
270 UINT8 *Name;\r
271 UINT8 *Value;\r
a3bcde70 272\r
d1050b9d
MK
273 Num = 0;\r
274 Cur = (UINT8 *)Packet + MTFTP6_OPCODE_LEN;\r
275 Last = (UINT8 *)Packet + PacketLen - 1;\r
a3bcde70
HT
276\r
277 //\r
278 // process option name and value pairs.\r
279 // The last byte is always zero.\r
280 //\r
281 while (Cur < Last) {\r
282 Name = Cur;\r
283\r
284 while (*Cur != 0) {\r
285 Cur++;\r
286 }\r
287\r
288 if (Cur == Last) {\r
289 return EFI_PROTOCOL_ERROR;\r
290 }\r
291\r
292 Value = ++Cur;\r
293\r
294 while (*Cur != 0) {\r
295 Cur++;\r
296 }\r
297\r
298 Num++;\r
299\r
d1050b9d
MK
300 if ((Options != NULL) && (Num <= *Count)) {\r
301 Options[Num - 1].OptionStr = Name;\r
302 Options[Num - 1].ValueStr = Value;\r
a3bcde70
HT
303 }\r
304\r
305 Cur++;\r
306 }\r
307\r
308 //\r
309 // Return buffer too small if the buffer passed-in isn't enough.\r
310 //\r
d1050b9d 311 if ((*Count < Num) || (Options == NULL)) {\r
a3bcde70
HT
312 *Count = Num;\r
313 return EFI_BUFFER_TOO_SMALL;\r
314 }\r
315\r
316 *Count = Num;\r
317 return EFI_SUCCESS;\r
318}\r
319\r
a3bcde70
HT
320/**\r
321 Go through the packet, generate option list array and fill it\r
322 by the result of parse options.\r
323\r
324 @param[in] Packet The packet to be checked.\r
325 @param[in] PacketLen The length of the packet.\r
326 @param[in, out] OptionCount The num of the Options on input.\r
327 The actual one on output.\r
328 @param[out] OptionList The option list array to be generated\r
329 and filled. It is optional.\r
330\r
331 @retval EFI_SUCCESS The packet has been parsed successfully.\r
332 @retval EFI_INVALID_PARAMETER The packet is malformatted.\r
333 @retval EFI_PROTOCOL_ERROR There is one option is malformatted at least.\r
334 @retval EFI_NOT_FOUND The packet has no options.\r
335 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.\r
336 @retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.\r
337\r
338**/\r
339EFI_STATUS\r
340Mtftp6ParseStart (\r
d1050b9d
MK
341 IN EFI_MTFTP6_PACKET *Packet,\r
342 IN UINT32 PacketLen,\r
343 IN OUT UINT32 *OptionCount,\r
344 OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL\r
a3bcde70
HT
345 )\r
346{\r
d1050b9d 347 EFI_STATUS Status;\r
a3bcde70 348\r
d1050b9d 349 if ((PacketLen == 0) || (Packet == NULL) || (OptionCount == NULL)) {\r
a3bcde70
HT
350 return EFI_INVALID_PARAMETER;\r
351 }\r
352\r
353 *OptionCount = 0;\r
354\r
355 if (OptionList != NULL) {\r
356 *OptionList = NULL;\r
357 }\r
358\r
359 if (NTOHS (Packet->OpCode) != EFI_MTFTP6_OPCODE_OACK) {\r
360 return EFI_INVALID_PARAMETER;\r
361 }\r
362\r
363 //\r
364 // The last byte must be zero to terminate the options.\r
365 //\r
d1050b9d 366 if (*((UINT8 *)Packet + PacketLen - 1) != 0) {\r
a3bcde70
HT
367 return EFI_PROTOCOL_ERROR;\r
368 }\r
369\r
370 //\r
371 // Parse packet with NULL buffer for the first time to get the number\r
372 // of options in the packet.\r
373 //\r
374 Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, NULL);\r
375\r
376 if (Status != EFI_BUFFER_TOO_SMALL) {\r
377 return Status;\r
378 }\r
379\r
380 //\r
381 // Return not found if there is no option parsed.\r
382 //\r
383 if (*OptionCount == 0) {\r
384 return EFI_NOT_FOUND;\r
385 }\r
386\r
387 //\r
388 // Only need parse out the number of options.\r
389 //\r
390 if (OptionList == NULL) {\r
391 return EFI_SUCCESS;\r
392 }\r
393\r
394 //\r
395 // Allocate the buffer according to the option number parsed before.\r
396 //\r
397 *OptionList = AllocateZeroPool (*OptionCount * sizeof (EFI_MTFTP6_OPTION));\r
398\r
399 if (*OptionList == NULL) {\r
400 return EFI_OUT_OF_RESOURCES;\r
401 }\r
402\r
403 //\r
404 // Parse packet with allocated buffer for the second time to fill the pointer array\r
405 // of the options in the packet.\r
406 //\r
407 Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, *OptionList);\r
408\r
409 if (EFI_ERROR (Status)) {\r
410 return Status;\r
411 }\r
412\r
413 return EFI_SUCCESS;\r
414}\r