]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParser.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / Library / QemuFwCfgSimpleParserLib / QemuFwCfgSimpleParser.c
CommitLineData
611c7f11
LE
1/** @file\r
2 Parse the contents of named fw_cfg files as simple (scalar) data types.\r
3\r
4 Copyright (C) 2020, Red Hat, Inc.\r
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7**/\r
8\r
9#include <Library/BaseLib.h>\r
10#include <Library/QemuFwCfgLib.h>\r
11#include <Library/QemuFwCfgSimpleParserLib.h>\r
12\r
13//\r
14// Size of the longest valid UINT64 string, including the terminating NUL.\r
15//\r
16#define UINT64_STRING_MAX_SIZE \\r
17 MAX (sizeof "18446744073709551615", sizeof "0xFFFFFFFFFFFFFFFF")\r
18\r
19//\r
20// Size of the longest valid BOOL string (see the "mTrueString" and\r
21// "mFalseString" arrays below), including the terminating NUL.\r
22//\r
23#define BOOL_STRING_MAX_SIZE (sizeof "disabled")\r
24\r
25//\r
26// Length of "\r\n", not including the terminating NUL.\r
27//\r
28#define CRLF_LENGTH (sizeof "\r\n" - 1)\r
29\r
30//\r
31// Words recognized as representing TRUE or FALSE.\r
32//\r
33STATIC CONST CHAR8 * CONST mTrueString[] = {\r
34 "true", "yes", "y", "enable", "enabled", "1"\r
35};\r
36STATIC CONST CHAR8 * CONST mFalseString[] = {\r
37 "false", "no", "n", "disable", "disabled", "0"\r
38};\r
39\r
40//\r
41// Helper functions.\r
42//\r
43\r
44/**\r
45 Look up FileName with QemuFwCfgFindFile() from QemuFwCfgLib. Read the fw_cfg\r
46 file into the caller-provided CHAR8 array. NUL-terminate the array.\r
47\r
48 @param[in] FileName The name of the fw_cfg file to look up and read.\r
49\r
50 @param[in,out] BufferSize On input, number of bytes available in Buffer.\r
51\r
52 On output, the number of bytes that have been\r
53 stored to Buffer.\r
54\r
55 On error, BufferSize is indeterminate.\r
56\r
57 @param[out] Buffer The buffer to read the fw_cfg file into. If the\r
58 fw_cfg file contents are not NUL-terminated, then\r
59 a NUL character is placed into Buffer after the\r
60 fw_cfg file contents.\r
61\r
62 On error, Buffer is indeterminate.\r
63\r
64 @retval RETURN_SUCCESS Buffer has been populated with the fw_cfg file\r
65 contents. Buffer is NUL-terminated regardless\r
66 of whether the fw_cfg file itself was\r
67 NUL-terminated.\r
68\r
69 @retval RETURN_UNSUPPORTED Firmware configuration is unavailable.\r
70\r
71 @retval RETURN_PROTOCOL_ERROR The fw_cfg file does not fit into Buffer.\r
72 (This is considered a QEMU configuration\r
73 error; BufferSize is considered authoritative\r
74 for the contents of the fw_cfg file identified\r
75 by FileName.)\r
76\r
77 @retval RETURN_PROTOCOL_ERROR The fw_cfg file contents are not themselves\r
78 NUL-terminated, and an extra NUL byte does not\r
79 fit into Buffer. (Again a QEMU configuration\r
80 error.)\r
81\r
82 @return Error codes propagated from\r
83 QemuFwCfgFindFile().\r
84**/\r
85STATIC\r
86RETURN_STATUS\r
87QemuFwCfgGetAsString (\r
88 IN CONST CHAR8 *FileName,\r
89 IN OUT UINTN *BufferSize,\r
90 OUT CHAR8 *Buffer\r
91 )\r
92{\r
93 RETURN_STATUS Status;\r
94 FIRMWARE_CONFIG_ITEM FwCfgItem;\r
95 UINTN FwCfgSize;\r
96\r
97 if (!QemuFwCfgIsAvailable ()) {\r
98 return RETURN_UNSUPPORTED;\r
99 }\r
100\r
101 Status = QemuFwCfgFindFile (FileName, &FwCfgItem, &FwCfgSize);\r
102 if (RETURN_ERROR (Status)) {\r
103 return Status;\r
104 }\r
105 if (FwCfgSize > *BufferSize) {\r
106 return RETURN_PROTOCOL_ERROR;\r
107 }\r
108\r
109 QemuFwCfgSelectItem (FwCfgItem);\r
110 QemuFwCfgReadBytes (FwCfgSize, Buffer);\r
111\r
112 //\r
113 // If Buffer is already NUL-terminated due to fw_cfg contents, we're done.\r
114 //\r
115 if (FwCfgSize > 0 && Buffer[FwCfgSize - 1] == '\0') {\r
116 *BufferSize = FwCfgSize;\r
117 return RETURN_SUCCESS;\r
118 }\r
119 //\r
120 // Otherwise, append a NUL byte to Buffer (if we have room for it).\r
121 //\r
122 if (FwCfgSize == *BufferSize) {\r
123 return RETURN_PROTOCOL_ERROR;\r
124 }\r
125 Buffer[FwCfgSize] = '\0';\r
126 *BufferSize = FwCfgSize + 1;\r
127 return RETURN_SUCCESS;\r
128}\r
129\r
130/**\r
131 Remove a trailing \r\n or \n sequence from a string.\r
132\r
133 @param[in,out] BufferSize On input, the number of bytes in Buffer, including\r
134 the terminating NUL.\r
135\r
136 On output, the adjusted string size (including the\r
137 terminating NUL), after stripping the \r\n or \n\r
138 suffix.\r
139\r
140 @param[in,out] Buffer The NUL-terminated string to trim.\r
141**/\r
142STATIC\r
143VOID\r
144StripNewline (\r
145 IN OUT UINTN *BufferSize,\r
146 IN OUT CHAR8 *Buffer\r
147 )\r
148{\r
149 UINTN InSize, OutSize;\r
150\r
151 InSize = *BufferSize;\r
152 OutSize = InSize;\r
153\r
154 if (InSize >= 3 &&\r
155 Buffer[InSize - 3] == '\r' && Buffer[InSize - 2] == '\n') {\r
156 OutSize = InSize - 2;\r
157 } else if (InSize >= 2 && Buffer[InSize - 2] == '\n') {\r
158 OutSize = InSize - 1;\r
159 }\r
160\r
161 if (OutSize < InSize) {\r
162 Buffer[OutSize - 1] = '\0';\r
163 *BufferSize = OutSize;\r
164 }\r
165}\r
166\r
167/**\r
168 Read the fw_cfg file identified by FileName as a string into a small array\r
169 with automatic storage duration, using QemuFwCfgGetAsString(). Parse the\r
170 string as a UINT64. Perform a range-check on the parsed value.\r
171\r
172 @param[in] FileName The name of the fw_cfg file to look up and parse.\r
173\r
174 @param[in] ParseAsHex If TRUE, call BaseLib's AsciiStrHexToUint64S() for\r
175 parsing the fw_cfg file.\r
176\r
177 If FALSE, call BaseLib's AsciiStrDecimalToUint64S()\r
178 for parsing the fw_cfg file.\r
179\r
180 @param[in] Limit The inclusive upper bound on the parsed UINT64 value.\r
181\r
182 @param[out] Value On success, Value has been parsed with the BaseLib\r
183 function determined by ParseAsHex, and has been\r
184 range-checked against [0, Limit].\r
185\r
186 On failure, Value is not changed.\r
187\r
188 @retval RETURN_SUCCESS Parsing successful. Value has been set.\r
189\r
190 @retval RETURN_UNSUPPORTED Firmware configuration is unavailable.\r
191\r
192 @retval RETURN_PROTOCOL_ERROR Parsing failed. Value has not been changed.\r
193\r
194 @retval RETURN_PROTOCOL_ERROR Parsing succeeded, but the result does not fit\r
195 in the [0, Limit] range. Value has not been\r
196 changed.\r
197\r
198 @return Error codes propagated from\r
199 QemuFwCfgFindFile() and from the BaseLib\r
200 function selected by ParseAsHex. Value has not\r
201 been changed.\r
202**/\r
203STATIC\r
204RETURN_STATUS\r
205QemuFwCfgParseUint64WithLimit (\r
206 IN CONST CHAR8 *FileName,\r
207 IN BOOLEAN ParseAsHex,\r
208 IN UINT64 Limit,\r
209 OUT UINT64 *Value\r
210 )\r
211{\r
212 UINTN Uint64StringSize;\r
213 CHAR8 Uint64String[UINT64_STRING_MAX_SIZE + CRLF_LENGTH];\r
214 RETURN_STATUS Status;\r
215 CHAR8 *EndPointer;\r
216 UINT64 Uint64;\r
217\r
218 Uint64StringSize = sizeof Uint64String;\r
219 Status = QemuFwCfgGetAsString (FileName, &Uint64StringSize, Uint64String);\r
220 if (RETURN_ERROR (Status)) {\r
221 return Status;\r
222 }\r
223\r
224 StripNewline (&Uint64StringSize, Uint64String);\r
225\r
226 if (ParseAsHex) {\r
227 Status = AsciiStrHexToUint64S (Uint64String, &EndPointer, &Uint64);\r
228 } else {\r
229 Status = AsciiStrDecimalToUint64S (Uint64String, &EndPointer, &Uint64);\r
230 }\r
231 if (RETURN_ERROR (Status)) {\r
232 return Status;\r
233 }\r
234\r
235 //\r
236 // Report a wire protocol error if the subject sequence is empty, or trailing\r
237 // garbage is present, or Limit is not honored.\r
238 //\r
239 if (EndPointer == Uint64String || *EndPointer != '\0' || Uint64 > Limit) {\r
240 return RETURN_PROTOCOL_ERROR;\r
241 }\r
242\r
243 *Value = Uint64;\r
244 return RETURN_SUCCESS;\r
245}\r
246\r
247//\r
248// Public functions.\r
249//\r
250\r
251RETURN_STATUS\r
252EFIAPI\r
253QemuFwCfgSimpleParserInit (\r
254 VOID\r
255 )\r
256{\r
257 //\r
258 // Do nothing, just participate in constructor dependency ordering.\r
259 //\r
260 return RETURN_SUCCESS;\r
261}\r
262\r
263RETURN_STATUS\r
264EFIAPI\r
265QemuFwCfgParseBool (\r
266 IN CONST CHAR8 *FileName,\r
267 OUT BOOLEAN *Value\r
268 )\r
269{\r
270 UINTN BoolStringSize;\r
271 CHAR8 BoolString[BOOL_STRING_MAX_SIZE + CRLF_LENGTH];\r
272 RETURN_STATUS Status;\r
273 UINTN Idx;\r
274\r
275 BoolStringSize = sizeof BoolString;\r
276 Status = QemuFwCfgGetAsString (FileName, &BoolStringSize, BoolString);\r
277 if (RETURN_ERROR (Status)) {\r
278 return Status;\r
279 }\r
280\r
281 StripNewline (&BoolStringSize, BoolString);\r
282\r
283 for (Idx = 0; Idx < ARRAY_SIZE (mTrueString); ++Idx) {\r
284 if (AsciiStriCmp (BoolString, mTrueString[Idx]) == 0) {\r
285 *Value = TRUE;\r
286 return RETURN_SUCCESS;\r
287 }\r
288 }\r
289\r
290 for (Idx = 0; Idx < ARRAY_SIZE (mFalseString); ++Idx) {\r
291 if (AsciiStriCmp (BoolString, mFalseString[Idx]) == 0) {\r
292 *Value = FALSE;\r
293 return RETURN_SUCCESS;\r
294 }\r
295 }\r
296\r
297 return RETURN_PROTOCOL_ERROR;\r
298}\r
299\r
300RETURN_STATUS\r
301EFIAPI\r
302QemuFwCfgParseUint8 (\r
303 IN CONST CHAR8 *FileName,\r
304 IN BOOLEAN ParseAsHex,\r
305 OUT UINT8 *Value\r
306 )\r
307{\r
308 RETURN_STATUS Status;\r
309 UINT64 Uint64;\r
310\r
311 Status = QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UINT8,\r
312 &Uint64);\r
313 if (RETURN_ERROR (Status)) {\r
314 return Status;\r
315 }\r
316 *Value = (UINT8)Uint64;\r
317 return RETURN_SUCCESS;\r
318}\r
319\r
320RETURN_STATUS\r
321EFIAPI\r
322QemuFwCfgParseUint16 (\r
323 IN CONST CHAR8 *FileName,\r
324 IN BOOLEAN ParseAsHex,\r
325 OUT UINT16 *Value\r
326 )\r
327{\r
328 RETURN_STATUS Status;\r
329 UINT64 Uint64;\r
330\r
331 Status = QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UINT16,\r
332 &Uint64);\r
333 if (RETURN_ERROR (Status)) {\r
334 return Status;\r
335 }\r
336 *Value = (UINT16)Uint64;\r
337 return RETURN_SUCCESS;\r
338}\r
339\r
340RETURN_STATUS\r
341EFIAPI\r
342QemuFwCfgParseUint32 (\r
343 IN CONST CHAR8 *FileName,\r
344 IN BOOLEAN ParseAsHex,\r
345 OUT UINT32 *Value\r
346 )\r
347{\r
348 RETURN_STATUS Status;\r
349 UINT64 Uint64;\r
350\r
351 Status = QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UINT32,\r
352 &Uint64);\r
353 if (RETURN_ERROR (Status)) {\r
354 return Status;\r
355 }\r
356 *Value = (UINT32)Uint64;\r
357 return RETURN_SUCCESS;\r
358}\r
359\r
360RETURN_STATUS\r
361EFIAPI\r
362QemuFwCfgParseUint64 (\r
363 IN CONST CHAR8 *FileName,\r
364 IN BOOLEAN ParseAsHex,\r
365 OUT UINT64 *Value\r
366 )\r
367{\r
368 RETURN_STATUS Status;\r
369 UINT64 Uint64;\r
370\r
371 Status = QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UINT64,\r
372 &Uint64);\r
373 if (RETURN_ERROR (Status)) {\r
374 return Status;\r
375 }\r
376 *Value = Uint64;\r
377 return RETURN_SUCCESS;\r
378}\r
379\r
380RETURN_STATUS\r
381EFIAPI\r
382QemuFwCfgParseUintn (\r
383 IN CONST CHAR8 *FileName,\r
384 IN BOOLEAN ParseAsHex,\r
385 OUT UINTN *Value\r
386 )\r
387{\r
388 RETURN_STATUS Status;\r
389 UINT64 Uint64;\r
390\r
391 Status = QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UINTN,\r
392 &Uint64);\r
393 if (RETURN_ERROR (Status)) {\r
394 return Status;\r
395 }\r
396 *Value = (UINTN)Uint64;\r
397 return RETURN_SUCCESS;\r
398}\r