]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / UpdateDriverDxe / ParseUpdateProfile.c
CommitLineData
b2824a8e 1/** @file\r
2 Source file for the component update driver. It parse the update\r
3 configuration file and pass the information to the update driver\r
4 so that the driver can perform updates accordingly.\r
5\r
0a6f4824 6 Copyright (c) 2002 - 2018, Intel Corporation. All rights reserved.<BR>\r
b2824a8e 7\r
c0a00b14 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
b2824a8e 9\r
10**/\r
11\r
12#include "UpdateDriver.h"\r
13\r
14/**\r
15 Copy one line data from buffer data to the line buffer.\r
16\r
17 @param Buffer Buffer data.\r
18 @param BufferSize Buffer Size.\r
19 @param LineBuffer Line buffer to store the found line data.\r
20 @param LineSize On input, size of the input line buffer.\r
21 On output, size of the actual line buffer.\r
22\r
23 @retval EFI_BUFFER_TOO_SMALL The size of input line buffer is not enough.\r
24 @retval EFI_SUCCESS Copy line data into the line buffer.\r
25\r
26**/\r
27EFI_STATUS\r
28ProfileGetLine (\r
29 IN UINT8 *Buffer,\r
30 IN UINTN BufferSize,\r
31 IN OUT UINT8 *LineBuffer,\r
32 IN OUT UINTN *LineSize\r
33 )\r
34{\r
35 UINTN Length;\r
36 UINT8 *PtrBuf;\r
37 UINTN PtrEnd;\r
38\r
39 PtrBuf = Buffer;\r
40 PtrEnd = (UINTN)Buffer + BufferSize;\r
41\r
42 //\r
43 // 0x0D indicates a line break. Otherwise there is no line break\r
44 //\r
45 while ((UINTN)PtrBuf < PtrEnd) {\r
46 if (*PtrBuf == 0x0D) {\r
47 break;\r
48 }\r
49 PtrBuf++;\r
50 }\r
51\r
52 if ((UINTN)PtrBuf >= (PtrEnd - 1)) {\r
53 //\r
54 // The buffer ends without any line break\r
55 // or it is the last character of the buffer\r
56 //\r
57 Length = BufferSize;\r
58 } else if (*(PtrBuf + 1) == 0x0A) {\r
59 //\r
60 // Further check if a 0x0A follows. If yes, count 0xA\r
61 //\r
62 Length = (UINTN) PtrBuf - (UINTN) Buffer + 2;\r
63 } else {\r
64 Length = (UINTN) PtrBuf - (UINTN) Buffer + 1;\r
65 }\r
66\r
67 if (Length > (*LineSize)) {\r
68 *LineSize = Length;\r
69 return EFI_BUFFER_TOO_SMALL;\r
70 }\r
71\r
72 SetMem (LineBuffer, *LineSize, 0x0);\r
73 *LineSize = Length;\r
74 CopyMem (LineBuffer, Buffer, Length);\r
75\r
76 return EFI_SUCCESS;\r
77}\r
78\r
79/**\r
80 Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail.\r
81\r
82 @param Buffer On input, buffer data to be trimed.\r
83 On output, the trimmed buffer.\r
84 @param BufferSize On input, size of original buffer data.\r
85 On output, size of the trimmed buffer.\r
86\r
87**/\r
88VOID\r
89ProfileTrim (\r
90 IN OUT UINT8 *Buffer,\r
91 IN OUT UINTN *BufferSize\r
92 )\r
93{\r
94 UINTN Length;\r
95 UINT8 *PtrBuf;\r
96 UINT8 *PtrEnd;\r
97\r
98 if (*BufferSize == 0) {\r
99 return;\r
100 }\r
101\r
102 //\r
103 // Trim the tail first, include CR, LF, TAB, and SPACE.\r
104 //\r
105 Length = *BufferSize;\r
106 PtrBuf = (UINT8 *) ((UINTN) Buffer + Length - 1);\r
107 while (PtrBuf >= Buffer) {\r
108 if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )\r
109 && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {\r
110 break;\r
111 }\r
112 PtrBuf --;\r
113 }\r
114\r
115 //\r
116 // all spaces, a blank line, return directly;\r
117 //\r
118 if (PtrBuf < Buffer) {\r
119 *BufferSize = 0;\r
120 return;\r
121 }\r
122\r
123 Length = (UINTN)PtrBuf - (UINTN)Buffer + 1;\r
124 PtrEnd = PtrBuf;\r
125 PtrBuf = Buffer;\r
126\r
127 //\r
128 // Now skip the heading CR, LF, TAB and SPACE\r
129 //\r
130 while (PtrBuf <= PtrEnd) {\r
131 if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )\r
132 && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {\r
133 break;\r
134 }\r
135 PtrBuf++;\r
136 }\r
137\r
138 //\r
139 // If no heading CR, LF, TAB or SPACE, directly return\r
140 //\r
141 if (PtrBuf == Buffer) {\r
142 *BufferSize = Length;\r
143 return;\r
144 }\r
145\r
146 *BufferSize = (UINTN)PtrEnd - (UINTN)PtrBuf + 1;\r
147\r
148 //\r
149 // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE.\r
150 // Now move out all these characters.\r
151 //\r
152 while (PtrBuf <= PtrEnd) {\r
153 *Buffer = *PtrBuf;\r
154 Buffer++;\r
155 PtrBuf++;\r
156 }\r
157\r
158 return;\r
159}\r
160\r
161/**\r
162 Insert new comment item into comment head.\r
163\r
164 @param Buffer Comment buffer to be added.\r
165 @param BufferSize Size of comment buffer.\r
166 @param CommentHead Comment Item head entry.\r
167\r
168 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
169 @retval EFI_SUCCESS New comment item is inserted.\r
170\r
171**/\r
172EFI_STATUS\r
173ProfileGetComments (\r
174 IN UINT8 *Buffer,\r
175 IN UINTN BufferSize,\r
176 IN OUT COMMENT_LINE **CommentHead\r
177 )\r
178{\r
179 COMMENT_LINE *CommentItem;\r
180\r
181 CommentItem = NULL;\r
182 CommentItem = AllocatePool (sizeof (COMMENT_LINE));\r
183 if (CommentItem == NULL) {\r
184 return EFI_OUT_OF_RESOURCES;\r
185 }\r
186\r
187 CommentItem->ptrNext = *CommentHead;\r
188 *CommentHead = CommentItem;\r
189\r
190 //\r
191 // Add a trailing '\0'\r
192 //\r
193 CommentItem->ptrComment = AllocatePool (BufferSize + 1);\r
194 if (CommentItem->ptrComment == NULL) {\r
195 FreePool (CommentItem);\r
196 return EFI_OUT_OF_RESOURCES;\r
197 }\r
198 CopyMem (CommentItem->ptrComment, Buffer, BufferSize);\r
199 *(CommentItem->ptrComment + BufferSize) = '\0';\r
200\r
201 return EFI_SUCCESS;\r
202}\r
203\r
204/**\r
205 Add new section item into Section head.\r
206\r
207 @param Buffer Section item data buffer.\r
208 @param BufferSize Size of section item.\r
209 @param SectionHead Section item head entry.\r
210\r
211 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
212 @retval EFI_SUCCESS Section item is NULL or Section item is added.\r
213\r
214**/\r
215EFI_STATUS\r
216ProfileGetSection (\r
217 IN UINT8 *Buffer,\r
218 IN UINTN BufferSize,\r
219 IN OUT SECTION_ITEM **SectionHead\r
220 )\r
221{\r
222 EFI_STATUS Status;\r
223 SECTION_ITEM *SectionItem;\r
224 UINTN Length;\r
225 UINT8 *PtrBuf;\r
226\r
227 Status = EFI_SUCCESS;\r
228 //\r
229 // The first character of Buffer is '[', now we want for ']'\r
230 //\r
231 PtrBuf = (UINT8 *)((UINTN)Buffer + BufferSize - 1);\r
232 while (PtrBuf > Buffer) {\r
233 if (*PtrBuf == ']') {\r
234 break;\r
235 }\r
236 PtrBuf --;\r
237 }\r
238 if (PtrBuf <= Buffer) {\r
239 //\r
240 // Not found. Omit this line\r
241 //\r
242 return Status;\r
243 }\r
244\r
245 //\r
246 // excluding the heading '[' and tailing ']'\r
247 //\r
248 Length = PtrBuf - Buffer - 1;\r
249 ProfileTrim (\r
250 Buffer + 1,\r
251 &Length\r
252 );\r
253\r
254 //\r
255 // omit this line if the section name is null\r
256 //\r
257 if (Length == 0) {\r
258 return Status;\r
259 }\r
260\r
261 SectionItem = AllocatePool (sizeof (SECTION_ITEM));\r
262 if (SectionItem == NULL) {\r
263 return EFI_OUT_OF_RESOURCES;\r
264 }\r
265\r
266 SectionItem->ptrSection = NULL;\r
267 SectionItem->SecNameLen = Length;\r
268 SectionItem->ptrEntry = NULL;\r
269 SectionItem->ptrValue = NULL;\r
270 SectionItem->ptrNext = *SectionHead;\r
271 *SectionHead = SectionItem;\r
272\r
273 //\r
274 // Add a trailing '\0'\r
275 //\r
276 SectionItem->ptrSection = AllocatePool (Length + 1);\r
277 if (SectionItem->ptrSection == NULL) {\r
278 return EFI_OUT_OF_RESOURCES;\r
279 }\r
280\r
281 //\r
282 // excluding the heading '['\r
283 //\r
284 CopyMem (SectionItem->ptrSection, Buffer + 1, Length);\r
285 *(SectionItem->ptrSection + Length) = '\0';\r
286\r
287 return EFI_SUCCESS;\r
288}\r
289\r
290/**\r
291 Add new section entry and entry value into Section head.\r
292\r
293 @param Buffer Section entry data buffer.\r
294 @param BufferSize Size of section entry.\r
295 @param SectionHead Section item head entry.\r
296\r
297 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
298 @retval EFI_SUCCESS Section entry is NULL or Section entry is added.\r
299\r
300**/\r
301EFI_STATUS\r
302ProfileGetEntry (\r
303 IN UINT8 *Buffer,\r
304 IN UINTN BufferSize,\r
305 IN OUT SECTION_ITEM **SectionHead\r
306 )\r
307{\r
308 EFI_STATUS Status;\r
309 SECTION_ITEM *SectionItem;\r
310 SECTION_ITEM *PtrSection;\r
311 UINTN Length;\r
312 UINT8 *PtrBuf;\r
313 UINT8 *PtrEnd;\r
314\r
315 Status = EFI_SUCCESS;\r
316 PtrBuf = Buffer;\r
317 PtrEnd = (UINT8 *) ((UINTN)Buffer + BufferSize - 1);\r
318\r
319 //\r
320 // First search for '='\r
321 //\r
322 while (PtrBuf <= PtrEnd) {\r
323 if (*PtrBuf == '=') {\r
324 break;\r
325 }\r
326 PtrBuf++;\r
327 }\r
328 if (PtrBuf > PtrEnd) {\r
329 //\r
330 // Not found. Omit this line\r
331 //\r
332 return Status;\r
333 }\r
334\r
335 //\r
336 // excluding the tailing '='\r
337 //\r
338 Length = PtrBuf - Buffer;\r
339 ProfileTrim (\r
340 Buffer,\r
341 &Length\r
342 );\r
343\r
344 //\r
345 // Omit this line if the entry name is null\r
346 //\r
347 if (Length == 0) {\r
348 return Status;\r
349 }\r
350\r
351 //\r
352 // Omit this line if no section header has been found before\r
353 //\r
354 if (*SectionHead == NULL) {\r
355 return Status;\r
356 }\r
357 PtrSection = *SectionHead;\r
358\r
359 SectionItem = AllocatePool (sizeof (SECTION_ITEM));\r
360 if (SectionItem == NULL) {\r
361 return EFI_OUT_OF_RESOURCES;\r
362 }\r
363\r
364 SectionItem->ptrSection = NULL;\r
365 SectionItem->ptrEntry = NULL;\r
366 SectionItem->ptrValue = NULL;\r
367 SectionItem->SecNameLen = PtrSection->SecNameLen;\r
368 SectionItem->ptrNext = *SectionHead;\r
369 *SectionHead = SectionItem;\r
370\r
371 //\r
372 // SectionName, add a trailing '\0'\r
373 //\r
374 SectionItem->ptrSection = AllocatePool (PtrSection->SecNameLen + 1);\r
375 if (SectionItem->ptrSection == NULL) {\r
376 return EFI_OUT_OF_RESOURCES;\r
377 }\r
378 CopyMem (SectionItem->ptrSection, PtrSection->ptrSection, PtrSection->SecNameLen + 1);\r
379\r
380 //\r
381 // EntryName, add a trailing '\0'\r
382 //\r
383 SectionItem->ptrEntry = AllocatePool (Length + 1);\r
384 if (SectionItem->ptrEntry == NULL) {\r
385 return EFI_OUT_OF_RESOURCES;\r
386 }\r
387 CopyMem (SectionItem->ptrEntry, Buffer, Length);\r
388 *(SectionItem->ptrEntry + Length) = '\0';\r
389\r
390 //\r
391 // Next search for '#'\r
392 //\r
393 PtrBuf = PtrBuf + 1;\r
394 Buffer = PtrBuf;\r
395 while (PtrBuf <= PtrEnd) {\r
396 if (*PtrBuf == '#') {\r
397 break;\r
398 }\r
399 PtrBuf++;\r
400 }\r
401 Length = PtrBuf - Buffer;\r
402 ProfileTrim (\r
403 Buffer,\r
404 &Length\r
405 );\r
406\r
407 if (Length > 0) {\r
408 //\r
409 // EntryValue, add a trailing '\0'\r
410 //\r
411 SectionItem->ptrValue = AllocatePool (Length + 1);\r
412 if (SectionItem->ptrValue == NULL) {\r
413 return EFI_OUT_OF_RESOURCES;\r
414 }\r
415 CopyMem (SectionItem->ptrValue, Buffer, Length);\r
416 *(SectionItem->ptrValue + Length) = '\0';\r
417 }\r
418\r
419 return EFI_SUCCESS;\r
420}\r
421\r
422/**\r
423 Free all comment entry and section entry.\r
424\r
425 @param Section Section entry list.\r
426 @param Comment Comment entry list.\r
427\r
428**/\r
429VOID\r
430FreeAllList (\r
431 IN SECTION_ITEM *Section,\r
432 IN COMMENT_LINE *Comment\r
433 )\r
434{\r
435 SECTION_ITEM *PtrSection;\r
436 COMMENT_LINE *PtrComment;\r
437\r
438 while (Section != NULL) {\r
439 PtrSection = Section;\r
440 Section = Section->ptrNext;\r
441 if (PtrSection->ptrEntry != NULL) {\r
442 FreePool (PtrSection->ptrEntry);\r
443 }\r
444 if (PtrSection->ptrSection != NULL) {\r
445 FreePool (PtrSection->ptrSection);\r
446 }\r
447 if (PtrSection->ptrValue != NULL) {\r
448 FreePool (PtrSection->ptrValue);\r
449 }\r
450 FreePool (PtrSection);\r
451 }\r
452\r
453 while (Comment != NULL) {\r
454 PtrComment = Comment;\r
455 Comment = Comment->ptrNext;\r
456 if (PtrComment->ptrComment != NULL) {\r
457 FreePool (PtrComment->ptrComment);\r
458 }\r
459 FreePool (PtrComment);\r
460 }\r
461\r
462 return;\r
463}\r
464\r
465/**\r
466 Get section entry value.\r
467\r
468 @param Section Section entry list.\r
469 @param SectionName Section name.\r
470 @param EntryName Section entry name.\r
471 @param EntryValue Point to the got entry value.\r
472\r
473 @retval EFI_NOT_FOUND Section is not found.\r
474 @retval EFI_SUCCESS Section entry value is got.\r
475\r
476**/\r
477EFI_STATUS\r
478UpdateGetProfileString (\r
479 IN SECTION_ITEM *Section,\r
480 IN UINT8 *SectionName,\r
481 IN UINT8 *EntryName,\r
482 OUT UINT8 **EntryValue\r
483 )\r
484{\r
485 *EntryValue = NULL;\r
486\r
487 while (Section != NULL) {\r
488 if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrSection, (CONST CHAR8 *) SectionName) == 0) {\r
489 if (Section->ptrEntry != NULL) {\r
490 if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrEntry, (CONST CHAR8 *) EntryName) == 0) {\r
491 break;\r
492 }\r
493 }\r
494 }\r
495 Section = Section->ptrNext;\r
496 }\r
497\r
498 if (Section == NULL) {\r
499 return EFI_NOT_FOUND;\r
500 }\r
501\r
502 *EntryValue = (UINT8 *) Section->ptrValue;\r
503\r
504 return EFI_SUCCESS;\r
505}\r
506\r
507/**\r
508 Convert the dec or hex ascii string to value.\r
509\r
510 @param Str ascii string to be converted.\r
511\r
512 @return the converted value.\r
513\r
514**/\r
515UINTN\r
516UpdateAtoi (\r
517 IN UINT8 *Str\r
518 )\r
519{\r
520 UINTN Number;\r
521\r
522 Number = 0;\r
523\r
524 //\r
525 // Skip preceeding while spaces\r
526 //\r
527 while (*Str != '\0') {\r
528 if (*Str != 0x20) {\r
529 break;\r
530 }\r
531 Str++;\r
532 }\r
533\r
534 if (*Str == '\0') {\r
535 return Number;\r
536 }\r
537\r
538 //\r
539 // Find whether the string is prefixed by 0x.\r
540 // That is, it should be xtoi or atoi.\r
541 //\r
542 if (*Str == '0') {\r
543 if ((*(Str+1) == 'x' ) || ( *(Str+1) == 'X')) {\r
544 return AsciiStrHexToUintn ((CONST CHAR8 *) Str);\r
545 }\r
546 }\r
547\r
548 while (*Str != '\0') {\r
549 if ((*Str >= '0') && (*Str <= '9')) {\r
550 Number = Number * 10 + *Str - '0';\r
551 } else {\r
552 break;\r
553 }\r
554 Str++;\r
555 }\r
556\r
557 return Number;\r
558}\r
559\r
560/**\r
561 Converts a decimal value to a Null-terminated ascii string.\r
562\r
563 @param Buffer Pointer to the output buffer for the produced Null-terminated\r
564 ASCII string.\r
565 @param Value The 64-bit sgned value to convert to a string.\r
566\r
567 @return The number of ASCII characters in Buffer not including the Null-terminator.\r
568\r
569**/\r
570UINTN\r
571UpdateValueToString (\r
572 IN OUT UINT8 *Buffer,\r
573 IN INT64 Value\r
574 )\r
575{\r
576 UINT8 TempBuffer[30];\r
577 UINT8 *TempStr;\r
578 UINT8 *BufferPtr;\r
579 UINTN Count;\r
580 UINT32 Remainder;\r
581\r
582 TempStr = TempBuffer;\r
583 BufferPtr = Buffer;\r
584 Count = 0;\r
585\r
586 if (Value < 0) {\r
587 *BufferPtr = '-';\r
588 BufferPtr++;\r
589 Value = -Value;\r
590 Count++;\r
591 }\r
592\r
593 do {\r
594 Value = (INT64) DivU64x32Remainder ((UINT64)Value, 10, &Remainder);\r
595 //\r
596 // The first item of TempStr is not occupied. It's kind of flag\r
597 //\r
598 TempStr++;\r
599 Count++;\r
600 *TempStr = (UINT8) ((UINT8)Remainder + '0');\r
601 } while (Value != 0);\r
602\r
603 //\r
604 // Reverse temp string into Buffer.\r
605 //\r
606 while (TempStr != TempBuffer) {\r
607 *BufferPtr = *TempStr;\r
608 BufferPtr++;\r
609 TempStr --;\r
610 }\r
611\r
612 *BufferPtr = 0;\r
613\r
614 return Count;\r
615}\r
616\r
617/**\r
0a6f4824 618 Convert the input value to a ascii string,\r
b2824a8e 619 and concatenates this string to the input string.\r
620\r
621 @param Str Pointer to a Null-terminated ASCII string.\r
622 @param Number The unsgned value to convert to a string.\r
623\r
624**/\r
625VOID\r
626UpdateStrCatNumber (\r
627 IN OUT UINT8 *Str,\r
628 IN UINTN Number\r
629 )\r
630{\r
631 UINTN Count;\r
632\r
633 while (*Str != '\0') {\r
634 Str++;\r
635 }\r
636\r
637 Count = UpdateValueToString (Str, (INT64)Number);\r
638\r
639 *(Str + Count) = '\0';\r
640\r
641 return;\r
642}\r
643\r
644/**\r
645 Convert the input ascii string into GUID value.\r
646\r
647 @param Str Ascii GUID string to be converted.\r
648 @param Guid Pointer to the converted GUID value.\r
649\r
650 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
651 @retval EFI_NOT_FOUND The input ascii string is not a valid GUID format string.\r
652 @retval EFI_SUCCESS GUID value is got.\r
653\r
654**/\r
655EFI_STATUS\r
656UpdateStringToGuid (\r
657 IN UINT8 *Str,\r
658 IN OUT EFI_GUID *Guid\r
659 )\r
660{\r
661 UINT8 *PtrBuffer;\r
662 UINT8 *PtrPosition;\r
663 UINT8 *Buffer;\r
664 UINTN Data;\r
665 UINTN StrLen;\r
666 UINTN Index;\r
667 UINT8 Digits[3];\r
668\r
669 StrLen = AsciiStrLen ((CONST CHAR8 *) Str);\r
c5ad1f86 670 Buffer = AllocateCopyPool (StrLen + 1, Str);\r
b2824a8e 671 if (Buffer == NULL) {\r
672 return EFI_OUT_OF_RESOURCES;\r
673 }\r
b2824a8e 674\r
675 //\r
676 // Data1\r
677 //\r
678 PtrBuffer = Buffer;\r
679 PtrPosition = PtrBuffer;\r
680 while (*PtrBuffer != '\0') {\r
681 if (*PtrBuffer == '-') {\r
682 break;\r
683 }\r
684 PtrBuffer++;\r
685 }\r
686 if (*PtrBuffer == '\0') {\r
687 FreePool (Buffer);\r
688 return EFI_NOT_FOUND;\r
689 }\r
690\r
691 *PtrBuffer = '\0';\r
692 Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);\r
693 Guid->Data1 = (UINT32)Data;\r
694\r
695 //\r
696 // Data2\r
697 //\r
698 PtrBuffer++;\r
699 PtrPosition = PtrBuffer;\r
700 while (*PtrBuffer != '\0') {\r
701 if (*PtrBuffer == '-') {\r
702 break;\r
703 }\r
704 PtrBuffer++;\r
705 }\r
706 if (*PtrBuffer == '\0') {\r
707 FreePool (Buffer);\r
708 return EFI_NOT_FOUND;\r
709 }\r
710 *PtrBuffer = '\0';\r
711 Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);\r
712 Guid->Data2 = (UINT16)Data;\r
713\r
714 //\r
715 // Data3\r
716 //\r
717 PtrBuffer++;\r
718 PtrPosition = PtrBuffer;\r
719 while (*PtrBuffer != '\0') {\r
720 if (*PtrBuffer == '-') {\r
721 break;\r
722 }\r
723 PtrBuffer++;\r
724 }\r
725 if (*PtrBuffer == '\0') {\r
726 FreePool (Buffer);\r
727 return EFI_NOT_FOUND;\r
728 }\r
729 *PtrBuffer = '\0';\r
730 Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);\r
731 Guid->Data3 = (UINT16)Data;\r
732\r
733 //\r
734 // Data4[0..1]\r
735 //\r
736 for ( Index = 0 ; Index < 2 ; Index++) {\r
737 PtrBuffer++;\r
738 if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {\r
739 FreePool (Buffer);\r
740 return EFI_NOT_FOUND;\r
741 }\r
742 Digits[0] = *PtrBuffer;\r
743 PtrBuffer++;\r
744 Digits[1] = *PtrBuffer;\r
745 Digits[2] = '\0';\r
746 Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);\r
747 Guid->Data4[Index] = (UINT8)Data;\r
748 }\r
749\r
750 //\r
751 // skip the '-'\r
752 //\r
753 PtrBuffer++;\r
754 if ((*PtrBuffer != '-' ) || ( *PtrBuffer == '\0')) {\r
755 return EFI_NOT_FOUND;\r
756 }\r
757\r
758 //\r
759 // Data4[2..7]\r
760 //\r
761 for ( ; Index < 8; Index++) {\r
762 PtrBuffer++;\r
763 if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {\r
764 FreePool (Buffer);\r
765 return EFI_NOT_FOUND;\r
766 }\r
767 Digits[0] = *PtrBuffer;\r
768 PtrBuffer++;\r
769 Digits[1] = *PtrBuffer;\r
770 Digits[2] = '\0';\r
771 Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);\r
772 Guid->Data4[Index] = (UINT8)Data;\r
773 }\r
774\r
775 FreePool (Buffer);\r
776\r
777 return EFI_SUCCESS;\r
778}\r
779\r
780/**\r
781 Pre process config data buffer into Section entry list and Comment entry list.\r
0a6f4824 782\r
b2824a8e 783 @param DataBuffer Config raw file buffer.\r
784 @param BufferSize Size of raw buffer.\r
785 @param SectionHead Pointer to the section entry list.\r
786 @param CommentHead Pointer to the comment entry list.\r
787\r
788 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
789 @retval EFI_SUCCESS Config data buffer is preprocessed.\r
790\r
791**/\r
792EFI_STATUS\r
793PreProcessDataFile (\r
794 IN UINT8 *DataBuffer,\r
795 IN UINTN BufferSize,\r
796 IN OUT SECTION_ITEM **SectionHead,\r
797 IN OUT COMMENT_LINE **CommentHead\r
798 )\r
799{\r
800 EFI_STATUS Status;\r
801 CHAR8 *Source;\r
802 CHAR8 *CurrentPtr;\r
803 CHAR8 *BufferEnd;\r
804 CHAR8 *PtrLine;\r
805 UINTN LineLength;\r
806 UINTN SourceLength;\r
807 UINTN MaxLineLength;\r
808\r
809 *SectionHead = NULL;\r
810 *CommentHead = NULL;\r
811 BufferEnd = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize);\r
812 CurrentPtr = (CHAR8 *) DataBuffer;\r
813 MaxLineLength = MAX_LINE_LENGTH;\r
814 Status = EFI_SUCCESS;\r
815\r
816 PtrLine = AllocatePool (MaxLineLength);\r
817 if (PtrLine == NULL) {\r
818 return EFI_OUT_OF_RESOURCES;\r
819 }\r
820\r
821 while (CurrentPtr < BufferEnd) {\r
822 Source = CurrentPtr;\r
823 SourceLength = (UINTN)BufferEnd - (UINTN)CurrentPtr;\r
824 LineLength = MaxLineLength;\r
825 //\r
826 // With the assumption that line length is less than 512\r
827 // characters. Otherwise BUFFER_TOO_SMALL will be returned.\r
828 //\r
829 Status = ProfileGetLine (\r
830 (UINT8 *) Source,\r
831 SourceLength,\r
832 (UINT8 *) PtrLine,\r
833 &LineLength\r
834 );\r
835 if (EFI_ERROR (Status)) {\r
836 if (Status == EFI_BUFFER_TOO_SMALL) {\r
837 //\r
838 // If buffer too small, re-allocate the buffer according\r
839 // to the returned LineLength and try again.\r
840 //\r
841 FreePool (PtrLine);\r
842 PtrLine = NULL;\r
843 PtrLine = AllocatePool (LineLength);\r
844 if (PtrLine == NULL) {\r
845 Status = EFI_OUT_OF_RESOURCES;\r
846 break;\r
847 }\r
848 SourceLength = LineLength;\r
849 Status = ProfileGetLine (\r
850 (UINT8 *) Source,\r
851 SourceLength,\r
852 (UINT8 *) PtrLine,\r
853 &LineLength\r
854 );\r
855 if (EFI_ERROR (Status)) {\r
856 break;\r
857 }\r
858 MaxLineLength = LineLength;\r
859 } else {\r
860 break;\r
861 }\r
862 }\r
863 CurrentPtr = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength);\r
864\r
865 //\r
866 // Line got. Trim the line before processing it.\r
867 //\r
868 ProfileTrim (\r
869 (UINT8 *) PtrLine,\r
870 &LineLength\r
871 );\r
872\r
873 //\r
874 // Blank line\r
875 //\r
876 if (LineLength == 0) {\r
877 continue;\r
878 }\r
879\r
880 if (PtrLine[0] == '#') {\r
881 Status = ProfileGetComments (\r
882 (UINT8 *) PtrLine,\r
883 LineLength,\r
884 CommentHead\r
885 );\r
886 } else if (PtrLine[0] == '[') {\r
887 Status = ProfileGetSection (\r
888 (UINT8 *) PtrLine,\r
889 LineLength,\r
890 SectionHead\r
891 );\r
892 } else {\r
893 Status = ProfileGetEntry (\r
894 (UINT8 *) PtrLine,\r
895 LineLength,\r
896 SectionHead\r
897 );\r
898 }\r
899\r
900 if (EFI_ERROR (Status)) {\r
901 break;\r
902 }\r
903 }\r
904\r
905 //\r
906 // Free buffer\r
907 //\r
908 FreePool (PtrLine);\r
909\r
910 return Status;\r
911}\r
912\r
913/**\r
914 Parse Config data file to get the updated data array.\r
915\r
916 @param DataBuffer Config raw file buffer.\r
917 @param BufferSize Size of raw buffer.\r
918 @param NumOfUpdates Pointer to the number of update data.\r
919 @param UpdateArray Pointer to the config of update data.\r
920\r
921 @retval EFI_NOT_FOUND No config data is found.\r
922 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
923 @retval EFI_SUCCESS Parse the config file successfully.\r
924\r
925**/\r
926EFI_STATUS\r
927ParseUpdateDataFile (\r
928 IN UINT8 *DataBuffer,\r
929 IN UINTN BufferSize,\r
930 IN OUT UINTN *NumOfUpdates,\r
931 IN OUT UPDATE_CONFIG_DATA **UpdateArray\r
932 )\r
933{\r
934 EFI_STATUS Status;\r
935 CHAR8 *Value;\r
936 CHAR8 *SectionName;\r
937 CHAR8 Entry[MAX_LINE_LENGTH];\r
938 SECTION_ITEM *SectionHead;\r
939 COMMENT_LINE *CommentHead;\r
940 UINTN Num;\r
941 UINTN Index;\r
942 EFI_GUID FileGuid;\r
943\r
944 SectionHead = NULL;\r
945 CommentHead = NULL;\r
946\r
947 //\r
948 // First process the data buffer and get all sections and entries\r
949 //\r
950 Status = PreProcessDataFile (\r
951 DataBuffer,\r
952 BufferSize,\r
953 &SectionHead,\r
954 &CommentHead\r
955 );\r
956 if (EFI_ERROR (Status)) {\r
957 FreeAllList (SectionHead, CommentHead);\r
958 return Status;\r
959 }\r
960\r
961 //\r
962 // Now get NumOfUpdate\r
963 //\r
964 Value = NULL;\r
965 Status = UpdateGetProfileString (\r
966 SectionHead,\r
967 (UINT8 *) "Head",\r
968 (UINT8 *) "NumOfUpdate",\r
969 (UINT8 **) &Value\r
970 );\r
971 if (Value == NULL) {\r
972 FreeAllList (SectionHead, CommentHead);\r
973 return EFI_NOT_FOUND;\r
974 }\r
975 Num = UpdateAtoi((UINT8 *) Value);\r
976 if (Num <= 0) {\r
977 FreeAllList (SectionHead, CommentHead);\r
978 return EFI_NOT_FOUND;\r
979 }\r
980\r
981 *NumOfUpdates = Num;\r
982 *UpdateArray = AllocatePool ((sizeof (UPDATE_CONFIG_DATA) * Num));\r
983 if (*UpdateArray == NULL) {\r
984 FreeAllList (SectionHead, CommentHead);\r
985 return EFI_OUT_OF_RESOURCES;\r
986 }\r
987\r
988 for ( Index = 0 ; Index < *NumOfUpdates ; Index++) {\r
989 //\r
990 // Get the section name of each update\r
991 //\r
c5ad1f86 992 AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update");\r
b2824a8e 993 UpdateStrCatNumber ((UINT8 *) Entry, Index);\r
994 Value = NULL;\r
995 Status = UpdateGetProfileString (\r
996 SectionHead,\r
997 (UINT8 *) "Head",\r
998 (UINT8 *) Entry,\r
999 (UINT8 **) &Value\r
1000 );\r
1001 if (Value == NULL) {\r
1002 FreeAllList (SectionHead, CommentHead);\r
1003 return EFI_NOT_FOUND;\r
1004 }\r
1005\r
1006 //\r
1007 // The section name of this update has been found.\r
1008 // Now looks for all the config data of this update\r
1009 //\r
1010 SectionName = Value;\r
1011\r
1012 //\r
1013 // UpdateType\r
1014 //\r
1015 Value = NULL;\r
1016 Status = UpdateGetProfileString (\r
1017 SectionHead,\r
1018 (UINT8 *) SectionName,\r
1019 (UINT8 *) "UpdateType",\r
1020 (UINT8 **) &Value\r
1021 );\r
1022 if (Value == NULL) {\r
1023 FreeAllList (SectionHead, CommentHead);\r
1024 return EFI_NOT_FOUND;\r
1025 }\r
1026\r
1027 Num = UpdateAtoi((UINT8 *) Value);\r
1028 if (( Num >= (UINTN) UpdateOperationMaximum)) {\r
1029 FreeAllList (SectionHead, CommentHead);\r
1030 return Status;\r
1031 }\r
1032 (*UpdateArray)[Index].Index = Index;\r
1033 (*UpdateArray)[Index].UpdateType = (UPDATE_OPERATION_TYPE) Num;\r
1034\r
1035 //\r
1036 // FvBaseAddress\r
1037 //\r
1038 Value = NULL;\r
1039 Status = UpdateGetProfileString (\r
1040 SectionHead,\r
1041 (UINT8 *) SectionName,\r
1042 (UINT8 *) "FvBaseAddress",\r
1043 (UINT8 **) &Value\r
1044 );\r
1045 if (Value == NULL) {\r
1046 FreeAllList (SectionHead, CommentHead);\r
1047 return EFI_NOT_FOUND;\r
1048 }\r
1049\r
1050 Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value);\r
1051 (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num;\r
1052\r
1053 //\r
1054 // FileBuid\r
1055 //\r
1056 Value = NULL;\r
1057 Status = UpdateGetProfileString (\r
1058 SectionHead,\r
1059 (UINT8 *) SectionName,\r
1060 (UINT8 *) "FileGuid",\r
1061 (UINT8 **) &Value\r
1062 );\r
1063 if (Value == NULL) {\r
1064 FreeAllList (SectionHead, CommentHead);\r
1065 return EFI_NOT_FOUND;\r
1066 }\r
1067\r
1068 Status = UpdateStringToGuid ((UINT8 *) Value, &FileGuid);\r
1069 if (EFI_ERROR (Status)) {\r
1070 FreeAllList (SectionHead, CommentHead);\r
1071 return Status;\r
1072 }\r
1073 CopyMem (&((*UpdateArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID));\r
1074\r
1075 //\r
1076 // FaultTolerant\r
1077 // Default value is FALSE\r
1078 //\r
1079 Value = NULL;\r
1080 (*UpdateArray)[Index].FaultTolerant = FALSE;\r
1081 Status = UpdateGetProfileString (\r
1082 SectionHead,\r
1083 (UINT8 *) SectionName,\r
1084 (UINT8 *) "FaultTolerant",\r
1085 (UINT8 **) &Value\r
1086 );\r
1087 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1088 FreeAllList (SectionHead, CommentHead);\r
1089 return Status;\r
1090 } else if (Value != NULL) {\r
1091 if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "TRUE") == 0) {\r
1092 (*UpdateArray)[Index].FaultTolerant = TRUE;\r
1093 } else if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "FALSE") == 0) {\r
1094 (*UpdateArray)[Index].FaultTolerant = FALSE;\r
1095 }\r
1096 }\r
1097\r
1098 if ((*UpdateArray)[Index].UpdateType == UpdateFvRange) {\r
1099 //\r
1100 // Length\r
1101 //\r
1102 Value = NULL;\r
1103 Status = UpdateGetProfileString (\r
1104 SectionHead,\r
1105 (UINT8 *) SectionName,\r
1106 (UINT8 *) "Length",\r
1107 (UINT8 **) &Value\r
1108 );\r
1109 if (Value == NULL) {\r
1110 FreeAllList (SectionHead, CommentHead);\r
1111 return EFI_NOT_FOUND;\r
1112 }\r
1113\r
1114 Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value);\r
1115 (*UpdateArray)[Index].Length = (UINTN) Num;\r
1116 }\r
1117 }\r
1118\r
1119 //\r
1120 // Now all configuration data got. Free those temporary buffers\r
1121 //\r
1122 FreeAllList (SectionHead, CommentHead);\r
1123\r
1124 return EFI_SUCCESS;\r
1125}\r
1126\r