3 Copyright (c) 2004, Intel Corporation
\r
4 All rights reserved. This program and the accompanying materials
\r
5 are licensed and made available under the terms and conditions of the BSD License
\r
6 which accompanies this distribution. The full text of the license may be found at
\r
7 http://opensource.org/licenses/bsd-license.php
\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
18 Creates output file that is a properly formed section per the FV spec.
\r
26 #include <Common/UefiBaseTypes.h>
\r
27 #include <Common/FirmwareVolumeImageFormat.h>
\r
28 #include <Protocol/GuidedSectionExtraction.h>
\r
30 #include "CommonLib.h"
\r
31 #include "Compress.h"
\r
33 #include "EfiUtilityMsgs.h"
\r
36 // GenSec Tool Information
\r
38 #define UTILITY_NAME "GenSec"
\r
39 #define UTILITY_MAJOR_VERSION 1
\r
40 #define UTILITY_MINOR_VERSION 0
\r
42 #define MAXIMUM_INPUT_FILE_NUM 10
\r
43 #define MAX_SECTION_SIZE 0x1000000
\r
45 CHAR8 *SectionTypeName[] = {
\r
46 NULL, // 0x00 - reserved
\r
47 "EFI_SECTION_COMPRESSION", // 0x01
\r
48 "EFI_SECTION_GUID_DEFINED", // 0x02
\r
49 NULL, // 0x03 - reserved
\r
50 NULL, // 0x04 - reserved
\r
51 NULL, // 0x05 - reserved
\r
52 NULL, // 0x06 - reserved
\r
53 NULL, // 0x07 - reserved
\r
54 NULL, // 0x08 - reserved
\r
55 NULL, // 0x09 - reserved
\r
56 NULL, // 0x0A - reserved
\r
57 NULL, // 0x0B - reserved
\r
58 NULL, // 0x0C - reserved
\r
59 NULL, // 0x0D - reserved
\r
60 NULL, // 0x0E - reserved
\r
61 NULL, // 0x0F - reserved
\r
62 "EFI_SECTION_PE32", // 0x10
\r
63 "EFI_SECTION_PIC", // 0x11
\r
64 "EFI_SECTION_TE", // 0x12
\r
65 "EFI_SECTION_DXE_DEPEX", // 0x13
\r
66 "EFI_SECTION_VERSION", // 0x14
\r
67 "EFI_SECTION_USER_INTERFACE", // 0x15
\r
68 "EFI_SECTION_COMPATIBILITY16", // 0x16
\r
69 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
\r
70 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
\r
71 "EFI_SECTION_RAW", // 0x19
\r
73 "EFI_SECTION_PEI_DEPEX" // 0x1B
\r
76 CHAR8 *CompressionTypeName[] = { "PI_NONE", "PI_STD" };
\r
77 CHAR8 *GUIDedSectionAttribue[] = { NULL, "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
\r
80 // Crc32 GUID section related definitions.
\r
83 EFI_GUID_DEFINED_SECTION GuidSectionHeader;
\r
84 UINT32 CRC32Checksum;
\r
85 } CRC32_SECTION_HEADER;
\r
87 EFI_GUID gZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
\r
88 EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
\r
97 Routine Description:
\r
99 Print out version information for this utility.
\r
111 printf ("%s v%d.%d - EDKII Utility to create output file with formed section per the PI spec.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
\r
112 printf ("Copyright (c) 2007 Intel Corporation. All rights reserved.\n");
\r
123 printf ("\nUsage: " UTILITY_NAME " [inputfilename]\n\
\r
124 -o, --outputfile [FileName]\n\
\r
125 -s, --SectionType <EFI_SECTION_COMPRESSION|\n\
\r
126 EFI_SECTION_GUID_DEFINED|\n\
\r
127 EFI_SECTION_PE32|\n\
\r
128 EFI_SECTION_PIC|\n\
\r
130 EFI_SECTION_DXE_DEPEX|\n\
\r
131 EFI_SECTION_VERSION|\n\
\r
132 EFI_SECTION_USER_INTERFACE|\n\
\r
133 EFI_SECTION_COMPATIBILITY16|\n\
\r
134 EFI_SECTION_FIRMWARE_VOLUME_IMAGE|\n\
\r
135 EFI_SECTION_FREEFORM_SUBTYPE_GUID|\n\
\r
136 EFI_SECTION_RAW|\n\
\r
137 EFI_SECTION_PEI_DEPEX>\n\
\r
138 -c, --compress <PI_NONE|PI_STD>\n\
\r
139 -g, --vendorguid [GuidValue (########-####-####-####-############)]\n\
\r
140 -r, --attributes <PROCESSING_REQUIRED|AUTH_STATUS_VALID>\n\
\r
141 -n, --name \"string\"\n\
\r
142 -j, --buildnumber #### (0000~9999)\n\
\r
148 Ascii2UnicodeWriteString (
\r
159 // Next, write out the string... Convert ASCII to Unicode in the process.
\r
163 fwrite (&String[Index], 1, 1, OutFile);
\r
164 fwrite (&AsciiNull, 1, 1, OutFile);
\r
165 } while (String[Index++] != 0);
\r
169 GenSectionCommonLeafSection (
\r
170 CHAR8 **InputFileName,
\r
171 UINT32 InputFileNum,
\r
177 Routine Description:
\r
179 Generate a leaf section of type other than EFI_SECTION_VERSION
\r
180 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
\r
181 The function won't validate the input file's contents. For
\r
182 common leaf sections, the input file may be a binary file.
\r
183 The utility will add section header to the file.
\r
187 InputFileName - Name of the input file.
\r
189 InputFileNum - Number of input files. Should be 1 for leaf section.
\r
191 SectionType - A valid section type string
\r
193 OutFile - Output file handle
\r
197 STATUS_ERROR - can't continue
\r
198 STATUS_SUCCESS - successful return
\r
202 UINT32 InputFileLength;
\r
205 UINT32 TotalLength;
\r
206 EFI_COMMON_SECTION_HEADER CommonSect;
\r
209 if (InputFileNum > 1) {
\r
210 Error (NULL, 0, 0, "invalid parameter", "more than one input file specified");
\r
211 return STATUS_ERROR;
\r
212 } else if (InputFileNum < 1) {
\r
213 Error (NULL, 0, 0, "no input file specified", NULL);
\r
214 return STATUS_ERROR;
\r
217 // Open the input file
\r
219 InFile = fopen (InputFileName[0], "rb");
\r
220 if (InFile == NULL) {
\r
221 Error (NULL, 0, 0, InputFileName[0], "failed to open input file");
\r
222 return STATUS_ERROR;
\r
225 Status = STATUS_ERROR;
\r
228 // Seek to the end of the input file so we can determine its size
\r
230 fseek (InFile, 0, SEEK_END);
\r
231 InputFileLength = ftell (InFile);
\r
232 fseek (InFile, 0, SEEK_SET);
\r
234 // Fill in the fields in the local section header structure
\r
236 CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
\r
237 TotalLength = sizeof (CommonSect) + InputFileLength;
\r
239 // Size must fit in 3 bytes
\r
241 if (TotalLength >= MAX_SECTION_SIZE) {
\r
242 Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit(%dM).", TotalLength, MAX_SECTION_SIZE>>20);
\r
246 // Now copy the size into the section header and write out the section header
\r
248 memcpy (&CommonSect.Size, &TotalLength, 3);
\r
249 fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
\r
251 // Allocate a buffer to read in the contents of the input file. Then
\r
252 // read it in as one block and write it to the output file.
\r
254 if (InputFileLength != 0) {
\r
255 Buffer = (UINT8 *) malloc ((size_t) InputFileLength);
\r
256 if (Buffer == NULL) {
\r
257 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
\r
261 if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) {
\r
262 Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file");
\r
266 if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) {
\r
267 Error (NULL, 0, 0, "failed to write to output file", NULL);
\r
272 Status = STATUS_SUCCESS;
\r
276 if (Buffer != NULL) {
\r
284 GetSectionContents (
\r
285 CHAR8 **InputFileName,
\r
286 UINT32 InputFileNum,
\r
288 UINT32 *BufferLength
\r
292 Routine Description:
\r
294 Get the contents of all section files specified in InputFileName
\r
299 InputFileName - Name of the input file.
\r
301 InputFileNum - Number of input files. Should be at least 1.
\r
303 FileBuffer - Output buffer to contain data
\r
305 BufferLength - On input, this is size of the FileBuffer.
\r
306 On output, this is the actual length of the data.
\r
310 EFI_SUCCESS on successful return
\r
311 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
\r
312 EFI_ABORTED if unable to open input file.
\r
313 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
\r
321 if (InputFileNum < 1) {
\r
322 Error (NULL, 0, 0, "must specify at least one input file", NULL);
\r
323 return EFI_INVALID_PARAMETER;
\r
326 if (BufferLength == NULL) {
\r
327 Error (NULL, 0, 0, "BufferLength can't be NULL", NULL);
\r
328 return EFI_INVALID_PARAMETER;
\r
333 // Go through our array of file names and copy their contents
\r
334 // to the output buffer.
\r
336 for (Index = 0; Index < InputFileNum; Index++) {
\r
338 // make sure section ends on a DWORD boundary
\r
340 while ((Size & 0x03) != 0) {
\r
341 if (FileBuffer != NULL && Size < *BufferLength) {
\r
342 FileBuffer[Size] = 0;
\r
348 // Open file and read contents
\r
350 InFile = fopen (InputFileName[Index], "rb");
\r
351 if (InFile == NULL) {
\r
352 Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");
\r
353 return EFI_ABORTED;
\r
356 fseek (InFile, 0, SEEK_END);
\r
357 FileSize = ftell (InFile);
\r
358 fseek (InFile, 0, SEEK_SET);
\r
360 // Now read the contents of the file into the buffer
\r
361 // Buffer must be enough to contain the file content.
\r
363 if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) {
\r
364 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
\r
365 Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");
\r
367 return EFI_ABORTED;
\r
375 if (Size > *BufferLength) {
\r
376 *BufferLength = Size;
\r
377 return EFI_BUFFER_TOO_SMALL;
\r
379 *BufferLength = Size;
\r
380 return EFI_SUCCESS;
\r
385 GenSectionCompressionSection (
\r
386 CHAR8 **InputFileName,
\r
387 UINT32 InputFileNum,
\r
388 UINT8 SectCompSubType,
\r
393 Routine Description:
\r
395 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
\r
396 Input file must be already sectioned. The function won't validate
\r
397 the input files' contents. Caller should hand in files already
\r
398 with section header.
\r
402 InputFileName - Name of the input file.
\r
404 InputFileNum - Number of input files. Should be at least 1.
\r
406 SectCompSubType - Specify the compression algorithm requested.
\r
408 OutFile - Output file handle
\r
412 EFI_SUCCESS on successful return
\r
413 EFI_INVALID_PARAMETER if InputFileNum is less than 1
\r
414 EFI_ABORTED if unable to open input file.
\r
415 EFI_OUT_OF_RESOURCES No resource to complete the operation.
\r
418 UINT32 TotalLength;
\r
419 UINT32 InputLength;
\r
420 UINT32 CompressedLength;
\r
422 UINT8 *OutputBuffer;
\r
424 EFI_COMPRESSION_SECTION CompressionSect;
\r
425 COMPRESS_FUNCTION CompressFunction;
\r
429 OutputBuffer = NULL;
\r
430 CompressedLength = 0;
\r
432 // read all input file contents into a buffer
\r
433 // first get the size of all file contents
\r
435 Status = GetSectionContents (
\r
442 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
443 FileBuffer = (UINT8 *) malloc (InputLength);
\r
444 if (FileBuffer == NULL) {
\r
445 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
\r
446 return EFI_OUT_OF_RESOURCES;
\r
449 // read all input file contents into a buffer
\r
451 Status = GetSectionContents (
\r
459 if (EFI_ERROR (Status)) {
\r
460 if (FileBuffer != NULL) {
\r
466 CompressFunction = NULL;
\r
469 // Now data is in FileBuffer, compress the data
\r
471 switch (SectCompSubType) {
\r
472 case EFI_NOT_COMPRESSED:
\r
473 CompressedLength = InputLength;
\r
476 case EFI_STANDARD_COMPRESSION:
\r
477 CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
\r
481 Error (NULL, 0, 0, "unknown compression type", NULL);
\r
483 return EFI_ABORTED;
\r
486 if (CompressFunction != NULL) {
\r
488 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
\r
489 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
490 OutputBuffer = malloc (CompressedLength);
\r
491 if (!OutputBuffer) {
\r
493 return EFI_OUT_OF_RESOURCES;
\r
496 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
\r
500 FileBuffer = OutputBuffer;
\r
502 if (EFI_ERROR (Status)) {
\r
503 if (FileBuffer != NULL) {
\r
511 TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);
\r
512 if (TotalLength >= MAX_SECTION_SIZE) {
\r
513 Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
\r
514 if (FileBuffer != NULL) {
\r
517 if (OutputBuffer != NULL) {
\r
518 free (OutputBuffer);
\r
520 return STATUS_ERROR;
\r
524 // Add the section header for the compressed data
\r
526 CompressionSect.CommonHeader.Type = EFI_SECTION_COMPRESSION;
\r
527 CompressionSect.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
\r
528 CompressionSect.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
\r
529 CompressionSect.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
\r
530 CompressionSect.CompressionType = SectCompSubType;
\r
531 CompressionSect.UncompressedLength = InputLength;
\r
533 fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);
\r
534 fwrite (FileBuffer, CompressedLength, 1, OutFile);
\r
536 return EFI_SUCCESS;
\r
540 GenSectionGuidDefinedSection (
\r
541 CHAR8 **InputFileName,
\r
542 UINT32 InputFileNum,
\r
543 EFI_GUID *VendorGuid,
\r
544 UINT16 DataAttribute,
\r
549 Routine Description:
\r
551 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
\r
552 Input file must be already sectioned. The function won't validate
\r
553 the input files' contents. Caller should hand in files already
\r
554 with section header.
\r
558 InputFileName - Name of the input file.
\r
560 InputFileNum - Number of input files. Should be at least 1.
\r
562 VendorGuid - Specify vendor guid value.
\r
564 DataAttribute - Specify attribute for the vendor guid data.
\r
566 OutFile - Output file handle
\r
570 EFI_SUCCESS on successful return
\r
571 EFI_INVALID_PARAMETER if InputFileNum is less than 1
\r
572 EFI_ABORTED if unable to open input file.
\r
573 EFI_OUT_OF_RESOURCES No resource to complete the operation.
\r
577 UINT32 TotalLength;
\r
578 UINT32 InputLength;
\r
580 UINT32 Crc32Checksum;
\r
582 CRC32_SECTION_HEADER Crc32GuidSect;
\r
583 EFI_GUID_DEFINED_SECTION VendorGuidSect;
\r
588 // read all input file contents into a buffer
\r
589 // first get the size of all file contents
\r
591 Status = GetSectionContents (
\r
598 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
599 FileBuffer = (UINT8 *) malloc (InputLength);
\r
600 if (FileBuffer == NULL) {
\r
601 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
\r
602 return EFI_OUT_OF_RESOURCES;
\r
605 // read all input file contents into a buffer
\r
607 Status = GetSectionContents (
\r
615 if (EFI_ERROR (Status)) {
\r
616 if (FileBuffer != NULL) {
\r
623 // Now data is in FileBuffer
\r
625 if (CompareGuid (VendorGuid, &gEfiCrc32SectionGuid) == 0) {
\r
627 // Default Guid section is CRC32.
\r
630 CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);
\r
632 TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);
\r
633 if (TotalLength >= MAX_SECTION_SIZE) {
\r
634 Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
\r
636 return STATUS_ERROR;
\r
639 Crc32GuidSect.GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
\r
640 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
\r
641 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
\r
642 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
\r
643 memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
\r
644 Crc32GuidSect.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
\r
645 Crc32GuidSect.GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);
\r
646 Crc32GuidSect.CRC32Checksum = Crc32Checksum;
\r
647 fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);
\r
650 TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION);
\r
651 if (TotalLength >= MAX_SECTION_SIZE) {
\r
652 Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
\r
654 return STATUS_ERROR;
\r
657 VendorGuidSect.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
\r
658 VendorGuidSect.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
\r
659 VendorGuidSect.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
\r
660 VendorGuidSect.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
\r
661 memcpy (&(VendorGuidSect.SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
\r
662 VendorGuidSect.Attributes = DataAttribute;
\r
663 VendorGuidSect.DataOffset = sizeof (EFI_GUID_DEFINED_SECTION);
\r
664 fwrite (&VendorGuidSect, sizeof (EFI_GUID_DEFINED_SECTION), 1, OutFile);
\r
667 fwrite (FileBuffer, InputLength, 1, OutFile);
\r
670 return EFI_SUCCESS;
\r
680 Routine Description:
\r
686 command line parameters
\r
690 EFI_SUCCESS Section header successfully generated and section concatenated.
\r
691 EFI_ABORTED Could not generate the section
\r
692 EFI_OUT_OF_RESOURCES No resource to complete the operation.
\r
697 UINT32 InputFileNum;
\r
700 CHAR8 **InputFileName;
\r
701 CHAR8 *OutputFileName;
\r
702 CHAR8 *SectionName;
\r
703 CHAR8 *CompressionName;
\r
704 CHAR8 *StringBuffer;
\r
705 EFI_GUID VendorGuid = gZeroGuid;
\r
706 INT32 VersionNumber;
\r
708 UINT8 SectCompSubType;
\r
709 UINT16 SectGuidAttribute;
\r
710 EFI_COMMON_SECTION_HEADER CommonSect;
\r
711 UINT32 InputLength;
\r
713 BOOLEAN AllocatedFlag;
\r
716 InputFileName = NULL;
\r
717 OutputFileName = NULL;
\r
718 SectionName = NULL;
\r
719 CompressionName = NULL;
\r
726 SectType = EFI_SECTION_ALL;
\r
727 SectCompSubType = 0;
\r
728 SectGuidAttribute = 0;
\r
731 AllocatedFlag = FALSE;
\r
732 Status = STATUS_SUCCESS;
\r
735 SetUtilityName (UTILITY_NAME);
\r
739 return STATUS_ERROR;
\r
743 // Parse command line
\r
748 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
\r
750 return STATUS_ERROR;
\r
753 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--version") == 0)) {
\r
755 return STATUS_ERROR;
\r
759 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
\r
760 SectionName = argv[1];
\r
766 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
\r
767 OutputFileName = argv[1];
\r
773 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
\r
774 CompressionName = argv[1];
\r
780 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendorguid") == 0)) {
\r
781 StringToGuid (argv[1], &VendorGuid);
\r
787 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
\r
788 if (stricmp (argv[1], GUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
\r
789 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
\r
790 } else if (stricmp (argv[1], GUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
\r
791 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
\r
793 Error (NULL, 0, 0, argv[1], "unknown Guid Section Attribute");
\r
802 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
\r
803 StringBuffer = argv[1];
\r
809 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
\r
811 // Verify string is a integrator number
\r
813 for (Index = 0; Index < strlen (argv[1]); Index++) {
\r
814 if ((argv[1][Index] != '-') && (isdigit (argv[1][Index]) == 0)) {
\r
815 Error (NULL, 0, 0, NULL, "ERROR: %s is not a valid integer.", argv[1]);
\r
816 Status = EFI_ABORTED;
\r
821 sscanf (argv[1], "%d", &VersionNumber);
\r
828 // Get Input file name
\r
830 if ((InputFileNum == 0) && (InputFileName == NULL)) {
\r
831 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
\r
832 if (InputFileName == NULL) {
\r
833 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
\r
834 return EFI_OUT_OF_RESOURCES;
\r
837 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
\r
838 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
\r
840 // InputFileName buffer too small, need to realloc
\r
842 InputFileName = (CHAR8 **) realloc (
\r
844 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
\r
847 if (InputFileName == NULL) {
\r
848 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
\r
849 return EFI_OUT_OF_RESOURCES;
\r
852 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
\r
855 InputFileName[InputFileNum++] = argv[0];
\r
861 // Parse all command line parameters to get the corresponding section type.
\r
863 if (SectionName == NULL) {
\r
865 // No specified Section type, default is SECTION_ALL.
\r
867 SectType = EFI_SECTION_ALL;
\r
868 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
\r
869 SectType = EFI_SECTION_COMPRESSION;
\r
870 if (CompressionName == NULL) {
\r
872 // Default is PI_STD compression algorithm.
\r
874 SectCompSubType = EFI_STANDARD_COMPRESSION;
\r
875 } else if (stricmp (CompressionName, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
\r
876 SectCompSubType = EFI_NOT_COMPRESSED;
\r
877 } else if (stricmp (CompressionName, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
\r
878 SectCompSubType = EFI_STANDARD_COMPRESSION;
\r
880 Error (NULL, 0, 0, CompressionName, "unknown compression type");
\r
884 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
\r
885 SectType = EFI_SECTION_GUID_DEFINED;
\r
887 if (CompareGuid (&VendorGuid, &gZeroGuid) == 0) {
\r
888 memcpy (&VendorGuid, &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
\r
891 if (SectGuidAttribute == 0) {
\r
892 SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
\r
894 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PE32]) == 0) {
\r
895 SectType = EFI_SECTION_PE32;
\r
896 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PIC]) == 0) {
\r
897 SectType = EFI_SECTION_PIC;
\r
898 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_TE]) == 0) {
\r
899 SectType = EFI_SECTION_TE;
\r
900 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
\r
901 SectType = EFI_SECTION_DXE_DEPEX;
\r
902 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_VERSION]) == 0) {
\r
903 SectType = EFI_SECTION_VERSION;
\r
904 if (VersionNumber < 0 || VersionNumber > 9999) {
\r
905 Error (NULL, 0, 0, NULL, "%d is illegal version number\n", VersionNumber);
\r
909 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
\r
910 SectType = EFI_SECTION_USER_INTERFACE;
\r
911 if (StringBuffer[0] == '\0') {
\r
912 Error (NULL, 0, 0, "user interface string not specified", NULL);
\r
916 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
\r
917 SectType = EFI_SECTION_COMPATIBILITY16;
\r
918 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
\r
919 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
\r
920 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
\r
921 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
\r
922 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_RAW]) == 0) {
\r
923 SectType = EFI_SECTION_RAW;
\r
924 } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
\r
925 SectType = EFI_SECTION_PEI_DEPEX;
\r
927 Error (NULL, 0, 0, SectionName, "unknown section type");
\r
932 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
\r
934 // The input file are required for those section type.
\r
935 // The file are from stdin.
\r
937 if (InputFileNum == 0) {
\r
939 AllocatedFlag = TRUE;
\r
942 // Init InputFileName pointer list
\r
944 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
\r
945 if (InputFileName == NULL) {
\r
946 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
\r
947 return EFI_OUT_OF_RESOURCES;
\r
949 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
\r
952 if ((InputFileNum != 0) && (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0)) {
\r
954 // InputFileName buffer too small, need to realloc
\r
956 InputFileName = (CHAR8 **) realloc (
\r
958 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
\r
961 if (InputFileName == NULL) {
\r
962 for (Index = 0; Index < InputFileNum; Index ++) {
\r
963 free (InputFileName [InputFileNum]);
\r
965 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
\r
966 return EFI_OUT_OF_RESOURCES;
\r
968 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
\r
971 InputFileName [InputFileNum] = (CHAR8 *) malloc (_MAX_PATH);
\r
972 if (InputFileName == NULL) {
\r
973 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
\r
974 for (Index = 0; Index < InputFileNum; Index ++) {
\r
975 free (InputFileName [InputFileNum]);
\r
977 free (InputFileName);
\r
978 return EFI_OUT_OF_RESOURCES;
\r
980 } while (fscanf (stdin, "%s", InputFileName[InputFileNum++]) != EOF);
\r
982 // Free the last memory space because it doesn't have data.
\r
985 free (InputFileName[InputFileNum]);
\r
990 // Open output file
\r
992 if (OutputFileName == NULL) {
\r
995 OutFile = fopen (OutputFileName, "wb");
\r
998 if (OutFile == NULL) {
\r
999 Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
\r
1004 // At this point, we've fully validated the command line, and opened appropriate
\r
1005 // files, so let's go and do what we've been asked to do...
\r
1008 // Within this switch, build and write out the section header including any
\r
1009 // section type specific pieces. If there's an input file, it's tacked on later
\r
1011 switch (SectType) {
\r
1012 case EFI_SECTION_COMPRESSION:
\r
1013 Status = GenSectionCompressionSection (
\r
1021 case EFI_SECTION_GUID_DEFINED:
\r
1022 Status = GenSectionGuidDefinedSection (
\r
1026 SectGuidAttribute,
\r
1031 case EFI_SECTION_VERSION:
\r
1032 CommonSect.Type = (EFI_SECTION_TYPE) SectType;
\r
1034 Index = sizeof (CommonSect);
\r
1036 // 2 bytes for the build number UINT16
\r
1040 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
\r
1042 Index += (strlen (StringBuffer) * 2) + 2;
\r
1043 memcpy (&CommonSect.Size, &Index, 3);
\r
1044 fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
\r
1045 fwrite (&VersionNumber, sizeof (UINT16), 1, OutFile);
\r
1046 Ascii2UnicodeWriteString (StringBuffer, OutFile);
\r
1049 case EFI_SECTION_USER_INTERFACE:
\r
1050 CommonSect.Type = (EFI_SECTION_TYPE) SectType;
\r
1051 Index = sizeof (CommonSect);
\r
1053 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
\r
1055 Index += (strlen (StringBuffer) * 2) + 2;
\r
1056 memcpy (&CommonSect.Size, &Index, 3);
\r
1057 fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
\r
1058 Ascii2UnicodeWriteString (StringBuffer, OutFile);
\r
1061 case EFI_SECTION_ALL:
\r
1063 // read all input file contents into a buffer
\r
1064 // first get the size of all file contents
\r
1066 Status = GetSectionContents (
\r
1073 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
1074 FileBuffer = (UINT8 *) malloc (InputLength);
\r
1075 if (FileBuffer == NULL) {
\r
1076 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
\r
1080 // read all input file contents into a buffer
\r
1082 Status = GetSectionContents (
\r
1090 if (Status == EFI_SUCCESS) {
\r
1091 fwrite (FileBuffer, InputLength, 1, OutFile);
\r
1094 if (FileBuffer != NULL) {
\r
1095 free (FileBuffer);
\r
1101 // All other section types are caught by default (they're all the same)
\r
1103 Status = GenSectionCommonLeafSection (
\r
1113 if (AllocatedFlag == TRUE) {
\r
1114 for (Index = 0; Index < InputFileNum; Index ++) {
\r
1115 free (InputFileName[Index]);
\r
1119 if (InputFileName != NULL) {
\r
1120 free (InputFileName);
\r
1123 if (OutFile != NULL) {
\r
1126 // If we had errors, then delete the output file
\r
1128 if (GetUtilityStatus () == STATUS_ERROR) {
\r
1129 remove (OutputFileName);
\r
1133 return GetUtilityStatus ();
\r