1 /** @file 2 Creates output file that is a properly formed section per the PI spec. 3 4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <ctype.h> 19 20 #include <Common/UefiBaseTypes.h> 21 #include <Common/PiFirmwareFile.h> 22 #include <Protocol/GuidedSectionExtraction.h> 23 #include <IndustryStandard/PeImage.h> 24 25 #include "CommonLib.h" 26 #include "Compress.h" 27 #include "Crc32.h" 28 #include "EfiUtilityMsgs.h" 29 #include "ParseInf.h" 30 31 // 32 // GenSec Tool Information 33 // 34 #define UTILITY_NAME "GenSec" 35 #define UTILITY_MAJOR_VERSION 0 36 #define UTILITY_MINOR_VERSION 1 37 38 STATIC CHAR8 *mSectionTypeName[] = { 39 NULL, // 0x00 - reserved 40 "EFI_SECTION_COMPRESSION", // 0x01 41 "EFI_SECTION_GUID_DEFINED", // 0x02 42 NULL, // 0x03 - reserved 43 NULL, // 0x04 - reserved 44 NULL, // 0x05 - reserved 45 NULL, // 0x06 - reserved 46 NULL, // 0x07 - reserved 47 NULL, // 0x08 - reserved 48 NULL, // 0x09 - reserved 49 NULL, // 0x0A - reserved 50 NULL, // 0x0B - reserved 51 NULL, // 0x0C - reserved 52 NULL, // 0x0D - reserved 53 NULL, // 0x0E - reserved 54 NULL, // 0x0F - reserved 55 "EFI_SECTION_PE32", // 0x10 56 "EFI_SECTION_PIC", // 0x11 57 "EFI_SECTION_TE", // 0x12 58 "EFI_SECTION_DXE_DEPEX", // 0x13 59 "EFI_SECTION_VERSION", // 0x14 60 "EFI_SECTION_USER_INTERFACE", // 0x15 61 "EFI_SECTION_COMPATIBILITY16", // 0x16 62 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17 63 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18 64 "EFI_SECTION_RAW", // 0x19 65 NULL, // 0x1A 66 "EFI_SECTION_PEI_DEPEX", // 0x1B 67 "EFI_SECTION_SMM_DEPEX" // 0x1C 68 }; 69 70 STATIC CHAR8 *mCompressionTypeName[] = { "PI_NONE", "PI_STD" }; 71 72 #define EFI_GUIDED_SECTION_NONE 0x80 73 STATIC CHAR8 *mGUIDedSectionAttribue[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"}; 74 75 STATIC CHAR8 *mAlignName[] = { 76 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", 77 "1K", "2K", "4K", "8K", "16K", "32K", "64K" 78 }; 79 80 // 81 // Crc32 GUID section related definitions. 82 // 83 typedef struct { 84 EFI_GUID_DEFINED_SECTION GuidSectionHeader; 85 UINT32 CRC32Checksum; 86 } CRC32_SECTION_HEADER; 87 88 typedef struct { 89 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader; 90 UINT32 CRC32Checksum; 91 } CRC32_SECTION_HEADER2; 92 93 STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 94 STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; 95 96 STATIC 97 VOID 98 Version ( 99 VOID 100 ) 101 /*++ 102 103 Routine Description: 104 105 Print out version information for this utility. 106 107 Arguments: 108 109 None 110 111 Returns: 112 113 None 114 115 --*/ 116 { 117 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); 118 } 119 120 STATIC 121 VOID 122 Usage ( 123 VOID 124 ) 125 /*++ 126 127 Routine Description: 128 129 Print Help message. 130 131 Arguments: 132 133 VOID 134 135 Returns: 136 137 None 138 139 --*/ 140 { 141 // 142 // Summary usage 143 // 144 fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME); 145 146 // 147 // Copyright declaration 148 // 149 fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n"); 150 151 // 152 // Details Option 153 // 154 fprintf (stdout, "Options:\n"); 155 fprintf (stdout, " -o FileName, --outputfile FileName\n\ 156 File is the SectionFile to be created.\n"); 157 fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\ 158 SectionType defined in PI spec is one type of\n\ 159 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\ 160 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\ 161 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\ 162 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\ 163 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\ 164 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\ 165 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\ 166 if -s option is not given, \n\ 167 EFI_SECTION_ALL is default section type.\n"); 168 fprintf (stdout, " -c [Type], --compress [Type]\n\ 169 Compress method type can be PI_NONE or PI_STD.\n\ 170 if -c option is not given, PI_STD is default type.\n"); 171 fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\ 172 GuidValue is one specific vendor guid value.\n\ 173 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); 174 fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\ 175 GuidHeaderLength is the size of header of guided data\n"); 176 fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\ 177 GuidAttr is guid section atttributes, which may be\n\ 178 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\ 179 if -r option is not given, default PROCESSING_REQUIRED\n"); 180 fprintf (stdout, " -n String, --name String\n\ 181 String is a NULL terminated string used in Ui section.\n"); 182 fprintf (stdout, " -j Number, --buildnumber Number\n\ 183 Number is an integer value between 0 and 65535\n\ 184 used in Ver section.\n"); 185 fprintf (stdout, " --sectionalign SectionAlign\n\ 186 SectionAlign points to section alignment, which support\n\ 187 the alignment scope 1~64K. It is specified in same\n\ 188 order that the section file is input.\n"); 189 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); 190 fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); 191 fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); 192 fprintf (stdout, " --version Show program's version number and exit.\n"); 193 fprintf (stdout, " -h, --help Show this help message and exit.\n"); 194 } 195 196 VOID 197 Ascii2UnicodeString ( 198 CHAR8 *String, 199 CHAR16 *UniString 200 ) 201 /*++ 202 203 Routine Description: 204 205 Write ascii string as unicode string format to FILE 206 207 Arguments: 208 209 String - Pointer to string that is written to FILE. 210 UniString - Pointer to unicode string 211 212 Returns: 213 214 NULL 215 216 --*/ 217 { 218 while (*String != '\0') { 219 *(UniString++) = (CHAR16) *(String++); 220 } 221 // 222 // End the UniString with a NULL. 223 // 224 *UniString = '\0'; 225 } 226 227 STATUS 228 GenSectionCommonLeafSection ( 229 CHAR8 **InputFileName, 230 UINT32 InputFileNum, 231 UINT8 SectionType, 232 UINT8 **OutFileBuffer 233 ) 234 /*++ 235 236 Routine Description: 237 238 Generate a leaf section of type other than EFI_SECTION_VERSION 239 and EFI_SECTION_USER_INTERFACE. Input file must be well formed. 240 The function won't validate the input file's contents. For 241 common leaf sections, the input file may be a binary file. 242 The utility will add section header to the file. 243 244 Arguments: 245 246 InputFileName - Name of the input file. 247 248 InputFileNum - Number of input files. Should be 1 for leaf section. 249 250 SectionType - A valid section type string 251 252 OutFileBuffer - Buffer pointer to Output file contents 253 254 Returns: 255 256 STATUS_ERROR - can't continue 257 STATUS_SUCCESS - successful return 258 259 --*/ 260 { 261 UINT32 InputFileLength; 262 FILE *InFile; 263 UINT8 *Buffer; 264 UINT32 TotalLength; 265 UINT32 HeaderLength; 266 EFI_COMMON_SECTION_HEADER *CommonSect; 267 STATUS Status; 268 269 if (InputFileNum > 1) { 270 Error (NULL, 0, 2000, "Invalid paramter", "more than one input file specified"); 271 return STATUS_ERROR; 272 } else if (InputFileNum < 1) { 273 Error (NULL, 0, 2000, "Invalid paramter", "no input file specified"); 274 return STATUS_ERROR; 275 } 276 // 277 // Open the input file 278 // 279 InFile = fopen (LongFilePath (InputFileName[0]), "rb"); 280 if (InFile == NULL) { 281 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]); 282 return STATUS_ERROR; 283 } 284 285 Status = STATUS_ERROR; 286 Buffer = NULL; 287 // 288 // Seek to the end of the input file so we can determine its size 289 // 290 fseek (InFile, 0, SEEK_END); 291 InputFileLength = ftell (InFile); 292 fseek (InFile, 0, SEEK_SET); 293 DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength); 294 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength; 295 // 296 // Size must fit in 3 bytes 297 // 298 //if (TotalLength >= MAX_SECTION_SIZE) { 299 // Error (NULL, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20); 300 // goto Done; 301 //} 302 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER); 303 if (TotalLength >= MAX_SECTION_SIZE) { 304 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength; 305 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2); 306 } 307 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength); 308 // 309 // Fill in the fields in the local section header structure 310 // 311 Buffer = (UINT8 *) malloc ((size_t) TotalLength); 312 if (Buffer == NULL) { 313 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); 314 goto Done; 315 } 316 CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer; 317 CommonSect->Type = SectionType; 318 if (TotalLength < MAX_SECTION_SIZE) { 319 CommonSect->Size[0] = (UINT8) (TotalLength & 0xff); 320 CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); 321 CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); 322 } else { 323 memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3); 324 ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength; 325 } 326 327 // 328 // read data from the input file. 329 // 330 if (InputFileLength != 0) { 331 if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) { 332 Error (NULL, 0, 0004, "Error reading file", InputFileName[0]); 333 goto Done; 334 } 335 } 336 337 // 338 // Set OutFileBuffer 339 // 340 *OutFileBuffer = Buffer; 341 Status = STATUS_SUCCESS; 342 343 Done: 344 fclose (InFile); 345 346 return Status; 347 } 348 349 STATIC 350 EFI_STATUS 351 StringtoAlignment ( 352 IN CHAR8 *AlignBuffer, 353 OUT UINT32 *AlignNumber 354 ) 355 /*++ 356 357 Routine Description: 358 359 Converts Align String to align value (1~64K). 360 361 Arguments: 362 363 AlignBuffer - Pointer to Align string. 364 AlignNumber - Pointer to Align value. 365 366 Returns: 367 368 EFI_SUCCESS Successfully convert align string to align value. 369 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope. 370 371 --*/ 372 { 373 UINT32 Index = 0; 374 // 375 // Check AlignBuffer 376 // 377 if (AlignBuffer == NULL) { 378 return EFI_INVALID_PARAMETER; 379 } 380 for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) { 381 if (stricmp (AlignBuffer, mAlignName [Index]) == 0) { 382 *AlignNumber = 1 << Index; 383 return EFI_SUCCESS; 384 } 385 } 386 return EFI_INVALID_PARAMETER; 387 } 388 389 EFI_STATUS 390 GetSectionContents ( 391 CHAR8 **InputFileName, 392 UINT32 *InputFileAlign, 393 UINT32 InputFileNum, 394 UINT8 *FileBuffer, 395 UINT32 *BufferLength 396 ) 397 /*++ 398 399 Routine Description: 400 401 Get the contents of all section files specified in InputFileName 402 into FileBuffer. 403 404 Arguments: 405 406 InputFileName - Name of the input file. 407 408 InputFileAlign - Alignment required by the input file data. 409 410 InputFileNum - Number of input files. Should be at least 1. 411 412 FileBuffer - Output buffer to contain data 413 414 BufferLength - On input, this is size of the FileBuffer. 415 On output, this is the actual length of the data. 416 417 Returns: 418 419 EFI_SUCCESS on successful return 420 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL. 421 EFI_ABORTED if unable to open input file. 422 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data. 423 --*/ 424 { 425 UINT32 Size; 426 UINT32 Offset; 427 UINT32 FileSize; 428 UINT32 Index; 429 FILE *InFile; 430 EFI_COMMON_SECTION_HEADER *SectHeader; 431 EFI_COMMON_SECTION_HEADER2 TempSectHeader; 432 EFI_TE_IMAGE_HEADER TeHeader; 433 UINT32 TeOffset; 434 EFI_GUID_DEFINED_SECTION GuidSectHeader; 435 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2; 436 UINT32 HeaderSize; 437 438 if (InputFileNum < 1) { 439 Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file"); 440 return EFI_INVALID_PARAMETER; 441 } 442 443 if (BufferLength == NULL) { 444 Error (NULL, 0, 2000, "Invalid paramter", "BufferLength can't be NULL"); 445 return EFI_INVALID_PARAMETER; 446 } 447 448 Size = 0; 449 Offset = 0; 450 TeOffset = 0; 451 // 452 // Go through our array of file names and copy their contents 453 // to the output buffer. 454 // 455 for (Index = 0; Index < InputFileNum; Index++) { 456 // 457 // make sure section ends on a DWORD boundary 458 // 459 while ((Size & 0x03) != 0) { 460 if (FileBuffer != NULL && Size < *BufferLength) { 461 FileBuffer[Size] = 0; 462 } 463 Size++; 464 } 465 466 // 467 // Open file and read contents 468 // 469 InFile = fopen (LongFilePath (InputFileName[Index]), "rb"); 470 if (InFile == NULL) { 471 Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]); 472 return EFI_ABORTED; 473 } 474 475 fseek (InFile, 0, SEEK_END); 476 FileSize = ftell (InFile); 477 fseek (InFile, 0, SEEK_SET); 478 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize); 479 // 480 // Adjust section buffer when section alignment is required. 481 // 482 if (InputFileAlign != NULL) { 483 // 484 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section. 485 // 486 TeOffset = 0; 487 // 488 // The section might be EFI_COMMON_SECTION_HEADER2 489 // But only Type needs to be checked 490 // 491 if (FileSize >= MAX_SECTION_SIZE) { 492 HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2); 493 } else { 494 HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER); 495 } 496 fread (&TempSectHeader, 1, HeaderSize, InFile); 497 if (TempSectHeader.Type == EFI_SECTION_TE) { 498 fread (&TeHeader, 1, sizeof (TeHeader), InFile); 499 if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { 500 TeOffset = TeHeader.StrippedSize - sizeof (TeHeader); 501 } 502 } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) { 503 fseek (InFile, 0, SEEK_SET); 504 if (FileSize >= MAX_SECTION_SIZE) { 505 fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile); 506 if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { 507 HeaderSize = GuidSectHeader2.DataOffset; 508 } 509 } else { 510 fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile); 511 if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { 512 HeaderSize = GuidSectHeader.DataOffset; 513 } 514 } 515 } 516 517 fseek (InFile, 0, SEEK_SET); 518 519 // 520 // Revert TeOffset to the converse value relative to Alignment 521 // This is to assure the original PeImage Header at Alignment. 522 // 523 if (TeOffset != 0) { 524 TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]); 525 TeOffset = TeOffset % InputFileAlign [Index]; 526 } 527 528 // 529 // make sure section data meet its alignment requirement by adding one raw pad section. 530 // 531 if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) { 532 Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1); 533 Offset = Offset - Size - HeaderSize - TeOffset; 534 535 if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) { 536 // 537 // The maximal alignment is 64K, the raw section size must be less than 0xffffff 538 // 539 memset (FileBuffer + Size, 0, Offset); 540 SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size); 541 SectHeader->Type = EFI_SECTION_RAW; 542 SectHeader->Size[0] = (UINT8) (Offset & 0xff); 543 SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8); 544 SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16); 545 } 546 DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset); 547 548 Size = Size + Offset; 549 } 550 } 551 552 // 553 // Now read the contents of the file into the buffer 554 // Buffer must be enough to contain the file content. 555 // 556 if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) { 557 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) { 558 Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]); 559 fclose (InFile); 560 return EFI_ABORTED; 561 } 562 } 563 564 fclose (InFile); 565 Size += FileSize; 566 } 567 568 // 569 // Set the real required buffer size. 570 // 571 if (Size > *BufferLength) { 572 *BufferLength = Size; 573 return EFI_BUFFER_TOO_SMALL; 574 } else { 575 *BufferLength = Size; 576 return EFI_SUCCESS; 577 } 578 } 579 580 EFI_STATUS 581 GenSectionCompressionSection ( 582 CHAR8 **InputFileName, 583 UINT32 *InputFileAlign, 584 UINT32 InputFileNum, 585 UINT8 SectCompSubType, 586 UINT8 **OutFileBuffer 587 ) 588 /*++ 589 590 Routine Description: 591 592 Generate an encapsulating section of type EFI_SECTION_COMPRESSION 593 Input file must be already sectioned. The function won't validate 594 the input files' contents. Caller should hand in files already 595 with section header. 596 597 Arguments: 598 599 InputFileName - Name of the input file. 600 601 InputFileAlign - Alignment required by the input file data. 602 603 InputFileNum - Number of input files. Should be at least 1. 604 605 SectCompSubType - Specify the compression algorithm requested. 606 607 OutFileBuffer - Buffer pointer to Output file contents 608 609 Returns: 610 611 EFI_SUCCESS on successful return 612 EFI_INVALID_PARAMETER if InputFileNum is less than 1 613 EFI_ABORTED if unable to open input file. 614 EFI_OUT_OF_RESOURCES No resource to complete the operation. 615 --*/ 616 { 617 UINT32 TotalLength; 618 UINT32 InputLength; 619 UINT32 CompressedLength; 620 UINT32 HeaderLength; 621 UINT8 *FileBuffer; 622 UINT8 *OutputBuffer; 623 EFI_STATUS Status; 624 EFI_COMPRESSION_SECTION *CompressionSect; 625 EFI_COMPRESSION_SECTION2 *CompressionSect2; 626 COMPRESS_FUNCTION CompressFunction; 627 628 InputLength = 0; 629 FileBuffer = NULL; 630 OutputBuffer = NULL; 631 CompressedLength = 0; 632 TotalLength = 0; 633 // 634 // read all input file contents into a buffer 635 // first get the size of all file contents 636 // 637 Status = GetSectionContents ( 638 InputFileName, 639 InputFileAlign, 640 InputFileNum, 641 FileBuffer, 642 &InputLength 643 ); 644 645 if (Status == EFI_BUFFER_TOO_SMALL) { 646 FileBuffer = (UINT8 *) malloc (InputLength); 647 if (FileBuffer == NULL) { 648 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); 649 return EFI_OUT_OF_RESOURCES; 650 } 651 // 652 // read all input file contents into a buffer 653 // 654 Status = GetSectionContents ( 655 InputFileName, 656 InputFileAlign, 657 InputFileNum, 658 FileBuffer, 659 &InputLength 660 ); 661 } 662 663 if (EFI_ERROR (Status)) { 664 if (FileBuffer != NULL) { 665 free (FileBuffer); 666 } 667 return Status; 668 } 669 670 CompressFunction = NULL; 671 672 // 673 // Now data is in FileBuffer, compress the data 674 // 675 switch (SectCompSubType) { 676 case EFI_NOT_COMPRESSED: 677 CompressedLength = InputLength; 678 HeaderLength = sizeof (EFI_COMPRESSION_SECTION); 679 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) { 680 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2); 681 } 682 TotalLength = CompressedLength + HeaderLength; 683 // 684 // Copy file buffer to the none compressed data. 685 // 686 OutputBuffer = malloc (TotalLength); 687 if (OutputBuffer == NULL) { 688 free (FileBuffer); 689 return EFI_OUT_OF_RESOURCES; 690 } 691 memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength); 692 free (FileBuffer); 693 FileBuffer = OutputBuffer; 694 break; 695 696 case EFI_STANDARD_COMPRESSION: 697 CompressFunction = (COMPRESS_FUNCTION) EfiCompress; 698 break; 699 700 default: 701 Error (NULL, 0, 2000, "Invalid paramter", "unknown compression type"); 702 free (FileBuffer); 703 return EFI_ABORTED; 704 } 705 706 if (CompressFunction != NULL) { 707 708 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength); 709 if (Status == EFI_BUFFER_TOO_SMALL) { 710 HeaderLength = sizeof (EFI_COMPRESSION_SECTION); 711 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) { 712 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2); 713 } 714 TotalLength = CompressedLength + HeaderLength; 715 OutputBuffer = malloc (TotalLength); 716 if (!OutputBuffer) { 717 free (FileBuffer); 718 return EFI_OUT_OF_RESOURCES; 719 } 720 721 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength); 722 } 723 724 free (FileBuffer); 725 FileBuffer = OutputBuffer; 726 727 if (EFI_ERROR (Status)) { 728 if (FileBuffer != NULL) { 729 free (FileBuffer); 730 } 731 732 return Status; 733 } 734 } 735 736 DebugMsg (NULL, 0, 9, "comprss file size", 737 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength); 738 739 //if (TotalLength >= MAX_SECTION_SIZE) { 740 // Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20); 741 // if (FileBuffer != NULL) { 742 // free (FileBuffer); 743 // } 744 // if (OutputBuffer != NULL) { 745 // free (OutputBuffer); 746 // } 747 // return STATUS_ERROR; 748 //} 749 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength); 750 751 // 752 // Add the section header for the compressed data 753 // 754 if (TotalLength >= MAX_SECTION_SIZE) { 755 CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer; 756 757 memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3); 758 CompressionSect2->CommonHeader.Type = EFI_SECTION_COMPRESSION; 759 CompressionSect2->CommonHeader.ExtendedSize = TotalLength; 760 CompressionSect2->CompressionType = SectCompSubType; 761 CompressionSect2->UncompressedLength = InputLength; 762 } else { 763 CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer; 764 765 CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION; 766 CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); 767 CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); 768 CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); 769 CompressionSect->CompressionType = SectCompSubType; 770 CompressionSect->UncompressedLength = InputLength; 771 } 772 773 // 774 // Set OutFileBuffer 775 // 776 *OutFileBuffer = FileBuffer; 777 778 return EFI_SUCCESS; 779 } 780 781 EFI_STATUS 782 GenSectionGuidDefinedSection ( 783 CHAR8 **InputFileName, 784 UINT32 *InputFileAlign, 785 UINT32 InputFileNum, 786 EFI_GUID *VendorGuid, 787 UINT16 DataAttribute, 788 UINT32 DataHeaderSize, 789 UINT8 **OutFileBuffer 790 ) 791 /*++ 792 793 Routine Description: 794 795 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED 796 Input file must be already sectioned. The function won't validate 797 the input files' contents. Caller should hand in files already 798 with section header. 799 800 Arguments: 801 802 InputFileName - Name of the input file. 803 804 InputFileAlign - Alignment required by the input file data. 805 806 InputFileNum - Number of input files. Should be at least 1. 807 808 VendorGuid - Specify vendor guid value. 809 810 DataAttribute - Specify attribute for the vendor guid data. 811 812 DataHeaderSize- Guided Data Header Size 813 814 OutFileBuffer - Buffer pointer to Output file contents 815 816 Returns: 817 818 EFI_SUCCESS on successful return 819 EFI_INVALID_PARAMETER if InputFileNum is less than 1 820 EFI_ABORTED if unable to open input file. 821 EFI_OUT_OF_RESOURCES No resource to complete the operation. 822 823 --*/ 824 { 825 UINT32 TotalLength; 826 UINT32 InputLength; 827 UINT32 Offset; 828 UINT8 *FileBuffer; 829 UINT32 Crc32Checksum; 830 EFI_STATUS Status; 831 CRC32_SECTION_HEADER *Crc32GuidSect; 832 CRC32_SECTION_HEADER2 *Crc32GuidSect2; 833 EFI_GUID_DEFINED_SECTION *VendorGuidSect; 834 EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2; 835 836 InputLength = 0; 837 Offset = 0; 838 FileBuffer = NULL; 839 TotalLength = 0; 840 841 // 842 // read all input file contents into a buffer 843 // first get the size of all file contents 844 // 845 Status = GetSectionContents ( 846 InputFileName, 847 InputFileAlign, 848 InputFileNum, 849 FileBuffer, 850 &InputLength 851 ); 852 853 if (Status == EFI_BUFFER_TOO_SMALL) { 854 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) { 855 Offset = sizeof (CRC32_SECTION_HEADER); 856 if (InputLength + Offset >= MAX_SECTION_SIZE) { 857 Offset = sizeof (CRC32_SECTION_HEADER2); 858 } 859 } else { 860 Offset = sizeof (EFI_GUID_DEFINED_SECTION); 861 if (InputLength + Offset >= MAX_SECTION_SIZE) { 862 Offset = sizeof (EFI_GUID_DEFINED_SECTION2); 863 } 864 } 865 TotalLength = InputLength + Offset; 866 867 FileBuffer = (UINT8 *) malloc (InputLength + Offset); 868 if (FileBuffer == NULL) { 869 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); 870 return EFI_OUT_OF_RESOURCES; 871 } 872 // 873 // read all input file contents into a buffer 874 // 875 Status = GetSectionContents ( 876 InputFileName, 877 InputFileAlign, 878 InputFileNum, 879 FileBuffer + Offset, 880 &InputLength 881 ); 882 } 883 884 if (EFI_ERROR (Status)) { 885 if (FileBuffer != NULL) { 886 free (FileBuffer); 887 } 888 Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]); 889 return Status; 890 } 891 892 if (InputLength == 0) { 893 Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName); 894 return EFI_NOT_FOUND; 895 } 896 897 // 898 // Now data is in FileBuffer + Offset 899 // 900 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) { 901 // 902 // Default Guid section is CRC32. 903 // 904 Crc32Checksum = 0; 905 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum); 906 907 if (TotalLength >= MAX_SECTION_SIZE) { 908 Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer; 909 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; 910 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) 0xff; 911 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) 0xff; 912 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) 0xff; 913 Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength; 914 memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID)); 915 Crc32GuidSect2->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; 916 Crc32GuidSect2->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER2); 917 Crc32GuidSect2->CRC32Checksum = Crc32Checksum; 918 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset); 919 } else { 920 Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer; 921 Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; 922 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); 923 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); 924 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); 925 memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID)); 926 Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; 927 Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER); 928 Crc32GuidSect->CRC32Checksum = Crc32Checksum; 929 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset); 930 } 931 } else { 932 if (TotalLength >= MAX_SECTION_SIZE) { 933 VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer; 934 VendorGuidSect2->CommonHeader.Type = EFI_SECTION_GUID_DEFINED; 935 VendorGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff; 936 VendorGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff; 937 VendorGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff; 938 VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2); 939 memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID)); 940 VendorGuidSect2->Attributes = DataAttribute; 941 VendorGuidSect2->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize); 942 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset); 943 } else { 944 VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer; 945 VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED; 946 VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); 947 VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); 948 VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); 949 memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID)); 950 VendorGuidSect->Attributes = DataAttribute; 951 VendorGuidSect->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize); 952 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset); 953 } 954 } 955 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength); 956 957 // 958 // Set OutFileBuffer 959 // 960 *OutFileBuffer = FileBuffer; 961 962 return EFI_SUCCESS; 963 } 964 965 int 966 main ( 967 int argc, 968 char *argv[] 969 ) 970 /*++ 971 972 Routine Description: 973 974 Main 975 976 Arguments: 977 978 command line parameters 979 980 Returns: 981 982 EFI_SUCCESS Section header successfully generated and section concatenated. 983 EFI_ABORTED Could not generate the section 984 EFI_OUT_OF_RESOURCES No resource to complete the operation. 985 986 --*/ 987 { 988 UINT32 Index; 989 UINT32 InputFileNum; 990 FILE *OutFile; 991 CHAR8 **InputFileName; 992 CHAR8 *OutputFileName; 993 CHAR8 *SectionName; 994 CHAR8 *CompressionName; 995 CHAR8 *StringBuffer; 996 EFI_GUID VendorGuid = mZeroGuid; 997 int VersionNumber; 998 UINT8 SectType; 999 UINT8 SectCompSubType; 1000 UINT16 SectGuidAttribute; 1001 UINT64 SectGuidHeaderLength; 1002 EFI_VERSION_SECTION *VersionSect; 1003 EFI_USER_INTERFACE_SECTION *UiSect; 1004 UINT32 InputLength; 1005 UINT8 *OutFileBuffer; 1006 EFI_STATUS Status; 1007 UINT64 LogLevel; 1008 UINT32 *InputFileAlign; 1009 UINT32 InputFileAlignNum; 1010 EFI_COMMON_SECTION_HEADER *SectionHeader; 1011 1012 InputFileAlign = NULL; 1013 InputFileAlignNum = 0; 1014 InputFileName = NULL; 1015 OutputFileName = NULL; 1016 SectionName = NULL; 1017 CompressionName = NULL; 1018 StringBuffer = ""; 1019 OutFile = NULL; 1020 VersionNumber = 0; 1021 InputFileNum = 0; 1022 SectType = EFI_SECTION_ALL; 1023 SectCompSubType = 0; 1024 SectGuidAttribute = EFI_GUIDED_SECTION_NONE; 1025 OutFileBuffer = NULL; 1026 InputLength = 0; 1027 Status = STATUS_SUCCESS; 1028 LogLevel = 0; 1029 SectGuidHeaderLength = 0; 1030 VersionSect = NULL; 1031 UiSect = NULL; 1032 1033 SetUtilityName (UTILITY_NAME); 1034 1035 if (argc == 1) { 1036 Error (NULL, 0, 1001, "Missing options", "No options input"); 1037 Usage (); 1038 return STATUS_ERROR; 1039 } 1040 1041 // 1042 // Parse command line 1043 // 1044 argc --; 1045 argv ++; 1046 1047 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { 1048 Version (); 1049 Usage (); 1050 return STATUS_SUCCESS; 1051 } 1052 1053 if (stricmp (argv[0], "--version") == 0) { 1054 Version (); 1055 return STATUS_SUCCESS; 1056 } 1057 1058 while (argc > 0) { 1059 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) { 1060 SectionName = argv[1]; 1061 if (SectionName == NULL) { 1062 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL"); 1063 goto Finish; 1064 } 1065 argc -= 2; 1066 argv += 2; 1067 continue; 1068 } 1069 1070 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { 1071 OutputFileName = argv[1]; 1072 if (OutputFileName == NULL) { 1073 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL"); 1074 goto Finish; 1075 } 1076 argc -= 2; 1077 argv += 2; 1078 continue; 1079 } 1080 1081 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) { 1082 CompressionName = argv[1]; 1083 if (CompressionName == NULL) { 1084 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL"); 1085 goto Finish; 1086 } 1087 argc -= 2; 1088 argv += 2; 1089 continue; 1090 } 1091 1092 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) { 1093 Status = StringToGuid (argv[1], &VendorGuid); 1094 if (EFI_ERROR (Status)) { 1095 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); 1096 goto Finish; 1097 } 1098 argc -= 2; 1099 argv += 2; 1100 continue; 1101 } 1102 1103 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) { 1104 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) { 1105 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED; 1106 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) { 1107 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID; 1108 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) { 1109 // 1110 // NONE attribute 1111 // 1112 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE; 1113 } else { 1114 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); 1115 goto Finish; 1116 } 1117 argc -= 2; 1118 argv += 2; 1119 continue; 1120 } 1121 1122 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) { 1123 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength); 1124 if (EFI_ERROR (Status)) { 1125 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]); 1126 goto Finish; 1127 } 1128 argc -= 2; 1129 argv += 2; 1130 continue; 1131 } 1132 1133 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) { 1134 StringBuffer = argv[1]; 1135 if (StringBuffer == NULL) { 1136 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL"); 1137 goto Finish; 1138 } 1139 argc -= 2; 1140 argv += 2; 1141 continue; 1142 } 1143 1144 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) { 1145 if (argv[1] == NULL) { 1146 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL"); 1147 goto Finish; 1148 } 1149 // 1150 // Verify string is a integrator number 1151 // 1152 for (Index = 0; Index < strlen (argv[1]); Index++) { 1153 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) { 1154 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); 1155 goto Finish; 1156 } 1157 } 1158 1159 sscanf (argv[1], "%d", &VersionNumber); 1160 argc -= 2; 1161 argv += 2; 1162 continue; 1163 } 1164 1165 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { 1166 SetPrintLevel (VERBOSE_LOG_LEVEL); 1167 VerboseMsg ("Verbose output Mode Set!"); 1168 argc --; 1169 argv ++; 1170 continue; 1171 } 1172 1173 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { 1174 SetPrintLevel (KEY_LOG_LEVEL); 1175 KeyMsg ("Quiet output Mode Set!"); 1176 argc --; 1177 argv ++; 1178 continue; 1179 } 1180 1181 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { 1182 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); 1183 if (EFI_ERROR (Status)) { 1184 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); 1185 goto Finish; 1186 } 1187 if (LogLevel > 9) { 1188 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel); 1189 goto Finish; 1190 } 1191 SetPrintLevel (LogLevel); 1192 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); 1193 argc -= 2; 1194 argv += 2; 1195 continue; 1196 } 1197 1198 // 1199 // Section File alignment requirement 1200 // 1201 if (stricmp (argv[0], "--sectionalign") == 0) { 1202 if (InputFileAlignNum == 0) { 1203 InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)); 1204 if (InputFileAlign == NULL) { 1205 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1206 return 1; 1207 } 1208 memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)); 1209 } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) { 1210 InputFileAlign = (UINT32 *) realloc ( 1211 InputFileAlign, 1212 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32) 1213 ); 1214 1215 if (InputFileAlign == NULL) { 1216 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1217 return 1; 1218 } 1219 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32))); 1220 } 1221 1222 Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum])); 1223 if (EFI_ERROR (Status)) { 1224 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); 1225 goto Finish; 1226 } 1227 argc -= 2; 1228 argv += 2; 1229 InputFileAlignNum ++; 1230 continue; 1231 } 1232 1233 // 1234 // Get Input file name 1235 // 1236 if ((InputFileNum == 0) && (InputFileName == NULL)) { 1237 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)); 1238 if (InputFileName == NULL) { 1239 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); 1240 return 1; 1241 } 1242 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); 1243 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) { 1244 // 1245 // InputFileName buffer too small, need to realloc 1246 // 1247 InputFileName = (CHAR8 **) realloc ( 1248 InputFileName, 1249 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *) 1250 ); 1251 1252 if (InputFileName == NULL) { 1253 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); 1254 return 1; 1255 } 1256 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); 1257 } 1258 1259 InputFileName[InputFileNum++] = argv[0]; 1260 argc --; 1261 argv ++; 1262 } 1263 1264 if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) { 1265 Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section"); 1266 goto Finish; 1267 } 1268 1269 VerboseMsg ("%s tool start.", UTILITY_NAME); 1270 1271 // 1272 // Parse all command line parameters to get the corresponding section type. 1273 // 1274 VerboseMsg ("Section type is %s", SectionName); 1275 if (SectionName == NULL) { 1276 // 1277 // No specified Section type, default is SECTION_ALL. 1278 // 1279 SectType = EFI_SECTION_ALL; 1280 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) { 1281 SectType = EFI_SECTION_COMPRESSION; 1282 if (CompressionName == NULL) { 1283 // 1284 // Default is PI_STD compression algorithm. 1285 // 1286 SectCompSubType = EFI_STANDARD_COMPRESSION; 1287 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) { 1288 SectCompSubType = EFI_NOT_COMPRESSED; 1289 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) { 1290 SectCompSubType = EFI_STANDARD_COMPRESSION; 1291 } else { 1292 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName); 1293 goto Finish; 1294 } 1295 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]); 1296 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) { 1297 SectType = EFI_SECTION_GUID_DEFINED; 1298 1299 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) { 1300 // 1301 // NONE attribute, clear attribute value. 1302 // 1303 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE; 1304 } 1305 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", 1306 (unsigned) VendorGuid.Data1, 1307 VendorGuid.Data2, 1308 VendorGuid.Data3, 1309 VendorGuid.Data4[0], 1310 VendorGuid.Data4[1], 1311 VendorGuid.Data4[2], 1312 VendorGuid.Data4[3], 1313 VendorGuid.Data4[4], 1314 VendorGuid.Data4[5], 1315 VendorGuid.Data4[6], 1316 VendorGuid.Data4[7]); 1317 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) { 1318 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]); 1319 } 1320 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) { 1321 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]); 1322 } 1323 if (SectGuidHeaderLength != 0) { 1324 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength); 1325 } 1326 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) { 1327 SectType = EFI_SECTION_PE32; 1328 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) { 1329 SectType = EFI_SECTION_PIC; 1330 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) { 1331 SectType = EFI_SECTION_TE; 1332 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) { 1333 SectType = EFI_SECTION_DXE_DEPEX; 1334 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) { 1335 SectType = EFI_SECTION_SMM_DEPEX; 1336 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) { 1337 SectType = EFI_SECTION_VERSION; 1338 if (VersionNumber < 0 || VersionNumber > 65535) { 1339 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber); 1340 goto Finish; 1341 } 1342 VerboseMsg ("Version section number is %d", VersionNumber); 1343 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) { 1344 SectType = EFI_SECTION_USER_INTERFACE; 1345 if (StringBuffer[0] == '\0') { 1346 Error (NULL, 0, 1001, "Missing option", "user interface string"); 1347 goto Finish; 1348 } 1349 VerboseMsg ("UI section string name is %s", StringBuffer); 1350 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) { 1351 SectType = EFI_SECTION_COMPATIBILITY16; 1352 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) { 1353 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; 1354 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) { 1355 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID; 1356 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) { 1357 SectType = EFI_SECTION_RAW; 1358 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) { 1359 SectType = EFI_SECTION_PEI_DEPEX; 1360 } else { 1361 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName); 1362 goto Finish; 1363 } 1364 1365 // 1366 // GuidValue is only required by Guided section. 1367 // 1368 if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) { 1369 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName); 1370 } 1371 1372 // 1373 // Check whether there is input file 1374 // 1375 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) { 1376 // 1377 // The input file are required for other section type. 1378 // 1379 if (InputFileNum == 0) { 1380 Error (NULL, 0, 1001, "Missing options", "Input files"); 1381 goto Finish; 1382 } 1383 } 1384 // 1385 // Check whether there is output file 1386 // 1387 for (Index = 0; Index < InputFileNum; Index ++) { 1388 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]); 1389 } 1390 if (OutputFileName == NULL) { 1391 Error (NULL, 0, 1001, "Missing options", "Output file"); 1392 goto Finish; 1393 // OutFile = stdout; 1394 } 1395 VerboseMsg ("Output file name is %s", OutputFileName); 1396 1397 // 1398 // At this point, we've fully validated the command line, and opened appropriate 1399 // files, so let's go and do what we've been asked to do... 1400 // 1401 // 1402 // Within this switch, build and write out the section header including any 1403 // section type specific pieces. If there's an input file, it's tacked on later 1404 // 1405 switch (SectType) { 1406 case EFI_SECTION_COMPRESSION: 1407 if (InputFileAlign != NULL) { 1408 free (InputFileAlign); 1409 InputFileAlign = NULL; 1410 } 1411 Status = GenSectionCompressionSection ( 1412 InputFileName, 1413 InputFileAlign, 1414 InputFileNum, 1415 SectCompSubType, 1416 &OutFileBuffer 1417 ); 1418 break; 1419 1420 case EFI_SECTION_GUID_DEFINED: 1421 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) { 1422 // 1423 // Only process alignment for the default known CRC32 guided section. 1424 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated. 1425 // 1426 free (InputFileAlign); 1427 InputFileAlign = NULL; 1428 } 1429 Status = GenSectionGuidDefinedSection ( 1430 InputFileName, 1431 InputFileAlign, 1432 InputFileNum, 1433 &VendorGuid, 1434 SectGuidAttribute, 1435 (UINT32) SectGuidHeaderLength, 1436 &OutFileBuffer 1437 ); 1438 break; 1439 1440 case EFI_SECTION_VERSION: 1441 Index = sizeof (EFI_COMMON_SECTION_HEADER); 1442 // 1443 // 2 bytes for the build number UINT16 1444 // 1445 Index += 2; 1446 // 1447 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null. 1448 // 1449 Index += (strlen (StringBuffer) * 2) + 2; 1450 OutFileBuffer = (UINT8 *) malloc (Index); 1451 if (OutFileBuffer == NULL) { 1452 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); 1453 goto Finish; 1454 } 1455 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer; 1456 VersionSect->CommonHeader.Type = SectType; 1457 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff); 1458 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8); 1459 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16); 1460 VersionSect->BuildNumber = (UINT16) VersionNumber; 1461 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString); 1462 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index); 1463 break; 1464 1465 case EFI_SECTION_USER_INTERFACE: 1466 Index = sizeof (EFI_COMMON_SECTION_HEADER); 1467 // 1468 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null. 1469 // 1470 Index += (strlen (StringBuffer) * 2) + 2; 1471 OutFileBuffer = (UINT8 *) malloc (Index); 1472 if (OutFileBuffer == NULL) { 1473 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); 1474 goto Finish; 1475 } 1476 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer; 1477 UiSect->CommonHeader.Type = SectType; 1478 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff); 1479 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8); 1480 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16); 1481 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString); 1482 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index); 1483 break; 1484 1485 case EFI_SECTION_ALL: 1486 // 1487 // read all input file contents into a buffer 1488 // first get the size of all file contents 1489 // 1490 Status = GetSectionContents ( 1491 InputFileName, 1492 InputFileAlign, 1493 InputFileNum, 1494 OutFileBuffer, 1495 &InputLength 1496 ); 1497 1498 if (Status == EFI_BUFFER_TOO_SMALL) { 1499 OutFileBuffer = (UINT8 *) malloc (InputLength); 1500 if (OutFileBuffer == NULL) { 1501 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); 1502 goto Finish; 1503 } 1504 // 1505 // read all input file contents into a buffer 1506 // 1507 Status = GetSectionContents ( 1508 InputFileName, 1509 InputFileAlign, 1510 InputFileNum, 1511 OutFileBuffer, 1512 &InputLength 1513 ); 1514 } 1515 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength); 1516 break; 1517 default: 1518 // 1519 // All other section types are caught by default (they're all the same) 1520 // 1521 Status = GenSectionCommonLeafSection ( 1522 InputFileName, 1523 InputFileNum, 1524 SectType, 1525 &OutFileBuffer 1526 ); 1527 break; 1528 } 1529 1530 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) { 1531 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status); 1532 goto Finish; 1533 } 1534 1535 // 1536 // Get output file length 1537 // 1538 if (SectType != EFI_SECTION_ALL) { 1539 SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer; 1540 InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff; 1541 if (InputLength == 0xffffff) { 1542 InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize; 1543 } 1544 } 1545 1546 // 1547 // Write the output file 1548 // 1549 OutFile = fopen (LongFilePath (OutputFileName), "wb"); 1550 if (OutFile == NULL) { 1551 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName); 1552 goto Finish; 1553 } 1554 1555 fwrite (OutFileBuffer, InputLength, 1, OutFile); 1556 1557 Finish: 1558 if (InputFileName != NULL) { 1559 free (InputFileName); 1560 } 1561 1562 if (InputFileAlign != NULL) { 1563 free (InputFileAlign); 1564 } 1565 1566 if (OutFileBuffer != NULL) { 1567 free (OutFileBuffer); 1568 } 1569 1570 if (OutFile != NULL) { 1571 fclose (OutFile); 1572 } 1573 1574 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); 1575 1576 return GetUtilityStatus (); 1577 } 1578