]> git.proxmox.com Git - mirror_edk2.git/blame - SignedCapsulePkg/Library/IniParsingLib/IniParsingLib.c
SignedCapsulePkg: Apply uncrustify changes
[mirror_edk2.git] / SignedCapsulePkg / Library / IniParsingLib / IniParsingLib.c
CommitLineData
384070fd
JY
1/** @file\r
2 This library parses the INI configuration file.\r
3\r
4 The INI file format is:\r
5 ================\r
6 [SectionName]\r
7 EntryName=EntryValue\r
8 ================\r
9\r
10 Where:\r
11 1) SectionName is an ASCII string. The valid format is [A-Za-z0-9_]+\r
12 2) EntryName is an ASCII string. The valid format is [A-Za-z0-9_]+\r
13 3) EntryValue can be:\r
14 3.1) an ASCII String. The valid format is [A-Za-z0-9_]+\r
15 3.2) a GUID. The valid format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where x is [A-Fa-f0-9]\r
16 3.3) a decimal value. The valid format is [0-9]+\r
582b6cdd 17 3.4) a hexadecimal value. The valid format is 0x[A-Fa-f0-9]+\r
384070fd
JY
18 4) '#' or ';' can be used as comment at anywhere.\r
19 5) TAB(0x20) or SPACE(0x9) can be used as separator.\r
20 6) LF(\n, 0xA) or CR(\r, 0xD) can be used as line break.\r
21\r
22 Caution: This module requires additional review when modified.\r
23 This driver will have external input - INI data file.\r
24\r
25 OpenIniFile(), PreProcessDataFile(), ProfileGetSection(), ProfileGetEntry()\r
26 will receive untrusted input and do basic validation.\r
27\r
bf717f10 28 Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
384070fd 29\r
fbf06957 30 SPDX-License-Identifier: BSD-2-Clause-Patent\r
384070fd
JY
31\r
32**/\r
33\r
34#include <Uefi.h>\r
35#include <Library/BaseLib.h>\r
36#include <Library/BaseMemoryLib.h>\r
37#include <Library/DebugLib.h>\r
38#include <Library/MemoryAllocationLib.h>\r
39\r
b8786489
MK
40#define IS_HYPHEN(a) ((a) == '-')\r
41#define IS_NULL(a) ((a) == '\0')\r
384070fd
JY
42\r
43// This is default allocation. Reallocation will happen if it is not enough.\r
b8786489 44#define MAX_LINE_LENGTH 512\r
384070fd 45\r
67c09dd5
DB
46typedef struct _INI_SECTION_ITEM SECTION_ITEM;\r
47struct _INI_SECTION_ITEM {\r
b8786489
MK
48 CHAR8 *PtrSection;\r
49 UINTN SecNameLen;\r
50 CHAR8 *PtrEntry;\r
51 CHAR8 *PtrValue;\r
52 SECTION_ITEM *PtrNext;\r
384070fd
JY
53};\r
54\r
67c09dd5
DB
55typedef struct _INI_COMMENT_LINE COMMENT_LINE;\r
56struct _INI_COMMENT_LINE {\r
b8786489
MK
57 CHAR8 *PtrComment;\r
58 COMMENT_LINE *PtrNext;\r
384070fd
JY
59};\r
60\r
61typedef struct {\r
b8786489
MK
62 SECTION_ITEM *SectionHead;\r
63 COMMENT_LINE *CommentHead;\r
384070fd
JY
64} INI_PARSING_LIB_CONTEXT;\r
65\r
66/**\r
67 Return if the digital char is valid.\r
68\r
69 @param[in] DigitalChar The digital char to be checked.\r
70 @param[in] IncludeHex If it include HEX char.\r
71\r
72 @retval TRUE The digital char is valid.\r
73 @retval FALSE The digital char is invalid.\r
74**/\r
75BOOLEAN\r
76IsValidDigitalChar (\r
77 IN CHAR8 DigitalChar,\r
78 IN BOOLEAN IncludeHex\r
79 )\r
80{\r
b8786489 81 if ((DigitalChar >= '0') && (DigitalChar <= '9')) {\r
384070fd
JY
82 return TRUE;\r
83 }\r
b8786489 84\r
384070fd 85 if (IncludeHex) {\r
b8786489 86 if ((DigitalChar >= 'a') && (DigitalChar <= 'f')) {\r
384070fd
JY
87 return TRUE;\r
88 }\r
b8786489
MK
89\r
90 if ((DigitalChar >= 'A') && (DigitalChar <= 'F')) {\r
384070fd
JY
91 return TRUE;\r
92 }\r
93 }\r
b8786489 94\r
384070fd
JY
95 return FALSE;\r
96}\r
97\r
98/**\r
99 Return if the name char is valid.\r
100\r
101 @param[in] NameChar The name char to be checked.\r
102\r
103 @retval TRUE The name char is valid.\r
104 @retval FALSE The name char is invalid.\r
105**/\r
106BOOLEAN\r
107IsValidNameChar (\r
108 IN CHAR8 NameChar\r
109 )\r
110{\r
b8786489 111 if ((NameChar >= 'a') && (NameChar <= 'z')) {\r
384070fd
JY
112 return TRUE;\r
113 }\r
b8786489
MK
114\r
115 if ((NameChar >= 'A') && (NameChar <= 'Z')) {\r
384070fd
JY
116 return TRUE;\r
117 }\r
b8786489
MK
118\r
119 if ((NameChar >= '0') && (NameChar <= '9')) {\r
384070fd
JY
120 return TRUE;\r
121 }\r
b8786489 122\r
384070fd
JY
123 if (NameChar == '_') {\r
124 return TRUE;\r
125 }\r
b8786489 126\r
384070fd
JY
127 return FALSE;\r
128}\r
129\r
130/**\r
131 Return if the digital string is valid.\r
132\r
133 @param[in] Digital The digital to be checked.\r
134 @param[in] Length The length of digital string in bytes.\r
135 @param[in] IncludeHex If it include HEX char.\r
136\r
137 @retval TRUE The digital string is valid.\r
138 @retval FALSE The digital string is invalid.\r
139**/\r
140BOOLEAN\r
141IsValidDigital (\r
142 IN CHAR8 *Digital,\r
143 IN UINTN Length,\r
144 IN BOOLEAN IncludeHex\r
145 )\r
146{\r
147 UINTN Index;\r
b8786489 148\r
384070fd 149 for (Index = 0; Index < Length; Index++) {\r
b8786489 150 if (!IsValidDigitalChar (Digital[Index], IncludeHex)) {\r
384070fd
JY
151 return FALSE;\r
152 }\r
153 }\r
b8786489 154\r
384070fd
JY
155 return TRUE;\r
156}\r
157\r
158/**\r
159 Return if the decimal string is valid.\r
160\r
161 @param[in] Decimal The decimal string to be checked.\r
162 @param[in] Length The length of decimal string in bytes.\r
163\r
164 @retval TRUE The decimal string is valid.\r
165 @retval FALSE The decimal string is invalid.\r
166**/\r
167BOOLEAN\r
168IsValidDecimalString (\r
169 IN CHAR8 *Decimal,\r
170 IN UINTN Length\r
171 )\r
172{\r
b8786489 173 return IsValidDigital (Decimal, Length, FALSE);\r
384070fd
JY
174}\r
175\r
176/**\r
582b6cdd 177 Return if the hexadecimal string is valid.\r
384070fd 178\r
582b6cdd
AC
179 @param[in] Hex The hexadecimal string to be checked.\r
180 @param[in] Length The length of hexadecimal string in bytes.\r
384070fd 181\r
582b6cdd
AC
182 @retval TRUE The hexadecimal string is valid.\r
183 @retval FALSE The hexadecimal string is invalid.\r
384070fd
JY
184**/\r
185BOOLEAN\r
186IsValidHexString (\r
187 IN CHAR8 *Hex,\r
188 IN UINTN Length\r
189 )\r
190{\r
191 if (Length <= 2) {\r
192 return FALSE;\r
193 }\r
b8786489 194\r
384070fd
JY
195 if (Hex[0] != '0') {\r
196 return FALSE;\r
197 }\r
b8786489
MK
198\r
199 if ((Hex[1] != 'x') && (Hex[1] != 'X')) {\r
384070fd
JY
200 return FALSE;\r
201 }\r
b8786489
MK
202\r
203 return IsValidDigital (&Hex[2], Length - 2, TRUE);\r
384070fd
JY
204}\r
205\r
206/**\r
207 Return if the name string is valid.\r
208\r
209 @param[in] Name The name to be checked.\r
210 @param[in] Length The length of name string in bytes.\r
211\r
212 @retval TRUE The name string is valid.\r
213 @retval FALSE The name string is invalid.\r
214**/\r
215BOOLEAN\r
216IsValidName (\r
217 IN CHAR8 *Name,\r
218 IN UINTN Length\r
219 )\r
220{\r
221 UINTN Index;\r
b8786489 222\r
384070fd 223 for (Index = 0; Index < Length; Index++) {\r
b8786489 224 if (!IsValidNameChar (Name[Index])) {\r
384070fd
JY
225 return FALSE;\r
226 }\r
227 }\r
b8786489 228\r
384070fd
JY
229 return TRUE;\r
230}\r
231\r
232/**\r
233 Return if the value string is valid GUID.\r
234\r
235 @param[in] Value The value to be checked.\r
236 @param[in] Length The length of value string in bytes.\r
237\r
238 @retval TRUE The value string is valid GUID.\r
239 @retval FALSE The value string is invalid GUID.\r
240**/\r
241BOOLEAN\r
242IsValidGuid (\r
243 IN CHAR8 *Value,\r
244 IN UINTN Length\r
245 )\r
246{\r
b8786489 247 if (Length != sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") - 1) {\r
384070fd
JY
248 return FALSE;\r
249 }\r
b8786489
MK
250\r
251 if (!IS_HYPHEN (Value[8])) {\r
384070fd
JY
252 return FALSE;\r
253 }\r
b8786489
MK
254\r
255 if (!IS_HYPHEN (Value[13])) {\r
384070fd
JY
256 return FALSE;\r
257 }\r
b8786489
MK
258\r
259 if (!IS_HYPHEN (Value[18])) {\r
384070fd
JY
260 return FALSE;\r
261 }\r
b8786489
MK
262\r
263 if (!IS_HYPHEN (Value[23])) {\r
384070fd
JY
264 return FALSE;\r
265 }\r
b8786489
MK
266\r
267 if (!IsValidDigital (&Value[0], 8, TRUE)) {\r
384070fd
JY
268 return FALSE;\r
269 }\r
b8786489
MK
270\r
271 if (!IsValidDigital (&Value[9], 4, TRUE)) {\r
384070fd
JY
272 return FALSE;\r
273 }\r
b8786489
MK
274\r
275 if (!IsValidDigital (&Value[14], 4, TRUE)) {\r
384070fd
JY
276 return FALSE;\r
277 }\r
b8786489
MK
278\r
279 if (!IsValidDigital (&Value[19], 4, TRUE)) {\r
384070fd
JY
280 return FALSE;\r
281 }\r
b8786489
MK
282\r
283 if (!IsValidDigital (&Value[24], 12, TRUE)) {\r
384070fd
JY
284 return FALSE;\r
285 }\r
b8786489 286\r
384070fd
JY
287 return TRUE;\r
288}\r
289\r
290/**\r
291 Return if the value string is valid.\r
292\r
293 @param[in] Value The value to be checked.\r
294 @param[in] Length The length of value string in bytes.\r
295\r
296 @retval TRUE The name string is valid.\r
297 @retval FALSE The name string is invalid.\r
298**/\r
299BOOLEAN\r
300IsValidValue (\r
301 IN CHAR8 *Value,\r
302 IN UINTN Length\r
303 )\r
304{\r
b8786489 305 if (IsValidName (Value, Length) || IsValidGuid (Value, Length)) {\r
384070fd
JY
306 return TRUE;\r
307 }\r
b8786489 308\r
384070fd
JY
309 return FALSE;\r
310}\r
311\r
312/**\r
313 Dump an INI config file context.\r
314\r
315 @param[in] Context INI Config file context.\r
316**/\r
317VOID\r
318DumpIniSection (\r
319 IN VOID *Context\r
320 )\r
321{\r
b8786489
MK
322 INI_PARSING_LIB_CONTEXT *IniContext;\r
323 SECTION_ITEM *PtrSection;\r
324 SECTION_ITEM *Section;\r
384070fd
JY
325\r
326 if (Context == NULL) {\r
327 return;\r
328 }\r
329\r
330 IniContext = Context;\r
b8786489 331 Section = IniContext->SectionHead;\r
384070fd
JY
332\r
333 while (Section != NULL) {\r
334 PtrSection = Section;\r
b8786489 335 Section = Section->PtrNext;\r
384070fd 336 if (PtrSection->PtrSection != NULL) {\r
b8786489 337 DEBUG ((DEBUG_VERBOSE, "Section - %a\n", PtrSection->PtrSection));\r
384070fd 338 }\r
b8786489 339\r
384070fd
JY
340 if (PtrSection->PtrEntry != NULL) {\r
341 DEBUG ((DEBUG_VERBOSE, " Entry - %a\n", PtrSection->PtrEntry));\r
342 }\r
b8786489 343\r
384070fd 344 if (PtrSection->PtrValue != NULL) {\r
b8786489 345 DEBUG ((DEBUG_VERBOSE, " Value - %a\n", PtrSection->PtrValue));\r
384070fd
JY
346 }\r
347 }\r
348}\r
349\r
350/**\r
351 Copy one line data from buffer data to the line buffer.\r
352\r
353 @param[in] Buffer Buffer data.\r
354 @param[in] BufferSize Buffer Size.\r
355 @param[in, out] LineBuffer Line buffer to store the found line data.\r
356 @param[in, out] LineSize On input, size of the input line buffer.\r
357 On output, size of the actual line buffer.\r
358\r
359 @retval EFI_BUFFER_TOO_SMALL The size of input line buffer is not enough.\r
360 @retval EFI_SUCCESS Copy line data into the line buffer.\r
361\r
362**/\r
363EFI_STATUS\r
364ProfileGetLine (\r
b8786489
MK
365 IN UINT8 *Buffer,\r
366 IN UINTN BufferSize,\r
367 IN OUT UINT8 *LineBuffer,\r
368 IN OUT UINTN *LineSize\r
384070fd
JY
369 )\r
370{\r
b8786489
MK
371 UINTN Length;\r
372 UINT8 *PtrBuf;\r
373 UINTN PtrEnd;\r
384070fd 374\r
b8786489
MK
375 PtrBuf = Buffer;\r
376 PtrEnd = (UINTN)Buffer + BufferSize;\r
384070fd
JY
377\r
378 //\r
379 // 0x0D indicates a line break. Otherwise there is no line break\r
380 //\r
381 while ((UINTN)PtrBuf < PtrEnd) {\r
b8786489 382 if ((*PtrBuf == 0x0D) || (*PtrBuf == 0x0A)) {\r
384070fd
JY
383 break;\r
384 }\r
b8786489 385\r
384070fd
JY
386 PtrBuf++;\r
387 }\r
388\r
389 if ((UINTN)PtrBuf >= (PtrEnd - 1)) {\r
390 //\r
391 // The buffer ends without any line break\r
392 // or it is the last character of the buffer\r
393 //\r
b8786489 394 Length = BufferSize;\r
384070fd
JY
395 } else if (*(PtrBuf + 1) == 0x0A) {\r
396 //\r
397 // Further check if a 0x0A follows. If yes, count 0xA\r
398 //\r
b8786489 399 Length = (UINTN)PtrBuf - (UINTN)Buffer + 2;\r
384070fd 400 } else {\r
b8786489 401 Length = (UINTN)PtrBuf - (UINTN)Buffer + 1;\r
384070fd
JY
402 }\r
403\r
404 if (Length > (*LineSize)) {\r
405 *LineSize = Length;\r
406 return EFI_BUFFER_TOO_SMALL;\r
407 }\r
408\r
409 SetMem (LineBuffer, *LineSize, 0x0);\r
b8786489 410 *LineSize = Length;\r
384070fd
JY
411 CopyMem (LineBuffer, Buffer, Length);\r
412\r
413 return EFI_SUCCESS;\r
414}\r
415\r
416/**\r
417 Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail.\r
418\r
582b6cdd 419 @param[in, out] Buffer On input, buffer data to be trimmed.\r
384070fd
JY
420 On output, the trimmed buffer.\r
421 @param[in, out] BufferSize On input, size of original buffer data.\r
422 On output, size of the trimmed buffer.\r
423\r
424**/\r
425VOID\r
426ProfileTrim (\r
b8786489
MK
427 IN OUT UINT8 *Buffer,\r
428 IN OUT UINTN *BufferSize\r
384070fd
JY
429 )\r
430{\r
b8786489
MK
431 UINTN Length;\r
432 UINT8 *PtrBuf;\r
433 UINT8 *PtrEnd;\r
384070fd
JY
434\r
435 if (*BufferSize == 0) {\r
436 return;\r
437 }\r
438\r
439 //\r
440 // Trim the tail first, include CR, LF, TAB, and SPACE.\r
441 //\r
b8786489
MK
442 Length = *BufferSize;\r
443 PtrBuf = (UINT8 *)((UINTN)Buffer + Length - 1);\r
384070fd 444 while (PtrBuf >= Buffer) {\r
b8786489
MK
445 if ( (*PtrBuf != 0x0D) && (*PtrBuf != 0x0A)\r
446 && (*PtrBuf != 0x20) && (*PtrBuf != 0x09))\r
447 {\r
384070fd
JY
448 break;\r
449 }\r
b8786489
MK
450\r
451 PtrBuf--;\r
384070fd
JY
452 }\r
453\r
454 //\r
455 // all spaces, a blank line, return directly;\r
456 //\r
457 if (PtrBuf < Buffer) {\r
b8786489 458 *BufferSize = 0;\r
384070fd
JY
459 return;\r
460 }\r
461\r
b8786489
MK
462 Length = (UINTN)PtrBuf - (UINTN)Buffer + 1;\r
463 PtrEnd = PtrBuf;\r
464 PtrBuf = Buffer;\r
384070fd
JY
465\r
466 //\r
467 // Now skip the heading CR, LF, TAB and SPACE\r
468 //\r
469 while (PtrBuf <= PtrEnd) {\r
b8786489
MK
470 if ( (*PtrBuf != 0x0D) && (*PtrBuf != 0x0A)\r
471 && (*PtrBuf != 0x20) && (*PtrBuf != 0x09))\r
472 {\r
384070fd
JY
473 break;\r
474 }\r
b8786489 475\r
384070fd
JY
476 PtrBuf++;\r
477 }\r
478\r
479 //\r
480 // If no heading CR, LF, TAB or SPACE, directly return\r
481 //\r
482 if (PtrBuf == Buffer) {\r
b8786489 483 *BufferSize = Length;\r
384070fd
JY
484 return;\r
485 }\r
486\r
b8786489 487 *BufferSize = (UINTN)PtrEnd - (UINTN)PtrBuf + 1;\r
384070fd
JY
488\r
489 //\r
490 // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE.\r
491 // Now move out all these characters.\r
492 //\r
493 while (PtrBuf <= PtrEnd) {\r
b8786489 494 *Buffer = *PtrBuf;\r
384070fd
JY
495 Buffer++;\r
496 PtrBuf++;\r
497 }\r
498\r
499 return;\r
500}\r
501\r
502/**\r
503 Insert new comment item into comment head.\r
504\r
505 @param[in] Buffer Comment buffer to be added.\r
506 @param[in] BufferSize Size of comment buffer.\r
507 @param[in, out] CommentHead Comment Item head entry.\r
508\r
509 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
510 @retval EFI_SUCCESS New comment item is inserted.\r
511\r
512**/\r
513EFI_STATUS\r
514ProfileGetComments (\r
b8786489
MK
515 IN UINT8 *Buffer,\r
516 IN UINTN BufferSize,\r
517 IN OUT COMMENT_LINE **CommentHead\r
384070fd
JY
518 )\r
519{\r
b8786489 520 COMMENT_LINE *CommentItem;\r
384070fd
JY
521\r
522 CommentItem = NULL;\r
523 CommentItem = AllocatePool (sizeof (COMMENT_LINE));\r
524 if (CommentItem == NULL) {\r
525 return EFI_OUT_OF_RESOURCES;\r
526 }\r
527\r
b8786489
MK
528 CommentItem->PtrNext = *CommentHead;\r
529 *CommentHead = CommentItem;\r
384070fd
JY
530\r
531 //\r
532 // Add a trailing '\0'\r
533 //\r
534 CommentItem->PtrComment = AllocatePool (BufferSize + 1);\r
535 if (CommentItem->PtrComment == NULL) {\r
536 FreePool (CommentItem);\r
537 return EFI_OUT_OF_RESOURCES;\r
538 }\r
b8786489 539\r
384070fd
JY
540 CopyMem (CommentItem->PtrComment, Buffer, BufferSize);\r
541 *(CommentItem->PtrComment + BufferSize) = '\0';\r
542\r
543 return EFI_SUCCESS;\r
544}\r
545\r
546/**\r
547 Add new section item into Section head.\r
548\r
549 @param[in] Buffer Section item data buffer.\r
550 @param[in] BufferSize Size of section item.\r
551 @param[in, out] SectionHead Section item head entry.\r
552\r
553 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
554 @retval EFI_SUCCESS Section item is NULL or Section item is added.\r
555\r
556**/\r
557EFI_STATUS\r
558ProfileGetSection (\r
b8786489
MK
559 IN UINT8 *Buffer,\r
560 IN UINTN BufferSize,\r
561 IN OUT SECTION_ITEM **SectionHead\r
384070fd
JY
562 )\r
563{\r
b8786489
MK
564 SECTION_ITEM *SectionItem;\r
565 UINTN Length;\r
566 UINT8 *PtrBuf;\r
567 UINT8 *PtrEnd;\r
384070fd 568\r
b8786489 569 ASSERT (BufferSize >= 1);\r
384070fd
JY
570 //\r
571 // The first character of Buffer is '[', now we want for ']'\r
572 //\r
b8786489
MK
573 PtrEnd = (UINT8 *)((UINTN)Buffer + BufferSize - 1);\r
574 PtrBuf = (UINT8 *)((UINTN)Buffer + 1);\r
384070fd
JY
575 while (PtrBuf <= PtrEnd) {\r
576 if (*PtrBuf == ']') {\r
577 break;\r
578 }\r
b8786489
MK
579\r
580 PtrBuf++;\r
384070fd 581 }\r
b8786489 582\r
384070fd
JY
583 if (PtrBuf > PtrEnd) {\r
584 //\r
585 // Not found. Invalid line\r
586 //\r
587 return EFI_NOT_FOUND;\r
588 }\r
b8786489 589\r
384070fd
JY
590 if (PtrBuf <= Buffer + 1) {\r
591 // Empty name\r
592 return EFI_NOT_FOUND;\r
593 }\r
594\r
595 //\r
596 // excluding the heading '[' and tailing ']'\r
597 //\r
b8786489 598 Length = PtrBuf - Buffer - 1;\r
384070fd
JY
599 ProfileTrim (\r
600 Buffer + 1,\r
601 &Length\r
b8786489 602 );\r
384070fd
JY
603\r
604 //\r
605 // Invalid line if the section name is null\r
606 //\r
607 if (Length == 0) {\r
608 return EFI_NOT_FOUND;\r
609 }\r
610\r
b8786489 611 if (!IsValidName ((CHAR8 *)Buffer + 1, Length)) {\r
384070fd
JY
612 return EFI_INVALID_PARAMETER;\r
613 }\r
614\r
615 SectionItem = AllocatePool (sizeof (SECTION_ITEM));\r
616 if (SectionItem == NULL) {\r
617 return EFI_OUT_OF_RESOURCES;\r
618 }\r
619\r
620 SectionItem->PtrSection = NULL;\r
621 SectionItem->SecNameLen = Length;\r
622 SectionItem->PtrEntry = NULL;\r
623 SectionItem->PtrValue = NULL;\r
624 SectionItem->PtrNext = *SectionHead;\r
625 *SectionHead = SectionItem;\r
626\r
627 //\r
628 // Add a trailing '\0'\r
629 //\r
630 SectionItem->PtrSection = AllocatePool (Length + 1);\r
631 if (SectionItem->PtrSection == NULL) {\r
632 return EFI_OUT_OF_RESOURCES;\r
633 }\r
634\r
635 //\r
636 // excluding the heading '['\r
637 //\r
638 CopyMem (SectionItem->PtrSection, Buffer + 1, Length);\r
639 *(SectionItem->PtrSection + Length) = '\0';\r
640\r
641 return EFI_SUCCESS;\r
642}\r
643\r
644/**\r
645 Add new section entry and entry value into Section head.\r
646\r
647 @param[in] Buffer Section entry data buffer.\r
648 @param[in] BufferSize Size of section entry.\r
649 @param[in, out] SectionHead Section item head entry.\r
650\r
651 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
652 @retval EFI_SUCCESS Section entry is added.\r
653 @retval EFI_NOT_FOUND Section entry is not found.\r
654 @retval EFI_INVALID_PARAMETER Section entry is invalid.\r
655\r
656**/\r
657EFI_STATUS\r
658ProfileGetEntry (\r
b8786489
MK
659 IN UINT8 *Buffer,\r
660 IN UINTN BufferSize,\r
661 IN OUT SECTION_ITEM **SectionHead\r
384070fd
JY
662 )\r
663{\r
b8786489
MK
664 EFI_STATUS Status;\r
665 SECTION_ITEM *SectionItem;\r
666 SECTION_ITEM *PtrSection;\r
667 UINTN Length;\r
668 UINT8 *PtrBuf;\r
669 UINT8 *PtrEnd;\r
384070fd 670\r
b8786489
MK
671 Status = EFI_SUCCESS;\r
672 PtrBuf = Buffer;\r
673 PtrEnd = (UINT8 *)((UINTN)Buffer + BufferSize - 1);\r
384070fd
JY
674\r
675 //\r
676 // First search for '='\r
677 //\r
678 while (PtrBuf <= PtrEnd) {\r
679 if (*PtrBuf == '=') {\r
680 break;\r
681 }\r
b8786489 682\r
384070fd
JY
683 PtrBuf++;\r
684 }\r
b8786489 685\r
384070fd
JY
686 if (PtrBuf > PtrEnd) {\r
687 //\r
688 // Not found. Invalid line\r
689 //\r
690 return EFI_NOT_FOUND;\r
691 }\r
b8786489 692\r
384070fd
JY
693 if (PtrBuf <= Buffer) {\r
694 // Empty name\r
695 return EFI_NOT_FOUND;\r
696 }\r
697\r
698 //\r
699 // excluding the tailing '='\r
700 //\r
b8786489 701 Length = PtrBuf - Buffer;\r
384070fd
JY
702 ProfileTrim (\r
703 Buffer,\r
704 &Length\r
b8786489 705 );\r
384070fd
JY
706\r
707 //\r
708 // Invalid line if the entry name is null\r
709 //\r
710 if (Length == 0) {\r
711 return EFI_NOT_FOUND;\r
712 }\r
713\r
b8786489 714 if (!IsValidName ((CHAR8 *)Buffer, Length)) {\r
384070fd
JY
715 return EFI_INVALID_PARAMETER;\r
716 }\r
717\r
718 //\r
719 // Omit this line if no section header has been found before\r
720 //\r
721 if (*SectionHead == NULL) {\r
722 return Status;\r
723 }\r
b8786489
MK
724\r
725 PtrSection = *SectionHead;\r
384070fd
JY
726\r
727 SectionItem = AllocatePool (sizeof (SECTION_ITEM));\r
728 if (SectionItem == NULL) {\r
729 return EFI_OUT_OF_RESOURCES;\r
730 }\r
731\r
732 SectionItem->PtrSection = NULL;\r
733 SectionItem->PtrEntry = NULL;\r
734 SectionItem->PtrValue = NULL;\r
735 SectionItem->SecNameLen = PtrSection->SecNameLen;\r
736 SectionItem->PtrNext = *SectionHead;\r
737 *SectionHead = SectionItem;\r
738\r
739 //\r
740 // SectionName, add a trailing '\0'\r
741 //\r
742 SectionItem->PtrSection = AllocatePool (PtrSection->SecNameLen + 1);\r
743 if (SectionItem->PtrSection == NULL) {\r
744 return EFI_OUT_OF_RESOURCES;\r
745 }\r
b8786489 746\r
384070fd
JY
747 CopyMem (SectionItem->PtrSection, PtrSection->PtrSection, PtrSection->SecNameLen + 1);\r
748\r
749 //\r
750 // EntryName, add a trailing '\0'\r
751 //\r
752 SectionItem->PtrEntry = AllocatePool (Length + 1);\r
753 if (SectionItem->PtrEntry == NULL) {\r
b8786489 754 FreePool (SectionItem->PtrSection);\r
384070fd
JY
755 return EFI_OUT_OF_RESOURCES;\r
756 }\r
b8786489 757\r
384070fd
JY
758 CopyMem (SectionItem->PtrEntry, Buffer, Length);\r
759 *(SectionItem->PtrEntry + Length) = '\0';\r
760\r
761 //\r
762 // Next search for '#' or ';'\r
763 //\r
b8786489
MK
764 PtrBuf = PtrBuf + 1;\r
765 Buffer = PtrBuf;\r
384070fd 766 while (PtrBuf <= PtrEnd) {\r
b8786489 767 if ((*PtrBuf == '#') || (*PtrBuf == ';')) {\r
384070fd
JY
768 break;\r
769 }\r
b8786489 770\r
384070fd
JY
771 PtrBuf++;\r
772 }\r
b8786489 773\r
384070fd
JY
774 if (PtrBuf <= Buffer) {\r
775 // Empty name\r
b8786489
MK
776 FreePool (SectionItem->PtrEntry);\r
777 FreePool (SectionItem->PtrSection);\r
384070fd
JY
778 return EFI_NOT_FOUND;\r
779 }\r
b8786489
MK
780\r
781 Length = PtrBuf - Buffer;\r
384070fd
JY
782 ProfileTrim (\r
783 Buffer,\r
784 &Length\r
b8786489 785 );\r
384070fd
JY
786\r
787 //\r
788 // Invalid line if the entry value is null\r
789 //\r
790 if (Length == 0) {\r
b8786489
MK
791 FreePool (SectionItem->PtrEntry);\r
792 FreePool (SectionItem->PtrSection);\r
384070fd
JY
793 return EFI_NOT_FOUND;\r
794 }\r
795\r
b8786489
MK
796 if (!IsValidValue ((CHAR8 *)Buffer, Length)) {\r
797 FreePool (SectionItem->PtrEntry);\r
798 FreePool (SectionItem->PtrSection);\r
384070fd
JY
799 return EFI_INVALID_PARAMETER;\r
800 }\r
801\r
802 //\r
803 // EntryValue, add a trailing '\0'\r
804 //\r
805 SectionItem->PtrValue = AllocatePool (Length + 1);\r
806 if (SectionItem->PtrValue == NULL) {\r
b8786489
MK
807 FreePool (SectionItem->PtrEntry);\r
808 FreePool (SectionItem->PtrSection);\r
384070fd
JY
809 return EFI_OUT_OF_RESOURCES;\r
810 }\r
b8786489 811\r
384070fd
JY
812 CopyMem (SectionItem->PtrValue, Buffer, Length);\r
813 *(SectionItem->PtrValue + Length) = '\0';\r
814\r
815 return EFI_SUCCESS;\r
816}\r
817\r
818/**\r
819 Free all comment entry and section entry.\r
820\r
821 @param[in] Section Section entry list.\r
822 @param[in] Comment Comment entry list.\r
823\r
824**/\r
825VOID\r
826FreeAllList (\r
b8786489
MK
827 IN SECTION_ITEM *Section,\r
828 IN COMMENT_LINE *Comment\r
384070fd
JY
829 )\r
830{\r
b8786489
MK
831 SECTION_ITEM *PtrSection;\r
832 COMMENT_LINE *PtrComment;\r
384070fd
JY
833\r
834 while (Section != NULL) {\r
b8786489
MK
835 PtrSection = Section;\r
836 Section = Section->PtrNext;\r
384070fd
JY
837 if (PtrSection->PtrEntry != NULL) {\r
838 FreePool (PtrSection->PtrEntry);\r
839 }\r
b8786489 840\r
384070fd
JY
841 if (PtrSection->PtrSection != NULL) {\r
842 FreePool (PtrSection->PtrSection);\r
843 }\r
b8786489 844\r
384070fd
JY
845 if (PtrSection->PtrValue != NULL) {\r
846 FreePool (PtrSection->PtrValue);\r
847 }\r
b8786489 848\r
384070fd
JY
849 FreePool (PtrSection);\r
850 }\r
851\r
852 while (Comment != NULL) {\r
b8786489
MK
853 PtrComment = Comment;\r
854 Comment = Comment->PtrNext;\r
384070fd
JY
855 if (PtrComment->PtrComment != NULL) {\r
856 FreePool (PtrComment->PtrComment);\r
857 }\r
b8786489 858\r
384070fd
JY
859 FreePool (PtrComment);\r
860 }\r
861\r
862 return;\r
863}\r
864\r
865/**\r
866 Get section entry value.\r
867\r
868 @param[in] Section Section entry list.\r
869 @param[in] SectionName Section name.\r
870 @param[in] EntryName Section entry name.\r
871 @param[out] EntryValue Point to the got entry value.\r
872\r
873 @retval EFI_NOT_FOUND Section is not found.\r
874 @retval EFI_SUCCESS Section entry value is got.\r
875\r
876**/\r
877EFI_STATUS\r
878UpdateGetProfileString (\r
b8786489
MK
879 IN SECTION_ITEM *Section,\r
880 IN CHAR8 *SectionName,\r
881 IN CHAR8 *EntryName,\r
882 OUT CHAR8 **EntryValue\r
384070fd
JY
883 )\r
884{\r
b8786489 885 *EntryValue = NULL;\r
384070fd
JY
886\r
887 while (Section != NULL) {\r
b8786489 888 if (AsciiStrCmp ((CONST CHAR8 *)Section->PtrSection, (CONST CHAR8 *)SectionName) == 0) {\r
384070fd 889 if (Section->PtrEntry != NULL) {\r
b8786489 890 if (AsciiStrCmp ((CONST CHAR8 *)Section->PtrEntry, (CONST CHAR8 *)EntryName) == 0) {\r
384070fd
JY
891 break;\r
892 }\r
893 }\r
894 }\r
b8786489
MK
895\r
896 Section = Section->PtrNext;\r
384070fd
JY
897 }\r
898\r
899 if (Section == NULL) {\r
900 return EFI_NOT_FOUND;\r
901 }\r
902\r
b8786489 903 *EntryValue = Section->PtrValue;\r
384070fd
JY
904\r
905 return EFI_SUCCESS;\r
906}\r
907\r
384070fd
JY
908/**\r
909 Pre process config data buffer into Section entry list and Comment entry list.\r
910\r
911 @param[in] DataBuffer Config raw file buffer.\r
912 @param[in] BufferSize Size of raw buffer.\r
913 @param[in, out] SectionHead Pointer to the section entry list.\r
914 @param[in, out] CommentHead Pointer to the comment entry list.\r
915\r
916 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
917 @retval EFI_SUCCESS Config data buffer is preprocessed.\r
918 @retval EFI_NOT_FOUND Config data buffer is invalid, because Section or Entry is not found.\r
919 @retval EFI_INVALID_PARAMETER Config data buffer is invalid, because Section or Entry is invalid.\r
920\r
921**/\r
922EFI_STATUS\r
923PreProcessDataFile (\r
b8786489
MK
924 IN UINT8 *DataBuffer,\r
925 IN UINTN BufferSize,\r
926 IN OUT SECTION_ITEM **SectionHead,\r
927 IN OUT COMMENT_LINE **CommentHead\r
384070fd
JY
928 )\r
929{\r
b8786489
MK
930 EFI_STATUS Status;\r
931 CHAR8 *Source;\r
932 CHAR8 *CurrentPtr;\r
933 CHAR8 *BufferEnd;\r
934 CHAR8 *PtrLine;\r
935 UINTN LineLength;\r
936 UINTN SourceLength;\r
937 UINTN MaxLineLength;\r
938\r
939 *SectionHead = NULL;\r
940 *CommentHead = NULL;\r
941 BufferEnd = (CHAR8 *)((UINTN)DataBuffer + BufferSize);\r
942 CurrentPtr = (CHAR8 *)DataBuffer;\r
943 MaxLineLength = MAX_LINE_LENGTH;\r
944 Status = EFI_SUCCESS;\r
384070fd
JY
945\r
946 PtrLine = AllocatePool (MaxLineLength);\r
947 if (PtrLine == NULL) {\r
948 return EFI_OUT_OF_RESOURCES;\r
949 }\r
950\r
951 while (CurrentPtr < BufferEnd) {\r
b8786489
MK
952 Source = CurrentPtr;\r
953 SourceLength = (UINTN)BufferEnd - (UINTN)CurrentPtr;\r
954 LineLength = MaxLineLength;\r
384070fd
JY
955 //\r
956 // With the assumption that line length is less than 512\r
957 // characters. Otherwise BUFFER_TOO_SMALL will be returned.\r
958 //\r
b8786489
MK
959 Status = ProfileGetLine (\r
960 (UINT8 *)Source,\r
961 SourceLength,\r
962 (UINT8 *)PtrLine,\r
963 &LineLength\r
964 );\r
384070fd
JY
965 if (EFI_ERROR (Status)) {\r
966 if (Status == EFI_BUFFER_TOO_SMALL) {\r
967 //\r
968 // If buffer too small, re-allocate the buffer according\r
969 // to the returned LineLength and try again.\r
970 //\r
971 FreePool (PtrLine);\r
b8786489 972 PtrLine = NULL;\r
384070fd
JY
973 PtrLine = AllocatePool (LineLength);\r
974 if (PtrLine == NULL) {\r
b8786489 975 Status = EFI_OUT_OF_RESOURCES;\r
384070fd
JY
976 break;\r
977 }\r
b8786489
MK
978\r
979 SourceLength = LineLength;\r
980 Status = ProfileGetLine (\r
981 (UINT8 *)Source,\r
982 SourceLength,\r
983 (UINT8 *)PtrLine,\r
984 &LineLength\r
985 );\r
384070fd
JY
986 if (EFI_ERROR (Status)) {\r
987 break;\r
988 }\r
b8786489
MK
989\r
990 MaxLineLength = LineLength;\r
384070fd
JY
991 } else {\r
992 break;\r
993 }\r
994 }\r
b8786489
MK
995\r
996 CurrentPtr = (CHAR8 *)((UINTN)CurrentPtr + LineLength);\r
384070fd
JY
997\r
998 //\r
999 // Line got. Trim the line before processing it.\r
1000 //\r
1001 ProfileTrim (\r
b8786489 1002 (UINT8 *)PtrLine,\r
384070fd 1003 &LineLength\r
b8786489 1004 );\r
384070fd
JY
1005\r
1006 //\r
1007 // Blank line\r
1008 //\r
1009 if (LineLength == 0) {\r
1010 continue;\r
1011 }\r
1012\r
b8786489
MK
1013 if ((PtrLine[0] == '#') || (PtrLine[0] == ';')) {\r
1014 Status = ProfileGetComments (\r
1015 (UINT8 *)PtrLine,\r
1016 LineLength,\r
1017 CommentHead\r
1018 );\r
384070fd 1019 } else if (PtrLine[0] == '[') {\r
b8786489
MK
1020 Status = ProfileGetSection (\r
1021 (UINT8 *)PtrLine,\r
1022 LineLength,\r
1023 SectionHead\r
1024 );\r
384070fd 1025 } else {\r
b8786489
MK
1026 Status = ProfileGetEntry (\r
1027 (UINT8 *)PtrLine,\r
1028 LineLength,\r
1029 SectionHead\r
1030 );\r
384070fd
JY
1031 }\r
1032\r
1033 if (EFI_ERROR (Status)) {\r
1034 break;\r
1035 }\r
1036 }\r
1037\r
1038 //\r
1039 // Free buffer\r
1040 //\r
1041 FreePool (PtrLine);\r
1042\r
1043 return Status;\r
1044}\r
1045\r
1046/**\r
1047 Open an INI config file and return a context.\r
1048\r
1049 @param[in] DataBuffer Config raw file buffer.\r
1050 @param[in] BufferSize Size of raw buffer.\r
1051\r
1052 @return Config data buffer is opened and context is returned.\r
1053 @retval NULL No enough memory is allocated.\r
1054 @retval NULL Config data buffer is invalid.\r
1055**/\r
1056VOID *\r
1057EFIAPI\r
1058OpenIniFile (\r
b8786489
MK
1059 IN UINT8 *DataBuffer,\r
1060 IN UINTN BufferSize\r
384070fd
JY
1061 )\r
1062{\r
b8786489
MK
1063 EFI_STATUS Status;\r
1064 INI_PARSING_LIB_CONTEXT *IniContext;\r
384070fd 1065\r
b8786489 1066 if ((DataBuffer == NULL) || (BufferSize == 0)) {\r
384070fd
JY
1067 return NULL;\r
1068 }\r
1069\r
b8786489 1070 IniContext = AllocateZeroPool (sizeof (INI_PARSING_LIB_CONTEXT));\r
384070fd
JY
1071 if (IniContext == NULL) {\r
1072 return NULL;\r
1073 }\r
1074\r
1075 //\r
1076 // First process the data buffer and get all sections and entries\r
1077 //\r
1078 Status = PreProcessDataFile (\r
1079 DataBuffer,\r
1080 BufferSize,\r
1081 &IniContext->SectionHead,\r
1082 &IniContext->CommentHead\r
1083 );\r
b8786489
MK
1084 if (EFI_ERROR (Status)) {\r
1085 FreePool (IniContext);\r
384070fd
JY
1086 return NULL;\r
1087 }\r
b8786489 1088\r
384070fd 1089 DEBUG_CODE_BEGIN ();\r
b8786489 1090 DumpIniSection (IniContext);\r
384070fd
JY
1091 DEBUG_CODE_END ();\r
1092 return IniContext;\r
1093}\r
1094\r
1095/**\r
1096 Get section entry string value.\r
1097\r
1098 @param[in] Context INI Config file context.\r
1099 @param[in] SectionName Section name.\r
1100 @param[in] EntryName Section entry name.\r
1101 @param[out] EntryValue Point to the got entry string value.\r
1102\r
1103 @retval EFI_SUCCESS Section entry string value is got.\r
1104 @retval EFI_NOT_FOUND Section is not found.\r
1105**/\r
1106EFI_STATUS\r
1107EFIAPI\r
b8786489
MK
1108GetStringFromDataFile (\r
1109 IN VOID *Context,\r
1110 IN CHAR8 *SectionName,\r
1111 IN CHAR8 *EntryName,\r
1112 OUT CHAR8 **EntryValue\r
384070fd
JY
1113 )\r
1114{\r
b8786489
MK
1115 INI_PARSING_LIB_CONTEXT *IniContext;\r
1116 EFI_STATUS Status;\r
384070fd 1117\r
b8786489 1118 if ((Context == NULL) || (SectionName == NULL) || (EntryName == NULL) || (EntryValue == NULL)) {\r
384070fd
JY
1119 return EFI_INVALID_PARAMETER;\r
1120 }\r
1121\r
1122 IniContext = Context;\r
1123\r
b8786489
MK
1124 *EntryValue = NULL;\r
1125 Status = UpdateGetProfileString (\r
1126 IniContext->SectionHead,\r
1127 SectionName,\r
1128 EntryName,\r
1129 EntryValue\r
1130 );\r
384070fd
JY
1131 return Status;\r
1132}\r
1133\r
1134/**\r
1135 Get section entry GUID value.\r
1136\r
1137 @param[in] Context INI Config file context.\r
1138 @param[in] SectionName Section name.\r
1139 @param[in] EntryName Section entry name.\r
1140 @param[out] Guid Point to the got GUID value.\r
1141\r
1142 @retval EFI_SUCCESS Section entry GUID value is got.\r
1143 @retval EFI_NOT_FOUND Section is not found.\r
1144**/\r
1145EFI_STATUS\r
1146EFIAPI\r
1147GetGuidFromDataFile (\r
b8786489
MK
1148 IN VOID *Context,\r
1149 IN CHAR8 *SectionName,\r
1150 IN CHAR8 *EntryName,\r
1151 OUT EFI_GUID *Guid\r
384070fd
JY
1152 )\r
1153{\r
b8786489
MK
1154 CHAR8 *Value;\r
1155 EFI_STATUS Status;\r
1156 RETURN_STATUS RStatus;\r
384070fd 1157\r
b8786489 1158 if ((Context == NULL) || (SectionName == NULL) || (EntryName == NULL) || (Guid == NULL)) {\r
384070fd
JY
1159 return EFI_INVALID_PARAMETER;\r
1160 }\r
1161\r
b8786489 1162 Status = GetStringFromDataFile (\r
384070fd
JY
1163 Context,\r
1164 SectionName,\r
1165 EntryName,\r
1166 &Value\r
1167 );\r
b8786489 1168 if (EFI_ERROR (Status)) {\r
384070fd
JY
1169 return EFI_NOT_FOUND;\r
1170 }\r
b8786489 1171\r
cf2ddcf1 1172 ASSERT (Value != NULL);\r
58974b6e
RN
1173 RStatus = AsciiStrToGuid (Value, Guid);\r
1174 if (RETURN_ERROR (RStatus) || (Value[GUID_STRING_LENGTH] != '\0')) {\r
384070fd
JY
1175 return EFI_NOT_FOUND;\r
1176 }\r
b8786489 1177\r
384070fd
JY
1178 return EFI_SUCCESS;\r
1179}\r
1180\r
1181/**\r
1182 Get section entry decimal UINTN value.\r
1183\r
1184 @param[in] Context INI Config file context.\r
1185 @param[in] SectionName Section name.\r
1186 @param[in] EntryName Section entry name.\r
1187 @param[out] Data Point to the got decimal UINTN value.\r
1188\r
1189 @retval EFI_SUCCESS Section entry decimal UINTN value is got.\r
1190 @retval EFI_NOT_FOUND Section is not found.\r
1191**/\r
1192EFI_STATUS\r
1193EFIAPI\r
1194GetDecimalUintnFromDataFile (\r
b8786489
MK
1195 IN VOID *Context,\r
1196 IN CHAR8 *SectionName,\r
1197 IN CHAR8 *EntryName,\r
1198 OUT UINTN *Data\r
384070fd
JY
1199 )\r
1200{\r
b8786489
MK
1201 CHAR8 *Value;\r
1202 EFI_STATUS Status;\r
384070fd 1203\r
b8786489 1204 if ((Context == NULL) || (SectionName == NULL) || (EntryName == NULL) || (Data == NULL)) {\r
384070fd
JY
1205 return EFI_INVALID_PARAMETER;\r
1206 }\r
1207\r
b8786489 1208 Status = GetStringFromDataFile (\r
384070fd
JY
1209 Context,\r
1210 SectionName,\r
1211 EntryName,\r
1212 &Value\r
1213 );\r
b8786489 1214 if (EFI_ERROR (Status)) {\r
384070fd
JY
1215 return EFI_NOT_FOUND;\r
1216 }\r
b8786489 1217\r
cf2ddcf1 1218 ASSERT (Value != NULL);\r
b8786489 1219 if (!IsValidDecimalString (Value, AsciiStrLen (Value))) {\r
384070fd
JY
1220 return EFI_NOT_FOUND;\r
1221 }\r
b8786489
MK
1222\r
1223 *Data = AsciiStrDecimalToUintn (Value);\r
384070fd
JY
1224 return EFI_SUCCESS;\r
1225}\r
1226\r
1227/**\r
582b6cdd 1228 Get section entry hexadecimal UINTN value.\r
384070fd
JY
1229\r
1230 @param[in] Context INI Config file context.\r
1231 @param[in] SectionName Section name.\r
1232 @param[in] EntryName Section entry name.\r
582b6cdd 1233 @param[out] Data Point to the got hexadecimal UINTN value.\r
384070fd 1234\r
582b6cdd 1235 @retval EFI_SUCCESS Section entry hexadecimal UINTN value is got.\r
384070fd
JY
1236 @retval EFI_NOT_FOUND Section is not found.\r
1237**/\r
1238EFI_STATUS\r
1239EFIAPI\r
1240GetHexUintnFromDataFile (\r
b8786489
MK
1241 IN VOID *Context,\r
1242 IN CHAR8 *SectionName,\r
1243 IN CHAR8 *EntryName,\r
1244 OUT UINTN *Data\r
384070fd
JY
1245 )\r
1246{\r
b8786489
MK
1247 CHAR8 *Value;\r
1248 EFI_STATUS Status;\r
384070fd 1249\r
b8786489 1250 if ((Context == NULL) || (SectionName == NULL) || (EntryName == NULL) || (Data == NULL)) {\r
384070fd
JY
1251 return EFI_INVALID_PARAMETER;\r
1252 }\r
1253\r
b8786489 1254 Status = GetStringFromDataFile (\r
384070fd
JY
1255 Context,\r
1256 SectionName,\r
1257 EntryName,\r
1258 &Value\r
1259 );\r
b8786489 1260 if (EFI_ERROR (Status)) {\r
384070fd
JY
1261 return EFI_NOT_FOUND;\r
1262 }\r
b8786489 1263\r
cf2ddcf1 1264 ASSERT (Value != NULL);\r
b8786489 1265 if (!IsValidHexString (Value, AsciiStrLen (Value))) {\r
384070fd
JY
1266 return EFI_NOT_FOUND;\r
1267 }\r
b8786489
MK
1268\r
1269 *Data = AsciiStrHexToUintn (Value);\r
384070fd
JY
1270 return EFI_SUCCESS;\r
1271}\r
1272\r
1273/**\r
582b6cdd 1274 Get section entry hexadecimal UINT64 value.\r
384070fd
JY
1275\r
1276 @param[in] Context INI Config file context.\r
1277 @param[in] SectionName Section name.\r
1278 @param[in] EntryName Section entry name.\r
582b6cdd 1279 @param[out] Data Point to the got hexadecimal UINT64 value.\r
384070fd 1280\r
582b6cdd 1281 @retval EFI_SUCCESS Section entry hexadecimal UINT64 value is got.\r
384070fd
JY
1282 @retval EFI_NOT_FOUND Section is not found.\r
1283**/\r
1284EFI_STATUS\r
1285EFIAPI\r
1286GetHexUint64FromDataFile (\r
b8786489
MK
1287 IN VOID *Context,\r
1288 IN CHAR8 *SectionName,\r
1289 IN CHAR8 *EntryName,\r
1290 OUT UINT64 *Data\r
384070fd
JY
1291 )\r
1292{\r
b8786489
MK
1293 CHAR8 *Value;\r
1294 EFI_STATUS Status;\r
384070fd 1295\r
b8786489 1296 if ((Context == NULL) || (SectionName == NULL) || (EntryName == NULL) || (Data == NULL)) {\r
384070fd
JY
1297 return EFI_INVALID_PARAMETER;\r
1298 }\r
1299\r
b8786489 1300 Status = GetStringFromDataFile (\r
384070fd
JY
1301 Context,\r
1302 SectionName,\r
1303 EntryName,\r
1304 &Value\r
1305 );\r
b8786489 1306 if (EFI_ERROR (Status)) {\r
384070fd
JY
1307 return EFI_NOT_FOUND;\r
1308 }\r
b8786489 1309\r
cf2ddcf1 1310 ASSERT (Value != NULL);\r
b8786489 1311 if (!IsValidHexString (Value, AsciiStrLen (Value))) {\r
384070fd
JY
1312 return EFI_NOT_FOUND;\r
1313 }\r
b8786489
MK
1314\r
1315 *Data = AsciiStrHexToUint64 (Value);\r
384070fd
JY
1316 return EFI_SUCCESS;\r
1317}\r
1318\r
1319/**\r
1320 Close an INI config file and free the context.\r
1321\r
1322 @param[in] Context INI Config file context.\r
1323**/\r
1324VOID\r
1325EFIAPI\r
1326CloseIniFile (\r
b8786489 1327 IN VOID *Context\r
384070fd
JY
1328 )\r
1329{\r
b8786489 1330 INI_PARSING_LIB_CONTEXT *IniContext;\r
384070fd
JY
1331\r
1332 if (Context == NULL) {\r
b8786489 1333 return;\r
384070fd
JY
1334 }\r
1335\r
1336 IniContext = Context;\r
b8786489 1337 FreeAllList (IniContext->SectionHead, IniContext->CommentHead);\r
384070fd
JY
1338\r
1339 return;\r
1340}\r