]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParser.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / Library / QemuFwCfgSimpleParserLib / QemuFwCfgSimpleParser.c
... / ...
CommitLineData
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\r
106 if (FwCfgSize > *BufferSize) {\r
107 return RETURN_PROTOCOL_ERROR;\r
108 }\r
109\r
110 QemuFwCfgSelectItem (FwCfgItem);\r
111 QemuFwCfgReadBytes (FwCfgSize, Buffer);\r
112\r
113 //\r
114 // If Buffer is already NUL-terminated due to fw_cfg contents, we're done.\r
115 //\r
116 if ((FwCfgSize > 0) && (Buffer[FwCfgSize - 1] == '\0')) {\r
117 *BufferSize = FwCfgSize;\r
118 return RETURN_SUCCESS;\r
119 }\r
120\r
121 //\r
122 // Otherwise, append a NUL byte to Buffer (if we have room for it).\r
123 //\r
124 if (FwCfgSize == *BufferSize) {\r
125 return RETURN_PROTOCOL_ERROR;\r
126 }\r
127\r
128 Buffer[FwCfgSize] = '\0';\r
129 *BufferSize = FwCfgSize + 1;\r
130 return RETURN_SUCCESS;\r
131}\r
132\r
133/**\r
134 Remove a trailing \r\n or \n sequence from a string.\r
135\r
136 @param[in,out] BufferSize On input, the number of bytes in Buffer, including\r
137 the terminating NUL.\r
138\r
139 On output, the adjusted string size (including the\r
140 terminating NUL), after stripping the \r\n or \n\r
141 suffix.\r
142\r
143 @param[in,out] Buffer The NUL-terminated string to trim.\r
144**/\r
145STATIC\r
146VOID\r
147StripNewline (\r
148 IN OUT UINTN *BufferSize,\r
149 IN OUT CHAR8 *Buffer\r
150 )\r
151{\r
152 UINTN InSize, OutSize;\r
153\r
154 InSize = *BufferSize;\r
155 OutSize = InSize;\r
156\r
157 if ((InSize >= 3) &&\r
158 (Buffer[InSize - 3] == '\r') && (Buffer[InSize - 2] == '\n'))\r
159 {\r
160 OutSize = InSize - 2;\r
161 } else if ((InSize >= 2) && (Buffer[InSize - 2] == '\n')) {\r
162 OutSize = InSize - 1;\r
163 }\r
164\r
165 if (OutSize < InSize) {\r
166 Buffer[OutSize - 1] = '\0';\r
167 *BufferSize = OutSize;\r
168 }\r
169}\r
170\r
171/**\r
172 Read the fw_cfg file identified by FileName as a string into a small array\r
173 with automatic storage duration, using QemuFwCfgGetAsString(). Parse the\r
174 string as a UINT64. Perform a range-check on the parsed value.\r
175\r
176 @param[in] FileName The name of the fw_cfg file to look up and parse.\r
177\r
178 @param[in] ParseAsHex If TRUE, call BaseLib's AsciiStrHexToUint64S() for\r
179 parsing the fw_cfg file.\r
180\r
181 If FALSE, call BaseLib's AsciiStrDecimalToUint64S()\r
182 for parsing the fw_cfg file.\r
183\r
184 @param[in] Limit The inclusive upper bound on the parsed UINT64 value.\r
185\r
186 @param[out] Value On success, Value has been parsed with the BaseLib\r
187 function determined by ParseAsHex, and has been\r
188 range-checked against [0, Limit].\r
189\r
190 On failure, Value is not changed.\r
191\r
192 @retval RETURN_SUCCESS Parsing successful. Value has been set.\r
193\r
194 @retval RETURN_UNSUPPORTED Firmware configuration is unavailable.\r
195\r
196 @retval RETURN_PROTOCOL_ERROR Parsing failed. Value has not been changed.\r
197\r
198 @retval RETURN_PROTOCOL_ERROR Parsing succeeded, but the result does not fit\r
199 in the [0, Limit] range. Value has not been\r
200 changed.\r
201\r
202 @return Error codes propagated from\r
203 QemuFwCfgFindFile() and from the BaseLib\r
204 function selected by ParseAsHex. Value has not\r
205 been changed.\r
206**/\r
207STATIC\r
208RETURN_STATUS\r
209QemuFwCfgParseUint64WithLimit (\r
210 IN CONST CHAR8 *FileName,\r
211 IN BOOLEAN ParseAsHex,\r
212 IN UINT64 Limit,\r
213 OUT UINT64 *Value\r
214 )\r
215{\r
216 UINTN Uint64StringSize;\r
217 CHAR8 Uint64String[UINT64_STRING_MAX_SIZE + CRLF_LENGTH];\r
218 RETURN_STATUS Status;\r
219 CHAR8 *EndPointer;\r
220 UINT64 Uint64;\r
221\r
222 Uint64StringSize = sizeof Uint64String;\r
223 Status = QemuFwCfgGetAsString (FileName, &Uint64StringSize, Uint64String);\r
224 if (RETURN_ERROR (Status)) {\r
225 return Status;\r
226 }\r
227\r
228 StripNewline (&Uint64StringSize, Uint64String);\r
229\r
230 if (ParseAsHex) {\r
231 Status = AsciiStrHexToUint64S (Uint64String, &EndPointer, &Uint64);\r
232 } else {\r
233 Status = AsciiStrDecimalToUint64S (Uint64String, &EndPointer, &Uint64);\r
234 }\r
235\r
236 if (RETURN_ERROR (Status)) {\r
237 return Status;\r
238 }\r
239\r
240 //\r
241 // Report a wire protocol error if the subject sequence is empty, or trailing\r
242 // garbage is present, or Limit is not honored.\r
243 //\r
244 if ((EndPointer == Uint64String) || (*EndPointer != '\0') || (Uint64 > Limit)) {\r
245 return RETURN_PROTOCOL_ERROR;\r
246 }\r
247\r
248 *Value = Uint64;\r
249 return RETURN_SUCCESS;\r
250}\r
251\r
252//\r
253// Public functions.\r
254//\r
255\r
256RETURN_STATUS\r
257EFIAPI\r
258QemuFwCfgSimpleParserInit (\r
259 VOID\r
260 )\r
261{\r
262 //\r
263 // Do nothing, just participate in constructor dependency ordering.\r
264 //\r
265 return RETURN_SUCCESS;\r
266}\r
267\r
268RETURN_STATUS\r
269EFIAPI\r
270QemuFwCfgParseBool (\r
271 IN CONST CHAR8 *FileName,\r
272 OUT BOOLEAN *Value\r
273 )\r
274{\r
275 UINTN BoolStringSize;\r
276 CHAR8 BoolString[BOOL_STRING_MAX_SIZE + CRLF_LENGTH];\r
277 RETURN_STATUS Status;\r
278 UINTN Idx;\r
279\r
280 BoolStringSize = sizeof BoolString;\r
281 Status = QemuFwCfgGetAsString (FileName, &BoolStringSize, BoolString);\r
282 if (RETURN_ERROR (Status)) {\r
283 return Status;\r
284 }\r
285\r
286 StripNewline (&BoolStringSize, BoolString);\r
287\r
288 for (Idx = 0; Idx < ARRAY_SIZE (mTrueString); ++Idx) {\r
289 if (AsciiStriCmp (BoolString, mTrueString[Idx]) == 0) {\r
290 *Value = TRUE;\r
291 return RETURN_SUCCESS;\r
292 }\r
293 }\r
294\r
295 for (Idx = 0; Idx < ARRAY_SIZE (mFalseString); ++Idx) {\r
296 if (AsciiStriCmp (BoolString, mFalseString[Idx]) == 0) {\r
297 *Value = FALSE;\r
298 return RETURN_SUCCESS;\r
299 }\r
300 }\r
301\r
302 return RETURN_PROTOCOL_ERROR;\r
303}\r
304\r
305RETURN_STATUS\r
306EFIAPI\r
307QemuFwCfgParseUint8 (\r
308 IN CONST CHAR8 *FileName,\r
309 IN BOOLEAN ParseAsHex,\r
310 OUT UINT8 *Value\r
311 )\r
312{\r
313 RETURN_STATUS Status;\r
314 UINT64 Uint64;\r
315\r
316 Status = QemuFwCfgParseUint64WithLimit (\r
317 FileName,\r
318 ParseAsHex,\r
319 MAX_UINT8,\r
320 &Uint64\r
321 );\r
322 if (RETURN_ERROR (Status)) {\r
323 return Status;\r
324 }\r
325\r
326 *Value = (UINT8)Uint64;\r
327 return RETURN_SUCCESS;\r
328}\r
329\r
330RETURN_STATUS\r
331EFIAPI\r
332QemuFwCfgParseUint16 (\r
333 IN CONST CHAR8 *FileName,\r
334 IN BOOLEAN ParseAsHex,\r
335 OUT UINT16 *Value\r
336 )\r
337{\r
338 RETURN_STATUS Status;\r
339 UINT64 Uint64;\r
340\r
341 Status = QemuFwCfgParseUint64WithLimit (\r
342 FileName,\r
343 ParseAsHex,\r
344 MAX_UINT16,\r
345 &Uint64\r
346 );\r
347 if (RETURN_ERROR (Status)) {\r
348 return Status;\r
349 }\r
350\r
351 *Value = (UINT16)Uint64;\r
352 return RETURN_SUCCESS;\r
353}\r
354\r
355RETURN_STATUS\r
356EFIAPI\r
357QemuFwCfgParseUint32 (\r
358 IN CONST CHAR8 *FileName,\r
359 IN BOOLEAN ParseAsHex,\r
360 OUT UINT32 *Value\r
361 )\r
362{\r
363 RETURN_STATUS Status;\r
364 UINT64 Uint64;\r
365\r
366 Status = QemuFwCfgParseUint64WithLimit (\r
367 FileName,\r
368 ParseAsHex,\r
369 MAX_UINT32,\r
370 &Uint64\r
371 );\r
372 if (RETURN_ERROR (Status)) {\r
373 return Status;\r
374 }\r
375\r
376 *Value = (UINT32)Uint64;\r
377 return RETURN_SUCCESS;\r
378}\r
379\r
380RETURN_STATUS\r
381EFIAPI\r
382QemuFwCfgParseUint64 (\r
383 IN CONST CHAR8 *FileName,\r
384 IN BOOLEAN ParseAsHex,\r
385 OUT UINT64 *Value\r
386 )\r
387{\r
388 RETURN_STATUS Status;\r
389 UINT64 Uint64;\r
390\r
391 Status = QemuFwCfgParseUint64WithLimit (\r
392 FileName,\r
393 ParseAsHex,\r
394 MAX_UINT64,\r
395 &Uint64\r
396 );\r
397 if (RETURN_ERROR (Status)) {\r
398 return Status;\r
399 }\r
400\r
401 *Value = Uint64;\r
402 return RETURN_SUCCESS;\r
403}\r
404\r
405RETURN_STATUS\r
406EFIAPI\r
407QemuFwCfgParseUintn (\r
408 IN CONST CHAR8 *FileName,\r
409 IN BOOLEAN ParseAsHex,\r
410 OUT UINTN *Value\r
411 )\r
412{\r
413 RETURN_STATUS Status;\r
414 UINT64 Uint64;\r
415\r
416 Status = QemuFwCfgParseUint64WithLimit (\r
417 FileName,\r
418 ParseAsHex,\r
419 MAX_UINTN,\r
420 &Uint64\r
421 );\r
422 if (RETURN_ERROR (Status)) {\r
423 return Status;\r
424 }\r
425\r
426 *Value = (UINTN)Uint64;\r
427 return RETURN_SUCCESS;\r
428}\r