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