]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenSec/GenSec.c
BaseTools/GenSec: Fix potential memory leak
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
1 /** @file
2 Creates output file that is a properly formed section per the PI spec.
3
4 Copyright (c) 2004 - 2016, 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 parameter", "more than one input file specified");
271 return STATUS_ERROR;
272 } else if (InputFileNum < 1) {
273 Error (NULL, 0, 2000, "Invalid parameter", "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 parameter", "%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 parameter", "must specify at least one input file");
440 return EFI_INVALID_PARAMETER;
441 }
442
443 if (BufferLength == NULL) {
444 Error (NULL, 0, 2000, "Invalid parameter", "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 if (FileBuffer == NULL) {
671 return EFI_OUT_OF_RESOURCES;
672 }
673
674 CompressFunction = NULL;
675
676 //
677 // Now data is in FileBuffer, compress the data
678 //
679 switch (SectCompSubType) {
680 case EFI_NOT_COMPRESSED:
681 CompressedLength = InputLength;
682 HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
683 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
684 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
685 }
686 TotalLength = CompressedLength + HeaderLength;
687 //
688 // Copy file buffer to the none compressed data.
689 //
690 OutputBuffer = malloc (TotalLength);
691 if (OutputBuffer == NULL) {
692 free (FileBuffer);
693 return EFI_OUT_OF_RESOURCES;
694 }
695 memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);
696 free (FileBuffer);
697 FileBuffer = OutputBuffer;
698 break;
699
700 case EFI_STANDARD_COMPRESSION:
701 CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
702 break;
703
704 default:
705 Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");
706 free (FileBuffer);
707 return EFI_ABORTED;
708 }
709
710 if (CompressFunction != NULL) {
711
712 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
713 if (Status == EFI_BUFFER_TOO_SMALL) {
714 HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
715 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
716 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
717 }
718 TotalLength = CompressedLength + HeaderLength;
719 OutputBuffer = malloc (TotalLength);
720 if (!OutputBuffer) {
721 free (FileBuffer);
722 return EFI_OUT_OF_RESOURCES;
723 }
724
725 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);
726 }
727
728 free (FileBuffer);
729 FileBuffer = OutputBuffer;
730
731 if (EFI_ERROR (Status)) {
732 if (FileBuffer != NULL) {
733 free (FileBuffer);
734 }
735
736 return Status;
737 }
738
739 if (FileBuffer == NULL) {
740 return EFI_OUT_OF_RESOURCES;
741 }
742 }
743
744 DebugMsg (NULL, 0, 9, "comprss file size",
745 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);
746
747 //if (TotalLength >= MAX_SECTION_SIZE) {
748 // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
749 // if (FileBuffer != NULL) {
750 // free (FileBuffer);
751 // }
752 // if (OutputBuffer != NULL) {
753 // free (OutputBuffer);
754 // }
755 // return STATUS_ERROR;
756 //}
757 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
758
759 //
760 // Add the section header for the compressed data
761 //
762 if (TotalLength >= MAX_SECTION_SIZE) {
763 CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;
764
765 memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);
766 CompressionSect2->CommonHeader.Type = EFI_SECTION_COMPRESSION;
767 CompressionSect2->CommonHeader.ExtendedSize = TotalLength;
768 CompressionSect2->CompressionType = SectCompSubType;
769 CompressionSect2->UncompressedLength = InputLength;
770 } else {
771 CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;
772
773 CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION;
774 CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
775 CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
776 CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
777 CompressionSect->CompressionType = SectCompSubType;
778 CompressionSect->UncompressedLength = InputLength;
779 }
780
781 //
782 // Set OutFileBuffer
783 //
784 *OutFileBuffer = FileBuffer;
785
786 return EFI_SUCCESS;
787 }
788
789 EFI_STATUS
790 GenSectionGuidDefinedSection (
791 CHAR8 **InputFileName,
792 UINT32 *InputFileAlign,
793 UINT32 InputFileNum,
794 EFI_GUID *VendorGuid,
795 UINT16 DataAttribute,
796 UINT32 DataHeaderSize,
797 UINT8 **OutFileBuffer
798 )
799 /*++
800
801 Routine Description:
802
803 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
804 Input file must be already sectioned. The function won't validate
805 the input files' contents. Caller should hand in files already
806 with section header.
807
808 Arguments:
809
810 InputFileName - Name of the input file.
811
812 InputFileAlign - Alignment required by the input file data.
813
814 InputFileNum - Number of input files. Should be at least 1.
815
816 VendorGuid - Specify vendor guid value.
817
818 DataAttribute - Specify attribute for the vendor guid data.
819
820 DataHeaderSize- Guided Data Header Size
821
822 OutFileBuffer - Buffer pointer to Output file contents
823
824 Returns:
825
826 EFI_SUCCESS on successful return
827 EFI_INVALID_PARAMETER if InputFileNum is less than 1
828 EFI_ABORTED if unable to open input file.
829 EFI_OUT_OF_RESOURCES No resource to complete the operation.
830
831 --*/
832 {
833 UINT32 TotalLength;
834 UINT32 InputLength;
835 UINT32 Offset;
836 UINT8 *FileBuffer;
837 UINT32 Crc32Checksum;
838 EFI_STATUS Status;
839 CRC32_SECTION_HEADER *Crc32GuidSect;
840 CRC32_SECTION_HEADER2 *Crc32GuidSect2;
841 EFI_GUID_DEFINED_SECTION *VendorGuidSect;
842 EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2;
843
844 InputLength = 0;
845 Offset = 0;
846 FileBuffer = NULL;
847 TotalLength = 0;
848
849 //
850 // read all input file contents into a buffer
851 // first get the size of all file contents
852 //
853 Status = GetSectionContents (
854 InputFileName,
855 InputFileAlign,
856 InputFileNum,
857 FileBuffer,
858 &InputLength
859 );
860
861 if (Status == EFI_BUFFER_TOO_SMALL) {
862 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
863 Offset = sizeof (CRC32_SECTION_HEADER);
864 if (InputLength + Offset >= MAX_SECTION_SIZE) {
865 Offset = sizeof (CRC32_SECTION_HEADER2);
866 }
867 } else {
868 Offset = sizeof (EFI_GUID_DEFINED_SECTION);
869 if (InputLength + Offset >= MAX_SECTION_SIZE) {
870 Offset = sizeof (EFI_GUID_DEFINED_SECTION2);
871 }
872 }
873 TotalLength = InputLength + Offset;
874
875 FileBuffer = (UINT8 *) malloc (InputLength + Offset);
876 if (FileBuffer == NULL) {
877 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
878 return EFI_OUT_OF_RESOURCES;
879 }
880 //
881 // read all input file contents into a buffer
882 //
883 Status = GetSectionContents (
884 InputFileName,
885 InputFileAlign,
886 InputFileNum,
887 FileBuffer + Offset,
888 &InputLength
889 );
890 }
891
892 if (EFI_ERROR (Status)) {
893 if (FileBuffer != NULL) {
894 free (FileBuffer);
895 }
896 Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);
897 return Status;
898 }
899
900 if (FileBuffer == NULL) {
901 return EFI_OUT_OF_RESOURCES;
902 }
903
904 if (InputLength == 0) {
905 free (FileBuffer);
906 Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);
907 return EFI_NOT_FOUND;
908 }
909
910 //
911 // Now data is in FileBuffer + Offset
912 //
913 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
914 //
915 // Default Guid section is CRC32.
916 //
917 Crc32Checksum = 0;
918 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
919
920 if (TotalLength >= MAX_SECTION_SIZE) {
921 Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;
922 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
923 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) 0xff;
924 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) 0xff;
925 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) 0xff;
926 Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;
927 memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
928 Crc32GuidSect2->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
929 Crc32GuidSect2->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER2);
930 Crc32GuidSect2->CRC32Checksum = Crc32Checksum;
931 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);
932 } else {
933 Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
934 Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
935 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
936 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
937 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
938 memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
939 Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
940 Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);
941 Crc32GuidSect->CRC32Checksum = Crc32Checksum;
942 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);
943 }
944 } else {
945 if (TotalLength >= MAX_SECTION_SIZE) {
946 VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;
947 VendorGuidSect2->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
948 VendorGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff;
949 VendorGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff;
950 VendorGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff;
951 VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);
952 memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
953 VendorGuidSect2->Attributes = DataAttribute;
954 VendorGuidSect2->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);
955 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);
956 } else {
957 VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
958 VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
959 VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
960 VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
961 VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
962 memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
963 VendorGuidSect->Attributes = DataAttribute;
964 VendorGuidSect->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);
965 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);
966 }
967 }
968 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
969
970 //
971 // Set OutFileBuffer
972 //
973 *OutFileBuffer = FileBuffer;
974
975 return EFI_SUCCESS;
976 }
977
978 int
979 main (
980 int argc,
981 char *argv[]
982 )
983 /*++
984
985 Routine Description:
986
987 Main
988
989 Arguments:
990
991 command line parameters
992
993 Returns:
994
995 EFI_SUCCESS Section header successfully generated and section concatenated.
996 EFI_ABORTED Could not generate the section
997 EFI_OUT_OF_RESOURCES No resource to complete the operation.
998
999 --*/
1000 {
1001 UINT32 Index;
1002 UINT32 InputFileNum;
1003 FILE *OutFile;
1004 CHAR8 **InputFileName;
1005 CHAR8 *OutputFileName;
1006 CHAR8 *SectionName;
1007 CHAR8 *CompressionName;
1008 CHAR8 *StringBuffer;
1009 EFI_GUID VendorGuid = mZeroGuid;
1010 int VersionNumber;
1011 UINT8 SectType;
1012 UINT8 SectCompSubType;
1013 UINT16 SectGuidAttribute;
1014 UINT64 SectGuidHeaderLength;
1015 EFI_VERSION_SECTION *VersionSect;
1016 EFI_USER_INTERFACE_SECTION *UiSect;
1017 UINT32 InputLength;
1018 UINT8 *OutFileBuffer;
1019 EFI_STATUS Status;
1020 UINT64 LogLevel;
1021 UINT32 *InputFileAlign;
1022 UINT32 InputFileAlignNum;
1023 EFI_COMMON_SECTION_HEADER *SectionHeader;
1024
1025 InputFileAlign = NULL;
1026 InputFileAlignNum = 0;
1027 InputFileName = NULL;
1028 OutputFileName = NULL;
1029 SectionName = NULL;
1030 CompressionName = NULL;
1031 StringBuffer = "";
1032 OutFile = NULL;
1033 VersionNumber = 0;
1034 InputFileNum = 0;
1035 SectType = EFI_SECTION_ALL;
1036 SectCompSubType = 0;
1037 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;
1038 OutFileBuffer = NULL;
1039 InputLength = 0;
1040 Status = STATUS_SUCCESS;
1041 LogLevel = 0;
1042 SectGuidHeaderLength = 0;
1043 VersionSect = NULL;
1044 UiSect = NULL;
1045
1046 SetUtilityName (UTILITY_NAME);
1047
1048 if (argc == 1) {
1049 Error (NULL, 0, 1001, "Missing options", "No options input");
1050 Usage ();
1051 return STATUS_ERROR;
1052 }
1053
1054 //
1055 // Parse command line
1056 //
1057 argc --;
1058 argv ++;
1059
1060 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
1061 Version ();
1062 Usage ();
1063 return STATUS_SUCCESS;
1064 }
1065
1066 if (stricmp (argv[0], "--version") == 0) {
1067 Version ();
1068 return STATUS_SUCCESS;
1069 }
1070
1071 while (argc > 0) {
1072 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
1073 SectionName = argv[1];
1074 if (SectionName == NULL) {
1075 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
1076 goto Finish;
1077 }
1078 argc -= 2;
1079 argv += 2;
1080 continue;
1081 }
1082
1083 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
1084 OutputFileName = argv[1];
1085 if (OutputFileName == NULL) {
1086 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
1087 goto Finish;
1088 }
1089 argc -= 2;
1090 argv += 2;
1091 continue;
1092 }
1093
1094 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
1095 CompressionName = argv[1];
1096 if (CompressionName == NULL) {
1097 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1098 goto Finish;
1099 }
1100 argc -= 2;
1101 argv += 2;
1102 continue;
1103 }
1104
1105 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
1106 Status = StringToGuid (argv[1], &VendorGuid);
1107 if (EFI_ERROR (Status)) {
1108 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1109 goto Finish;
1110 }
1111 argc -= 2;
1112 argv += 2;
1113 continue;
1114 }
1115
1116 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
1117 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
1118 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
1119 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
1120 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
1121 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
1122 //
1123 // NONE attribute
1124 //
1125 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
1126 } else {
1127 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1128 goto Finish;
1129 }
1130 argc -= 2;
1131 argv += 2;
1132 continue;
1133 }
1134
1135 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
1136 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
1137 if (EFI_ERROR (Status)) {
1138 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
1139 goto Finish;
1140 }
1141 argc -= 2;
1142 argv += 2;
1143 continue;
1144 }
1145
1146 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
1147 StringBuffer = argv[1];
1148 if (StringBuffer == NULL) {
1149 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
1150 goto Finish;
1151 }
1152 argc -= 2;
1153 argv += 2;
1154 continue;
1155 }
1156
1157 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
1158 if (argv[1] == NULL) {
1159 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
1160 goto Finish;
1161 }
1162 //
1163 // Verify string is a integrator number
1164 //
1165 for (Index = 0; Index < strlen (argv[1]); Index++) {
1166 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {
1167 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1168 goto Finish;
1169 }
1170 }
1171
1172 sscanf (argv[1], "%d", &VersionNumber);
1173 argc -= 2;
1174 argv += 2;
1175 continue;
1176 }
1177
1178 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
1179 SetPrintLevel (VERBOSE_LOG_LEVEL);
1180 VerboseMsg ("Verbose output Mode Set!");
1181 argc --;
1182 argv ++;
1183 continue;
1184 }
1185
1186 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
1187 SetPrintLevel (KEY_LOG_LEVEL);
1188 KeyMsg ("Quiet output Mode Set!");
1189 argc --;
1190 argv ++;
1191 continue;
1192 }
1193
1194 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
1195 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
1196 if (EFI_ERROR (Status)) {
1197 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1198 goto Finish;
1199 }
1200 if (LogLevel > 9) {
1201 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);
1202 goto Finish;
1203 }
1204 SetPrintLevel (LogLevel);
1205 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
1206 argc -= 2;
1207 argv += 2;
1208 continue;
1209 }
1210
1211 //
1212 // Section File alignment requirement
1213 //
1214 if (stricmp (argv[0], "--sectionalign") == 0) {
1215 if (InputFileAlignNum == 0) {
1216 InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
1217 if (InputFileAlign == NULL) {
1218 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1219 goto Finish;
1220 }
1221 memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
1222 } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1223 InputFileAlign = (UINT32 *) realloc (
1224 InputFileAlign,
1225 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)
1226 );
1227
1228 if (InputFileAlign == NULL) {
1229 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1230 goto Finish;
1231 }
1232 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));
1233 }
1234
1235 Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));
1236 if (EFI_ERROR (Status)) {
1237 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1238 goto Finish;
1239 }
1240 argc -= 2;
1241 argv += 2;
1242 InputFileAlignNum ++;
1243 continue;
1244 }
1245
1246 //
1247 // Get Input file name
1248 //
1249 if ((InputFileNum == 0) && (InputFileName == NULL)) {
1250 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
1251 if (InputFileName == NULL) {
1252 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1253 goto Finish;
1254 }
1255 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1256 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1257 //
1258 // InputFileName buffer too small, need to realloc
1259 //
1260 InputFileName = (CHAR8 **) realloc (
1261 InputFileName,
1262 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
1263 );
1264
1265 if (InputFileName == NULL) {
1266 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1267 goto Finish;
1268 }
1269 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1270 }
1271
1272 InputFileName[InputFileNum++] = argv[0];
1273 argc --;
1274 argv ++;
1275 }
1276
1277 if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {
1278 Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");
1279 goto Finish;
1280 }
1281
1282 VerboseMsg ("%s tool start.", UTILITY_NAME);
1283
1284 //
1285 // Parse all command line parameters to get the corresponding section type.
1286 //
1287 VerboseMsg ("Section type is %s", SectionName);
1288 if (SectionName == NULL) {
1289 //
1290 // No specified Section type, default is SECTION_ALL.
1291 //
1292 SectType = EFI_SECTION_ALL;
1293 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
1294 SectType = EFI_SECTION_COMPRESSION;
1295 if (CompressionName == NULL) {
1296 //
1297 // Default is PI_STD compression algorithm.
1298 //
1299 SectCompSubType = EFI_STANDARD_COMPRESSION;
1300 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
1301 SectCompSubType = EFI_NOT_COMPRESSED;
1302 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
1303 SectCompSubType = EFI_STANDARD_COMPRESSION;
1304 } else {
1305 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
1306 goto Finish;
1307 }
1308 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
1309 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
1310 SectType = EFI_SECTION_GUID_DEFINED;
1311
1312 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
1313 //
1314 // NONE attribute, clear attribute value.
1315 //
1316 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;
1317 }
1318 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1319 (unsigned) VendorGuid.Data1,
1320 VendorGuid.Data2,
1321 VendorGuid.Data3,
1322 VendorGuid.Data4[0],
1323 VendorGuid.Data4[1],
1324 VendorGuid.Data4[2],
1325 VendorGuid.Data4[3],
1326 VendorGuid.Data4[4],
1327 VendorGuid.Data4[5],
1328 VendorGuid.Data4[6],
1329 VendorGuid.Data4[7]);
1330 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
1331 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
1332 }
1333 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
1334 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
1335 }
1336 if (SectGuidHeaderLength != 0) {
1337 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);
1338 }
1339 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
1340 SectType = EFI_SECTION_PE32;
1341 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
1342 SectType = EFI_SECTION_PIC;
1343 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
1344 SectType = EFI_SECTION_TE;
1345 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
1346 SectType = EFI_SECTION_DXE_DEPEX;
1347 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {
1348 SectType = EFI_SECTION_SMM_DEPEX;
1349 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
1350 SectType = EFI_SECTION_VERSION;
1351 if (VersionNumber < 0 || VersionNumber > 65535) {
1352 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);
1353 goto Finish;
1354 }
1355 VerboseMsg ("Version section number is %d", VersionNumber);
1356 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
1357 SectType = EFI_SECTION_USER_INTERFACE;
1358 if (StringBuffer[0] == '\0') {
1359 Error (NULL, 0, 1001, "Missing option", "user interface string");
1360 goto Finish;
1361 }
1362 VerboseMsg ("UI section string name is %s", StringBuffer);
1363 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
1364 SectType = EFI_SECTION_COMPATIBILITY16;
1365 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
1366 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
1367 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
1368 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
1369 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
1370 SectType = EFI_SECTION_RAW;
1371 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
1372 SectType = EFI_SECTION_PEI_DEPEX;
1373 } else {
1374 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
1375 goto Finish;
1376 }
1377
1378 //
1379 // GuidValue is only required by Guided section.
1380 //
1381 if ((SectType != EFI_SECTION_GUID_DEFINED) &&
1382 (SectionName != NULL) &&
1383 (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1384 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
1385 }
1386
1387 //
1388 // Check whether there is input file
1389 //
1390 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
1391 //
1392 // The input file are required for other section type.
1393 //
1394 if (InputFileNum == 0) {
1395 Error (NULL, 0, 1001, "Missing options", "Input files");
1396 goto Finish;
1397 }
1398 }
1399 //
1400 // Check whether there is output file
1401 //
1402 for (Index = 0; Index < InputFileNum; Index ++) {
1403 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);
1404 }
1405 if (OutputFileName == NULL) {
1406 Error (NULL, 0, 1001, "Missing options", "Output file");
1407 goto Finish;
1408 // OutFile = stdout;
1409 }
1410 VerboseMsg ("Output file name is %s", OutputFileName);
1411
1412 //
1413 // At this point, we've fully validated the command line, and opened appropriate
1414 // files, so let's go and do what we've been asked to do...
1415 //
1416 //
1417 // Within this switch, build and write out the section header including any
1418 // section type specific pieces. If there's an input file, it's tacked on later
1419 //
1420 switch (SectType) {
1421 case EFI_SECTION_COMPRESSION:
1422 if (InputFileAlign != NULL) {
1423 free (InputFileAlign);
1424 InputFileAlign = NULL;
1425 }
1426 Status = GenSectionCompressionSection (
1427 InputFileName,
1428 InputFileAlign,
1429 InputFileNum,
1430 SectCompSubType,
1431 &OutFileBuffer
1432 );
1433 break;
1434
1435 case EFI_SECTION_GUID_DEFINED:
1436 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1437 //
1438 // Only process alignment for the default known CRC32 guided section.
1439 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1440 //
1441 free (InputFileAlign);
1442 InputFileAlign = NULL;
1443 }
1444 Status = GenSectionGuidDefinedSection (
1445 InputFileName,
1446 InputFileAlign,
1447 InputFileNum,
1448 &VendorGuid,
1449 SectGuidAttribute,
1450 (UINT32) SectGuidHeaderLength,
1451 &OutFileBuffer
1452 );
1453 break;
1454
1455 case EFI_SECTION_VERSION:
1456 Index = sizeof (EFI_COMMON_SECTION_HEADER);
1457 //
1458 // 2 bytes for the build number UINT16
1459 //
1460 Index += 2;
1461 //
1462 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1463 //
1464 Index += (strlen (StringBuffer) * 2) + 2;
1465 OutFileBuffer = (UINT8 *) malloc (Index);
1466 if (OutFileBuffer == NULL) {
1467 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1468 goto Finish;
1469 }
1470 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
1471 VersionSect->CommonHeader.Type = SectType;
1472 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
1473 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
1474 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
1475 VersionSect->BuildNumber = (UINT16) VersionNumber;
1476 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
1477 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
1478 break;
1479
1480 case EFI_SECTION_USER_INTERFACE:
1481 Index = sizeof (EFI_COMMON_SECTION_HEADER);
1482 //
1483 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1484 //
1485 Index += (strlen (StringBuffer) * 2) + 2;
1486 OutFileBuffer = (UINT8 *) malloc (Index);
1487 if (OutFileBuffer == NULL) {
1488 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1489 goto Finish;
1490 }
1491 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
1492 UiSect->CommonHeader.Type = SectType;
1493 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
1494 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
1495 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
1496 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
1497 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
1498 break;
1499
1500 case EFI_SECTION_ALL:
1501 //
1502 // read all input file contents into a buffer
1503 // first get the size of all file contents
1504 //
1505 Status = GetSectionContents (
1506 InputFileName,
1507 InputFileAlign,
1508 InputFileNum,
1509 OutFileBuffer,
1510 &InputLength
1511 );
1512
1513 if (Status == EFI_BUFFER_TOO_SMALL) {
1514 OutFileBuffer = (UINT8 *) malloc (InputLength);
1515 if (OutFileBuffer == NULL) {
1516 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1517 goto Finish;
1518 }
1519 //
1520 // read all input file contents into a buffer
1521 //
1522 Status = GetSectionContents (
1523 InputFileName,
1524 InputFileAlign,
1525 InputFileNum,
1526 OutFileBuffer,
1527 &InputLength
1528 );
1529 }
1530 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);
1531 break;
1532 default:
1533 //
1534 // All other section types are caught by default (they're all the same)
1535 //
1536 Status = GenSectionCommonLeafSection (
1537 InputFileName,
1538 InputFileNum,
1539 SectType,
1540 &OutFileBuffer
1541 );
1542 break;
1543 }
1544
1545 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {
1546 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);
1547 goto Finish;
1548 }
1549
1550 //
1551 // Get output file length
1552 //
1553 if (SectType != EFI_SECTION_ALL) {
1554 SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;
1555 InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;
1556 if (InputLength == 0xffffff) {
1557 InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
1558 }
1559 }
1560
1561 //
1562 // Write the output file
1563 //
1564 OutFile = fopen (LongFilePath (OutputFileName), "wb");
1565 if (OutFile == NULL) {
1566 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
1567 goto Finish;
1568 }
1569
1570 fwrite (OutFileBuffer, InputLength, 1, OutFile);
1571
1572 Finish:
1573 if (InputFileName != NULL) {
1574 free (InputFileName);
1575 }
1576
1577 if (InputFileAlign != NULL) {
1578 free (InputFileAlign);
1579 }
1580
1581 if (OutFileBuffer != NULL) {
1582 free (OutFileBuffer);
1583 }
1584
1585 if (OutFile != NULL) {
1586 fclose (OutFile);
1587 }
1588
1589 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
1590
1591 return GetUtilityStatus ();
1592 }