VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParser.c@ 98412

Last change on this file since 98412 was 85718, checked in by vboxsync, 5 years ago

Devices/EFI: Merge edk-stable202005 and make it build, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette