3 Copyright (c) 2004 - 2008, 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 PI spec.
\r
26 #include <Common/UefiBaseTypes.h>
\r
27 #include <Common/PiFirmwareFile.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 0
\r
40 #define UTILITY_MINOR_VERSION 1
\r
42 #define MAX_SECTION_SIZE 0x1000000
\r
44 STATIC CHAR8 *mSectionTypeName[] = {
\r
45 NULL, // 0x00 - reserved
\r
46 "EFI_SECTION_COMPRESSION", // 0x01
\r
47 "EFI_SECTION_GUID_DEFINED", // 0x02
\r
48 NULL, // 0x03 - reserved
\r
49 NULL, // 0x04 - reserved
\r
50 NULL, // 0x05 - reserved
\r
51 NULL, // 0x06 - reserved
\r
52 NULL, // 0x07 - reserved
\r
53 NULL, // 0x08 - reserved
\r
54 NULL, // 0x09 - reserved
\r
55 NULL, // 0x0A - reserved
\r
56 NULL, // 0x0B - reserved
\r
57 NULL, // 0x0C - reserved
\r
58 NULL, // 0x0D - reserved
\r
59 NULL, // 0x0E - reserved
\r
60 NULL, // 0x0F - reserved
\r
61 "EFI_SECTION_PE32", // 0x10
\r
62 "EFI_SECTION_PIC", // 0x11
\r
63 "EFI_SECTION_TE", // 0x12
\r
64 "EFI_SECTION_DXE_DEPEX", // 0x13
\r
65 "EFI_SECTION_VERSION", // 0x14
\r
66 "EFI_SECTION_USER_INTERFACE", // 0x15
\r
67 "EFI_SECTION_COMPATIBILITY16", // 0x16
\r
68 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
\r
69 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
\r
70 "EFI_SECTION_RAW", // 0x19
\r
72 "EFI_SECTION_PEI_DEPEX" // 0x1B
\r
75 STATIC CHAR8 *mCompressionTypeName[] = { "PI_NONE", "PI_STD" };
\r
77 #define EFI_GUIDED_SECTION_NONE 0x80
\r
78 STATIC CHAR8 *mGUIDedSectionAttribue[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
\r
81 // Crc32 GUID section related definitions.
\r
84 EFI_GUID_DEFINED_SECTION GuidSectionHeader;
\r
85 UINT32 CRC32Checksum;
\r
86 } CRC32_SECTION_HEADER;
\r
88 STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
\r
89 STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
\r
98 Routine Description:
\r
100 Print out version information for this utility.
\r
112 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
\r
122 Routine Description:
\r
124 Print Help message.
\r
139 fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);
\r
142 // Copyright declaration
\r
144 fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
\r
149 fprintf (stdout, "Options:\n");
\r
150 fprintf (stdout, " -o FileName, --outputfile FileName\n\
\r
151 File is the SectionFile to be created.\n");
\r
152 fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\
\r
153 SectionType defined in PI spec is one type of\n\
\r
154 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
\r
155 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
\r
156 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
\r
157 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
\r
158 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
\r
159 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
\r
160 EFI_SECTION_PEI_DEPEX. if -s option is not given, \n\
\r
161 EFI_SECTION_ALL is default section type.\n");
\r
162 fprintf (stdout, " -c [Type], --compress [Type]\n\
\r
163 Compress method type can be PI_NONE or PI_STD.\n\
\r
164 if -c option is not given, PI_STD is default type.\n");
\r
165 fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\
\r
166 GuidValue is one specific vendor guid value.\n\
\r
167 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
\r
168 fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
\r
169 GuidHeaderLength is the size of header of guided data\n");
\r
170 fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\
\r
171 GuidAttr is guid section atttributes, which may be\n\
\r
172 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
\r
173 if -r option is not given, default PROCESSING_REQUIRED\n");
\r
174 fprintf (stdout, " -n String, --name String\n\
\r
175 String is a NULL terminated string used in Ui section.\n");
\r
176 fprintf (stdout, " -j Number, --buildnumber Number\n\
\r
177 Number is an integer value between 0000 and 9999\n\
\r
178 used in Ver section.\n");
\r
179 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
\r
180 fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
\r
181 fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
\r
182 fprintf (stdout, " --version Show program's version number and exit.\n");
\r
183 fprintf (stdout, " -h, --help Show this help message and exit.\n");
\r
187 Ascii2UnicodeString (
\r
193 Routine Description:
\r
195 Write ascii string as unicode string format to FILE
\r
199 String - Pointer to string that is written to FILE.
\r
200 UniString - Pointer to unicode string
\r
208 while (*String != '\0') {
\r
209 *(UniString++) = (CHAR16) *(String++);
\r
212 // End the UniString with a NULL.
\r
218 GenSectionCommonLeafSection (
\r
219 CHAR8 **InputFileName,
\r
220 UINT32 InputFileNum,
\r
222 UINT8 **OutFileBuffer
\r
226 Routine Description:
\r
228 Generate a leaf section of type other than EFI_SECTION_VERSION
\r
229 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
\r
230 The function won't validate the input file's contents. For
\r
231 common leaf sections, the input file may be a binary file.
\r
232 The utility will add section header to the file.
\r
236 InputFileName - Name of the input file.
\r
238 InputFileNum - Number of input files. Should be 1 for leaf section.
\r
240 SectionType - A valid section type string
\r
242 OutFileBuffer - Buffer pointer to Output file contents
\r
246 STATUS_ERROR - can't continue
\r
247 STATUS_SUCCESS - successful return
\r
251 UINT32 InputFileLength;
\r
254 UINT32 TotalLength;
\r
255 EFI_COMMON_SECTION_HEADER *CommonSect;
\r
258 if (InputFileNum > 1) {
\r
259 Error (NULL, 0, 2000, "Invalid paramter", "more than one input file specified");
\r
260 return STATUS_ERROR;
\r
261 } else if (InputFileNum < 1) {
\r
262 Error (NULL, 0, 2000, "Invalid paramter", "no input file specified");
\r
263 return STATUS_ERROR;
\r
266 // Open the input file
\r
268 InFile = fopen (InputFileName[0], "rb");
\r
269 if (InFile == NULL) {
\r
270 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);
\r
271 return STATUS_ERROR;
\r
274 Status = STATUS_ERROR;
\r
277 // Seek to the end of the input file so we can determine its size
\r
279 fseek (InFile, 0, SEEK_END);
\r
280 InputFileLength = ftell (InFile);
\r
281 fseek (InFile, 0, SEEK_SET);
\r
282 DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %d bytes", InputFileName[0], InputFileLength);
\r
283 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;
\r
285 // Size must fit in 3 bytes
\r
287 if (TotalLength >= MAX_SECTION_SIZE) {
\r
288 Error (NULL, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%dM).", InputFileName[0], TotalLength, MAX_SECTION_SIZE>>20);
\r
291 VerboseMsg ("the size of the created section file is %d bytes", TotalLength);
\r
293 // Fill in the fields in the local section header structure
\r
295 Buffer = (UINT8 *) malloc ((size_t) TotalLength);
\r
296 if (Buffer == NULL) {
\r
297 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
300 CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;
\r
301 CommonSect->Type = SectionType;
\r
302 CommonSect->Size[0] = (UINT8) (TotalLength & 0xff);
\r
303 CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
\r
304 CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
\r
307 // read data from the input file.
\r
309 if (InputFileLength != 0) {
\r
310 if (fread (Buffer + sizeof (EFI_COMMON_SECTION_HEADER), (size_t) InputFileLength, 1, InFile) != 1) {
\r
311 Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);
\r
317 // Set OutFileBuffer
\r
319 *OutFileBuffer = Buffer;
\r
320 Status = STATUS_SUCCESS;
\r
329 GetSectionContents (
\r
330 CHAR8 **InputFileName,
\r
331 UINT32 InputFileNum,
\r
333 UINT32 *BufferLength
\r
337 Routine Description:
\r
339 Get the contents of all section files specified in InputFileName
\r
344 InputFileName - Name of the input file.
\r
346 InputFileNum - Number of input files. Should be at least 1.
\r
348 FileBuffer - Output buffer to contain data
\r
350 BufferLength - On input, this is size of the FileBuffer.
\r
351 On output, this is the actual length of the data.
\r
355 EFI_SUCCESS on successful return
\r
356 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
\r
357 EFI_ABORTED if unable to open input file.
\r
358 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
\r
366 if (InputFileNum < 1) {
\r
367 Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file");
\r
368 return EFI_INVALID_PARAMETER;
\r
371 if (BufferLength == NULL) {
\r
372 Error (NULL, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");
\r
373 return EFI_INVALID_PARAMETER;
\r
378 // Go through our array of file names and copy their contents
\r
379 // to the output buffer.
\r
381 for (Index = 0; Index < InputFileNum; Index++) {
\r
383 // make sure section ends on a DWORD boundary
\r
385 while ((Size & 0x03) != 0) {
\r
386 if (FileBuffer != NULL && Size < *BufferLength) {
\r
387 FileBuffer[Size] = 0;
\r
393 // Open file and read contents
\r
395 InFile = fopen (InputFileName[Index], "rb");
\r
396 if (InFile == NULL) {
\r
397 Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);
\r
398 return EFI_ABORTED;
\r
401 fseek (InFile, 0, SEEK_END);
\r
402 FileSize = ftell (InFile);
\r
403 fseek (InFile, 0, SEEK_SET);
\r
404 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %d bytes", InputFileName[Index], FileSize);
\r
406 // Now read the contents of the file into the buffer
\r
407 // Buffer must be enough to contain the file content.
\r
409 if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) {
\r
410 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
\r
411 Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);
\r
413 return EFI_ABORTED;
\r
422 // Set the real required buffer size.
\r
424 if (Size > *BufferLength) {
\r
425 *BufferLength = Size;
\r
426 return EFI_BUFFER_TOO_SMALL;
\r
428 *BufferLength = Size;
\r
429 return EFI_SUCCESS;
\r
434 GenSectionCompressionSection (
\r
435 CHAR8 **InputFileName,
\r
436 UINT32 InputFileNum,
\r
437 UINT8 SectCompSubType,
\r
438 UINT8 **OutFileBuffer
\r
442 Routine Description:
\r
444 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
\r
445 Input file must be already sectioned. The function won't validate
\r
446 the input files' contents. Caller should hand in files already
\r
447 with section header.
\r
451 InputFileName - Name of the input file.
\r
453 InputFileNum - Number of input files. Should be at least 1.
\r
455 SectCompSubType - Specify the compression algorithm requested.
\r
457 OutFileBuffer - Buffer pointer to Output file contents
\r
461 EFI_SUCCESS on successful return
\r
462 EFI_INVALID_PARAMETER if InputFileNum is less than 1
\r
463 EFI_ABORTED if unable to open input file.
\r
464 EFI_OUT_OF_RESOURCES No resource to complete the operation.
\r
467 UINT32 TotalLength;
\r
468 UINT32 InputLength;
\r
469 UINT32 CompressedLength;
\r
471 UINT8 *OutputBuffer;
\r
473 EFI_COMPRESSION_SECTION *CompressionSect;
\r
474 COMPRESS_FUNCTION CompressFunction;
\r
478 OutputBuffer = NULL;
\r
479 CompressedLength = 0;
\r
481 // read all input file contents into a buffer
\r
482 // first get the size of all file contents
\r
484 Status = GetSectionContents (
\r
491 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
492 FileBuffer = (UINT8 *) malloc (InputLength);
\r
493 if (FileBuffer == NULL) {
\r
494 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
495 return EFI_OUT_OF_RESOURCES;
\r
498 // read all input file contents into a buffer
\r
500 Status = GetSectionContents (
\r
508 if (EFI_ERROR (Status)) {
\r
509 if (FileBuffer != NULL) {
\r
515 CompressFunction = NULL;
\r
518 // Now data is in FileBuffer, compress the data
\r
520 switch (SectCompSubType) {
\r
521 case EFI_NOT_COMPRESSED:
\r
522 CompressedLength = InputLength;
\r
525 case EFI_STANDARD_COMPRESSION:
\r
526 CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
\r
530 Error (NULL, 0, 2000, "Invalid paramter", "unknown compression type");
\r
532 return EFI_ABORTED;
\r
535 if (CompressFunction != NULL) {
\r
537 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
\r
538 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
539 OutputBuffer = malloc (CompressedLength + sizeof (EFI_COMPRESSION_SECTION));
\r
540 if (!OutputBuffer) {
\r
542 return EFI_OUT_OF_RESOURCES;
\r
545 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + sizeof (EFI_COMPRESSION_SECTION), &CompressedLength);
\r
549 FileBuffer = OutputBuffer;
\r
551 if (EFI_ERROR (Status)) {
\r
552 if (FileBuffer != NULL) {
\r
560 DebugMsg (NULL, 0, 9, "comprss file size",
\r
561 "the original section size is %d bytes and the compressed section size is %d bytes", InputLength, CompressedLength);
\r
562 TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);
\r
563 if (TotalLength >= MAX_SECTION_SIZE) {
\r
564 Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
\r
565 if (FileBuffer != NULL) {
\r
568 if (OutputBuffer != NULL) {
\r
569 free (OutputBuffer);
\r
571 return STATUS_ERROR;
\r
573 VerboseMsg ("the size of the created section file is %d bytes", TotalLength);
\r
576 // Add the section header for the compressed data
\r
578 CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;
\r
580 CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION;
\r
581 CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
\r
582 CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
\r
583 CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
\r
584 CompressionSect->CompressionType = SectCompSubType;
\r
585 CompressionSect->UncompressedLength = InputLength;
\r
588 // Set OutFileBuffer
\r
590 *OutFileBuffer = FileBuffer;
\r
592 return EFI_SUCCESS;
\r
596 GenSectionGuidDefinedSection (
\r
597 CHAR8 **InputFileName,
\r
598 UINT32 InputFileNum,
\r
599 EFI_GUID *VendorGuid,
\r
600 UINT16 DataAttribute,
\r
601 UINT32 DataHeaderSize,
\r
602 UINT8 **OutFileBuffer
\r
606 Routine Description:
\r
608 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
\r
609 Input file must be already sectioned. The function won't validate
\r
610 the input files' contents. Caller should hand in files already
\r
611 with section header.
\r
615 InputFileName - Name of the input file.
\r
617 InputFileNum - Number of input files. Should be at least 1.
\r
619 VendorGuid - Specify vendor guid value.
\r
621 DataAttribute - Specify attribute for the vendor guid data.
\r
623 DataHeaderSize- Guided Data Header Size
\r
625 OutFileBuffer - Buffer pointer to Output file contents
\r
629 EFI_SUCCESS on successful return
\r
630 EFI_INVALID_PARAMETER if InputFileNum is less than 1
\r
631 EFI_ABORTED if unable to open input file.
\r
632 EFI_OUT_OF_RESOURCES No resource to complete the operation.
\r
636 UINT32 TotalLength;
\r
637 UINT32 InputLength;
\r
640 UINT32 Crc32Checksum;
\r
642 CRC32_SECTION_HEADER *Crc32GuidSect;
\r
643 EFI_GUID_DEFINED_SECTION *VendorGuidSect;
\r
649 if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {
\r
650 Offset = sizeof (CRC32_SECTION_HEADER);
\r
652 Offset = sizeof (EFI_GUID_DEFINED_SECTION);
\r
656 // read all input file contents into a buffer
\r
657 // first get the size of all file contents
\r
659 Status = GetSectionContents (
\r
666 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
667 FileBuffer = (UINT8 *) malloc (InputLength + Offset);
\r
668 if (FileBuffer == NULL) {
\r
669 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
670 return EFI_OUT_OF_RESOURCES;
\r
673 // read all input file contents into a buffer
\r
675 Status = GetSectionContents (
\r
678 FileBuffer + Offset,
\r
683 if (EFI_ERROR (Status)) {
\r
684 if (FileBuffer != NULL) {
\r
691 // Now data is in FileBuffer + Offset
\r
693 if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {
\r
695 // Default Guid section is CRC32.
\r
698 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
\r
700 TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);
\r
701 if (TotalLength >= MAX_SECTION_SIZE) {
\r
702 Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
\r
704 return STATUS_ERROR;
\r
707 Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
\r
708 Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
\r
709 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
\r
710 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
\r
711 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
\r
712 memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
\r
713 Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
\r
714 Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);
\r
715 Crc32GuidSect->CRC32Checksum = Crc32Checksum;
\r
716 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", Crc32GuidSect->GuidSectionHeader.DataOffset);
\r
719 TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION);
\r
720 if (TotalLength >= MAX_SECTION_SIZE) {
\r
721 Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
\r
723 return STATUS_ERROR;
\r
726 VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
\r
727 VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
\r
728 VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
\r
729 VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
\r
730 VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
\r
731 memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
\r
732 VendorGuidSect->Attributes = DataAttribute;
\r
733 VendorGuidSect->DataOffset = sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize;
\r
734 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", VendorGuidSect->DataOffset);
\r
736 VerboseMsg ("the size of the created section file is %d bytes", TotalLength);
\r
739 // Set OutFileBuffer
\r
741 *OutFileBuffer = FileBuffer;
\r
743 return EFI_SUCCESS;
\r
753 Routine Description:
\r
759 command line parameters
\r
763 EFI_SUCCESS Section header successfully generated and section concatenated.
\r
764 EFI_ABORTED Could not generate the section
\r
765 EFI_OUT_OF_RESOURCES No resource to complete the operation.
\r
770 UINT32 InputFileNum;
\r
773 CHAR8 **InputFileName;
\r
774 CHAR8 *OutputFileName;
\r
775 CHAR8 *SectionName;
\r
776 CHAR8 *CompressionName;
\r
777 CHAR8 *StringBuffer;
\r
778 EFI_GUID VendorGuid = mZeroGuid;
\r
779 INT32 VersionNumber;
\r
781 UINT8 SectCompSubType;
\r
782 UINT16 SectGuidAttribute;
\r
783 UINT64 SectGuidHeaderLength;
\r
784 EFI_VERSION_SECTION *VersionSect;
\r
785 EFI_USER_INTERFACE_SECTION *UiSect;
\r
786 UINT32 InputLength;
\r
787 UINT8 *OutFileBuffer;
\r
793 InputFileName = NULL;
\r
794 OutputFileName = NULL;
\r
795 SectionName = NULL;
\r
796 CompressionName = NULL;
\r
802 SectType = EFI_SECTION_ALL;
\r
803 SectCompSubType = 0;
\r
804 SectGuidAttribute = 0;
\r
805 OutFileBuffer = NULL;
\r
807 Status = STATUS_SUCCESS;
\r
809 SectGuidHeaderLength = 0;
\r
810 VersionSect = NULL;
\r
814 SetUtilityName (UTILITY_NAME);
\r
817 Error (NULL, 0, 1001, "Missing options", "No options input");
\r
819 return STATUS_ERROR;
\r
823 // Parse command line
\r
828 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
\r
831 return STATUS_SUCCESS;
\r
834 if (stricmp (argv[0], "--version") == 0) {
\r
836 return STATUS_SUCCESS;
\r
840 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
\r
841 SectionName = argv[1];
\r
842 if (SectionName == NULL) {
\r
843 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
\r
851 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
\r
852 OutputFileName = argv[1];
\r
853 if (OutputFileName == NULL) {
\r
854 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
\r
862 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
\r
863 CompressionName = argv[1];
\r
864 if (CompressionName == NULL) {
\r
865 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
\r
873 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
\r
874 Status = StringToGuid (argv[1], &VendorGuid);
\r
875 if (EFI_ERROR (Status)) {
\r
876 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
\r
884 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
\r
885 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
\r
886 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
\r
887 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
\r
888 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
\r
889 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
\r
893 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
\r
895 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
\r
903 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
\r
904 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
\r
905 if (EFI_ERROR (Status)) {
\r
906 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
\r
914 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
\r
915 StringBuffer = argv[1];
\r
916 if (StringBuffer == NULL) {
\r
917 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
\r
925 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
\r
926 if (argv[1] == NULL) {
\r
927 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
\r
931 // Verify string is a integrator number
\r
933 for (Index = 0; Index < strlen (argv[1]); Index++) {
\r
934 if ((argv[1][Index] != '-') && (isdigit (argv[1][Index]) == 0)) {
\r
935 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
\r
940 sscanf (argv[1], "%d", &VersionNumber);
\r
946 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
\r
947 SetPrintLevel (VERBOSE_LOG_LEVEL);
\r
948 VerboseMsg ("Verbose output Mode Set!");
\r
954 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
\r
955 SetPrintLevel (KEY_LOG_LEVEL);
\r
956 KeyMsg ("Quiet output Mode Set!");
\r
962 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
\r
963 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
\r
964 if (EFI_ERROR (Status)) {
\r
965 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
\r
968 if (LogLevel > 9) {
\r
969 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", LogLevel);
\r
972 SetPrintLevel (LogLevel);
\r
973 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
\r
980 // Get Input file name
\r
982 if ((InputFileNum == 0) && (InputFileName == NULL)) {
\r
983 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
\r
984 if (InputFileName == NULL) {
\r
985 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
986 return EFI_OUT_OF_RESOURCES;
\r
989 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
\r
990 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
\r
992 // InputFileName buffer too small, need to realloc
\r
994 InputFileName = (CHAR8 **) realloc (
\r
996 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
\r
999 if (InputFileName == NULL) {
\r
1000 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
1001 return EFI_OUT_OF_RESOURCES;
\r
1004 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
\r
1007 InputFileName[InputFileNum++] = argv[0];
\r
1012 VerboseMsg ("%s tool start.", UTILITY_NAME);
\r
1015 // Parse all command line parameters to get the corresponding section type.
\r
1017 VerboseMsg ("Section type is %s", SectionName);
\r
1018 if (SectionName == NULL) {
\r
1020 // No specified Section type, default is SECTION_ALL.
\r
1022 SectType = EFI_SECTION_ALL;
\r
1023 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
\r
1024 SectType = EFI_SECTION_COMPRESSION;
\r
1025 if (CompressionName == NULL) {
\r
1027 // Default is PI_STD compression algorithm.
\r
1029 SectCompSubType = EFI_STANDARD_COMPRESSION;
\r
1030 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
\r
1031 SectCompSubType = EFI_NOT_COMPRESSED;
\r
1032 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
\r
1033 SectCompSubType = EFI_STANDARD_COMPRESSION;
\r
1035 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
\r
1038 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
\r
1039 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
\r
1040 SectType = EFI_SECTION_GUID_DEFINED;
\r
1042 if (CompareGuid (&VendorGuid, &mZeroGuid) == 0) {
\r
1043 memcpy (&VendorGuid, &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
\r
1046 if (SectGuidAttribute == 0) {
\r
1047 SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
\r
1049 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
\r
1051 // NONE attribute, clear attribute value.
\r
1053 SectGuidAttribute = 0;
\r
1055 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
\r
1059 VendorGuid.Data4[0],
\r
1060 VendorGuid.Data4[1],
\r
1061 VendorGuid.Data4[2],
\r
1062 VendorGuid.Data4[3],
\r
1063 VendorGuid.Data4[4],
\r
1064 VendorGuid.Data4[5],
\r
1065 VendorGuid.Data4[6],
\r
1066 VendorGuid.Data4[7]);
\r
1067 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
\r
1068 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
\r
1070 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
\r
1071 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
\r
1073 if (SectGuidHeaderLength != 0) {
\r
1074 VerboseMsg ("Guid Data Header size is 0x%x", SectGuidHeaderLength);
\r
1076 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
\r
1077 SectType = EFI_SECTION_PE32;
\r
1078 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
\r
1079 SectType = EFI_SECTION_PIC;
\r
1080 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
\r
1081 SectType = EFI_SECTION_TE;
\r
1082 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
\r
1083 SectType = EFI_SECTION_DXE_DEPEX;
\r
1084 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
\r
1085 SectType = EFI_SECTION_VERSION;
\r
1086 if (VersionNumber < 0 || VersionNumber > 9999) {
\r
1087 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber);
\r
1090 VerboseMsg ("Version section number is %d", VersionNumber);
\r
1091 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
\r
1092 SectType = EFI_SECTION_USER_INTERFACE;
\r
1093 if (StringBuffer[0] == '\0') {
\r
1094 Error (NULL, 0, 1001, "Missing option", "user interface string");
\r
1097 VerboseMsg ("UI section string name is %s", StringBuffer);
\r
1098 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
\r
1099 SectType = EFI_SECTION_COMPATIBILITY16;
\r
1100 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
\r
1101 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
\r
1102 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
\r
1103 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
\r
1104 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
\r
1105 SectType = EFI_SECTION_RAW;
\r
1106 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
\r
1107 SectType = EFI_SECTION_PEI_DEPEX;
\r
1109 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
\r
1114 // GuidValue is only required by Guided section.
\r
1116 if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
\r
1117 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
\r
1121 // Check whether there is input file
\r
1123 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
\r
1125 // The input file are required for other section type.
\r
1127 if (InputFileNum == 0) {
\r
1128 Error (NULL, 0, 1001, "Missing options", "Input files");
\r
1133 // Check whether there is output file
\r
1135 for (Index = 0; Index < InputFileNum; Index ++) {
\r
1136 VerboseMsg ("the %dth input file name is %s", Index, InputFileName[Index]);
\r
1138 if (OutputFileName == NULL) {
\r
1139 Error (NULL, 0, 1001, "Missing options", "Output file");
\r
1141 // OutFile = stdout;
\r
1143 VerboseMsg ("Output file name is %s", OutputFileName);
\r
1146 // At this point, we've fully validated the command line, and opened appropriate
\r
1147 // files, so let's go and do what we've been asked to do...
\r
1150 // Within this switch, build and write out the section header including any
\r
1151 // section type specific pieces. If there's an input file, it's tacked on later
\r
1153 switch (SectType) {
\r
1154 case EFI_SECTION_COMPRESSION:
\r
1155 Status = GenSectionCompressionSection (
\r
1163 case EFI_SECTION_GUID_DEFINED:
\r
1164 Status = GenSectionGuidDefinedSection (
\r
1168 SectGuidAttribute,
\r
1169 (UINT32) SectGuidHeaderLength,
\r
1174 case EFI_SECTION_VERSION:
\r
1175 Index = sizeof (EFI_COMMON_SECTION_HEADER);
\r
1177 // 2 bytes for the build number UINT16
\r
1181 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
\r
1183 Index += (strlen (StringBuffer) * 2) + 2;
\r
1184 OutFileBuffer = (UINT8 *) malloc (Index);
\r
1185 if (OutFileBuffer == NULL) {
\r
1186 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
1189 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
\r
1190 VersionSect->CommonHeader.Type = SectType;
\r
1191 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
\r
1192 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
\r
1193 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
\r
1194 VersionSect->BuildNumber = (UINT16) VersionNumber;
\r
1195 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
\r
1196 VerboseMsg ("the size of the created section file is %d bytes", Index);
\r
1199 case EFI_SECTION_USER_INTERFACE:
\r
1200 Index = sizeof (EFI_COMMON_SECTION_HEADER);
\r
1202 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
\r
1204 Index += (strlen (StringBuffer) * 2) + 2;
\r
1205 OutFileBuffer = (UINT8 *) malloc (Index);
\r
1206 if (OutFileBuffer == NULL) {
\r
1207 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
1210 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
\r
1211 UiSect->CommonHeader.Type = SectType;
\r
1212 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
\r
1213 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
\r
1214 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
\r
1215 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
\r
1216 VerboseMsg ("the size of the created section file is %d bytes", Index);
\r
1219 case EFI_SECTION_ALL:
\r
1221 // read all input file contents into a buffer
\r
1222 // first get the size of all file contents
\r
1224 Status = GetSectionContents (
\r
1231 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
1232 OutFileBuffer = (UINT8 *) malloc (InputLength);
\r
1233 if (OutFileBuffer == NULL) {
\r
1234 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
1238 // read all input file contents into a buffer
\r
1240 Status = GetSectionContents (
\r
1247 VerboseMsg ("the size of the created section file is %d bytes", InputLength);
\r
1251 // All other section types are caught by default (they're all the same)
\r
1253 Status = GenSectionCommonLeafSection (
\r
1263 // Get output file length
\r
1265 if (SectType != EFI_SECTION_ALL) {
\r
1266 InputLength = SECTION_SIZE (OutFileBuffer);
\r
1269 // Write the Buffer to the Output file.
\r
1271 OutFile = fopen (OutputFileName, "rb");
\r
1272 if (OutFile != NULL) {
\r
1274 // the output file exists
\r
1275 // first compare the output buffer and the exist output file
\r
1276 // if same, not to update output file
\r
1278 fseek (OutFile, 0, SEEK_END);
\r
1279 TempLength = ftell (OutFile);
\r
1280 fseek (OutFile, 0, SEEK_SET);
\r
1282 if (InputLength != TempLength) {
\r
1284 // they can't be same because their size are different
\r
1289 // read file data from output file
\r
1291 TempBuffer = (UINT8 *) malloc (TempLength);
\r
1292 if (TempBuffer == NULL) {
\r
1293 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
\r
1296 fread (TempBuffer, TempLength, 1, OutFile);
\r
1298 // Compare Data byte by byte
\r
1300 for (Index = 0; Index < InputLength; Index ++) {
\r
1301 if (OutFileBuffer [Index] != TempBuffer [Index]) {
\r
1306 // Data is same, output file doesn't need to be updated.
\r
1308 if (Index >= InputLength) {
\r
1314 if (OutFile != NULL) {
\r
1318 OutFile = fopen (OutputFileName, "wb");
\r
1319 if (OutFile == NULL) {
\r
1320 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
\r
1324 fwrite (OutFileBuffer, InputLength, 1, OutFile);
\r
1327 if (InputFileName != NULL) {
\r
1328 free (InputFileName);
\r
1331 if (TempBuffer != NULL) {
\r
1332 free (TempBuffer);
\r
1335 if (OutFileBuffer != NULL) {
\r
1336 free (OutFileBuffer);
\r
1339 if (OutFile != NULL) {
\r
1343 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
\r
1345 return GetUtilityStatus ();
\r