]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenSec/GenSec.c
BaseTools/GenSec: Fix a segmentation fault in main()
[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 - 2017, 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 - 2017, 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 (InputLength == 0) {
901 if (FileBuffer != NULL) {
902 free (FileBuffer);
903 }
904 Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);
905 return EFI_NOT_FOUND;
906 }
907
908 //
909 // InputLength != 0, but FileBuffer == NULL means out of resources.
910 //
911 if (FileBuffer == NULL) {
912 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
913 return EFI_OUT_OF_RESOURCES;
914 }
915
916 //
917 // Now data is in FileBuffer + Offset
918 //
919 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
920 //
921 // Default Guid section is CRC32.
922 //
923 Crc32Checksum = 0;
924 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
925
926 if (TotalLength >= MAX_SECTION_SIZE) {
927 Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;
928 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
929 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) 0xff;
930 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) 0xff;
931 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) 0xff;
932 Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;
933 memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
934 Crc32GuidSect2->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
935 Crc32GuidSect2->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER2);
936 Crc32GuidSect2->CRC32Checksum = Crc32Checksum;
937 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);
938 } else {
939 Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
940 Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
941 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
942 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
943 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
944 memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
945 Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
946 Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);
947 Crc32GuidSect->CRC32Checksum = Crc32Checksum;
948 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);
949 }
950 } else {
951 if (TotalLength >= MAX_SECTION_SIZE) {
952 VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;
953 VendorGuidSect2->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
954 VendorGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff;
955 VendorGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff;
956 VendorGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff;
957 VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);
958 memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
959 VendorGuidSect2->Attributes = DataAttribute;
960 VendorGuidSect2->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);
961 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);
962 } else {
963 VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
964 VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
965 VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
966 VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
967 VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
968 memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
969 VendorGuidSect->Attributes = DataAttribute;
970 VendorGuidSect->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);
971 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);
972 }
973 }
974 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
975
976 //
977 // Set OutFileBuffer
978 //
979 *OutFileBuffer = FileBuffer;
980
981 return EFI_SUCCESS;
982 }
983
984 int
985 main (
986 int argc,
987 char *argv[]
988 )
989 /*++
990
991 Routine Description:
992
993 Main
994
995 Arguments:
996
997 command line parameters
998
999 Returns:
1000
1001 EFI_SUCCESS Section header successfully generated and section concatenated.
1002 EFI_ABORTED Could not generate the section
1003 EFI_OUT_OF_RESOURCES No resource to complete the operation.
1004
1005 --*/
1006 {
1007 UINT32 Index;
1008 UINT32 InputFileNum;
1009 FILE *OutFile;
1010 CHAR8 **InputFileName;
1011 CHAR8 *OutputFileName;
1012 CHAR8 *SectionName;
1013 CHAR8 *CompressionName;
1014 CHAR8 *StringBuffer;
1015 EFI_GUID VendorGuid = mZeroGuid;
1016 int VersionNumber;
1017 UINT8 SectType;
1018 UINT8 SectCompSubType;
1019 UINT16 SectGuidAttribute;
1020 UINT64 SectGuidHeaderLength;
1021 EFI_VERSION_SECTION *VersionSect;
1022 EFI_USER_INTERFACE_SECTION *UiSect;
1023 UINT32 InputLength;
1024 UINT8 *OutFileBuffer;
1025 EFI_STATUS Status;
1026 UINT64 LogLevel;
1027 UINT32 *InputFileAlign;
1028 UINT32 InputFileAlignNum;
1029 EFI_COMMON_SECTION_HEADER *SectionHeader;
1030
1031 InputFileAlign = NULL;
1032 InputFileAlignNum = 0;
1033 InputFileName = NULL;
1034 OutputFileName = NULL;
1035 SectionName = NULL;
1036 CompressionName = NULL;
1037 StringBuffer = "";
1038 OutFile = NULL;
1039 VersionNumber = 0;
1040 InputFileNum = 0;
1041 SectType = EFI_SECTION_ALL;
1042 SectCompSubType = 0;
1043 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;
1044 OutFileBuffer = NULL;
1045 InputLength = 0;
1046 Status = STATUS_SUCCESS;
1047 LogLevel = 0;
1048 SectGuidHeaderLength = 0;
1049 VersionSect = NULL;
1050 UiSect = NULL;
1051
1052 SetUtilityName (UTILITY_NAME);
1053
1054 if (argc == 1) {
1055 Error (NULL, 0, 1001, "Missing options", "No options input");
1056 Usage ();
1057 return STATUS_ERROR;
1058 }
1059
1060 //
1061 // Parse command line
1062 //
1063 argc --;
1064 argv ++;
1065
1066 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
1067 Version ();
1068 Usage ();
1069 return STATUS_SUCCESS;
1070 }
1071
1072 if (stricmp (argv[0], "--version") == 0) {
1073 Version ();
1074 return STATUS_SUCCESS;
1075 }
1076
1077 while (argc > 0) {
1078 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
1079 SectionName = argv[1];
1080 if (SectionName == NULL) {
1081 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
1082 goto Finish;
1083 }
1084 argc -= 2;
1085 argv += 2;
1086 continue;
1087 }
1088
1089 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
1090 OutputFileName = argv[1];
1091 if (OutputFileName == NULL) {
1092 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
1093 goto Finish;
1094 }
1095 argc -= 2;
1096 argv += 2;
1097 continue;
1098 }
1099
1100 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
1101 CompressionName = argv[1];
1102 if (CompressionName == NULL) {
1103 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1104 goto Finish;
1105 }
1106 argc -= 2;
1107 argv += 2;
1108 continue;
1109 }
1110
1111 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
1112 Status = StringToGuid (argv[1], &VendorGuid);
1113 if (EFI_ERROR (Status)) {
1114 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1115 goto Finish;
1116 }
1117 argc -= 2;
1118 argv += 2;
1119 continue;
1120 }
1121
1122 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
1123 if (argv[1] == NULL) {
1124 Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");
1125 goto Finish;
1126 }
1127 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
1128 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
1129 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
1130 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
1131 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
1132 //
1133 // NONE attribute
1134 //
1135 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
1136 } else {
1137 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1138 goto Finish;
1139 }
1140 argc -= 2;
1141 argv += 2;
1142 continue;
1143 }
1144
1145 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
1146 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
1147 if (EFI_ERROR (Status)) {
1148 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
1149 goto Finish;
1150 }
1151 argc -= 2;
1152 argv += 2;
1153 continue;
1154 }
1155
1156 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
1157 StringBuffer = argv[1];
1158 if (StringBuffer == NULL) {
1159 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
1160 goto Finish;
1161 }
1162 argc -= 2;
1163 argv += 2;
1164 continue;
1165 }
1166
1167 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
1168 if (argv[1] == NULL) {
1169 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
1170 goto Finish;
1171 }
1172 //
1173 // Verify string is a integrator number
1174 //
1175 for (Index = 0; Index < strlen (argv[1]); Index++) {
1176 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {
1177 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1178 goto Finish;
1179 }
1180 }
1181
1182 sscanf (argv[1], "%d", &VersionNumber);
1183 argc -= 2;
1184 argv += 2;
1185 continue;
1186 }
1187
1188 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
1189 SetPrintLevel (VERBOSE_LOG_LEVEL);
1190 VerboseMsg ("Verbose output Mode Set!");
1191 argc --;
1192 argv ++;
1193 continue;
1194 }
1195
1196 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
1197 SetPrintLevel (KEY_LOG_LEVEL);
1198 KeyMsg ("Quiet output Mode Set!");
1199 argc --;
1200 argv ++;
1201 continue;
1202 }
1203
1204 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
1205 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
1206 if (EFI_ERROR (Status)) {
1207 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1208 goto Finish;
1209 }
1210 if (LogLevel > 9) {
1211 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);
1212 goto Finish;
1213 }
1214 SetPrintLevel (LogLevel);
1215 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
1216 argc -= 2;
1217 argv += 2;
1218 continue;
1219 }
1220
1221 //
1222 // Section File alignment requirement
1223 //
1224 if (stricmp (argv[0], "--sectionalign") == 0) {
1225 if (InputFileAlignNum == 0) {
1226 InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
1227 if (InputFileAlign == NULL) {
1228 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1229 goto Finish;
1230 }
1231 memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
1232 } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1233 InputFileAlign = (UINT32 *) realloc (
1234 InputFileAlign,
1235 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)
1236 );
1237
1238 if (InputFileAlign == NULL) {
1239 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1240 goto Finish;
1241 }
1242 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));
1243 }
1244
1245 Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));
1246 if (EFI_ERROR (Status)) {
1247 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1248 goto Finish;
1249 }
1250 argc -= 2;
1251 argv += 2;
1252 InputFileAlignNum ++;
1253 continue;
1254 }
1255
1256 //
1257 // Get Input file name
1258 //
1259 if ((InputFileNum == 0) && (InputFileName == NULL)) {
1260 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
1261 if (InputFileName == NULL) {
1262 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1263 goto Finish;
1264 }
1265 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1266 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1267 //
1268 // InputFileName buffer too small, need to realloc
1269 //
1270 InputFileName = (CHAR8 **) realloc (
1271 InputFileName,
1272 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
1273 );
1274
1275 if (InputFileName == NULL) {
1276 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1277 goto Finish;
1278 }
1279 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1280 }
1281
1282 InputFileName[InputFileNum++] = argv[0];
1283 argc --;
1284 argv ++;
1285 }
1286
1287 if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {
1288 Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");
1289 goto Finish;
1290 }
1291
1292 VerboseMsg ("%s tool start.", UTILITY_NAME);
1293
1294 //
1295 // Parse all command line parameters to get the corresponding section type.
1296 //
1297 VerboseMsg ("Section type is %s", SectionName);
1298 if (SectionName == NULL) {
1299 //
1300 // No specified Section type, default is SECTION_ALL.
1301 //
1302 SectType = EFI_SECTION_ALL;
1303 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
1304 SectType = EFI_SECTION_COMPRESSION;
1305 if (CompressionName == NULL) {
1306 //
1307 // Default is PI_STD compression algorithm.
1308 //
1309 SectCompSubType = EFI_STANDARD_COMPRESSION;
1310 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
1311 SectCompSubType = EFI_NOT_COMPRESSED;
1312 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
1313 SectCompSubType = EFI_STANDARD_COMPRESSION;
1314 } else {
1315 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
1316 goto Finish;
1317 }
1318 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
1319 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
1320 SectType = EFI_SECTION_GUID_DEFINED;
1321
1322 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
1323 //
1324 // NONE attribute, clear attribute value.
1325 //
1326 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;
1327 }
1328 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1329 (unsigned) VendorGuid.Data1,
1330 VendorGuid.Data2,
1331 VendorGuid.Data3,
1332 VendorGuid.Data4[0],
1333 VendorGuid.Data4[1],
1334 VendorGuid.Data4[2],
1335 VendorGuid.Data4[3],
1336 VendorGuid.Data4[4],
1337 VendorGuid.Data4[5],
1338 VendorGuid.Data4[6],
1339 VendorGuid.Data4[7]);
1340 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
1341 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
1342 }
1343 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
1344 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
1345 }
1346 if (SectGuidHeaderLength != 0) {
1347 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);
1348 }
1349 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
1350 SectType = EFI_SECTION_PE32;
1351 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
1352 SectType = EFI_SECTION_PIC;
1353 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
1354 SectType = EFI_SECTION_TE;
1355 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
1356 SectType = EFI_SECTION_DXE_DEPEX;
1357 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {
1358 SectType = EFI_SECTION_SMM_DEPEX;
1359 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
1360 SectType = EFI_SECTION_VERSION;
1361 if (VersionNumber < 0 || VersionNumber > 65535) {
1362 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);
1363 goto Finish;
1364 }
1365 VerboseMsg ("Version section number is %d", VersionNumber);
1366 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
1367 SectType = EFI_SECTION_USER_INTERFACE;
1368 if (StringBuffer[0] == '\0') {
1369 Error (NULL, 0, 1001, "Missing option", "user interface string");
1370 goto Finish;
1371 }
1372 VerboseMsg ("UI section string name is %s", StringBuffer);
1373 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
1374 SectType = EFI_SECTION_COMPATIBILITY16;
1375 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
1376 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
1377 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
1378 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
1379 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
1380 SectType = EFI_SECTION_RAW;
1381 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
1382 SectType = EFI_SECTION_PEI_DEPEX;
1383 } else {
1384 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
1385 goto Finish;
1386 }
1387
1388 //
1389 // GuidValue is only required by Guided section.
1390 //
1391 if ((SectType != EFI_SECTION_GUID_DEFINED) &&
1392 (SectionName != NULL) &&
1393 (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1394 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
1395 }
1396
1397 //
1398 // Check whether there is input file
1399 //
1400 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
1401 //
1402 // The input file are required for other section type.
1403 //
1404 if (InputFileNum == 0) {
1405 Error (NULL, 0, 1001, "Missing options", "Input files");
1406 goto Finish;
1407 }
1408 }
1409 //
1410 // Check whether there is output file
1411 //
1412 for (Index = 0; Index < InputFileNum; Index ++) {
1413 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);
1414 }
1415 if (OutputFileName == NULL) {
1416 Error (NULL, 0, 1001, "Missing options", "Output file");
1417 goto Finish;
1418 // OutFile = stdout;
1419 }
1420 VerboseMsg ("Output file name is %s", OutputFileName);
1421
1422 //
1423 // At this point, we've fully validated the command line, and opened appropriate
1424 // files, so let's go and do what we've been asked to do...
1425 //
1426 //
1427 // Within this switch, build and write out the section header including any
1428 // section type specific pieces. If there's an input file, it's tacked on later
1429 //
1430 switch (SectType) {
1431 case EFI_SECTION_COMPRESSION:
1432 if (InputFileAlign != NULL) {
1433 free (InputFileAlign);
1434 InputFileAlign = NULL;
1435 }
1436 Status = GenSectionCompressionSection (
1437 InputFileName,
1438 InputFileAlign,
1439 InputFileNum,
1440 SectCompSubType,
1441 &OutFileBuffer
1442 );
1443 break;
1444
1445 case EFI_SECTION_GUID_DEFINED:
1446 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1447 //
1448 // Only process alignment for the default known CRC32 guided section.
1449 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1450 //
1451 free (InputFileAlign);
1452 InputFileAlign = NULL;
1453 }
1454 Status = GenSectionGuidDefinedSection (
1455 InputFileName,
1456 InputFileAlign,
1457 InputFileNum,
1458 &VendorGuid,
1459 SectGuidAttribute,
1460 (UINT32) SectGuidHeaderLength,
1461 &OutFileBuffer
1462 );
1463 break;
1464
1465 case EFI_SECTION_VERSION:
1466 Index = sizeof (EFI_COMMON_SECTION_HEADER);
1467 //
1468 // 2 bytes for the build number UINT16
1469 //
1470 Index += 2;
1471 //
1472 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1473 //
1474 Index += (strlen (StringBuffer) * 2) + 2;
1475 OutFileBuffer = (UINT8 *) malloc (Index);
1476 if (OutFileBuffer == NULL) {
1477 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1478 goto Finish;
1479 }
1480 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
1481 VersionSect->CommonHeader.Type = SectType;
1482 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
1483 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
1484 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
1485 VersionSect->BuildNumber = (UINT16) VersionNumber;
1486 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
1487 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
1488 break;
1489
1490 case EFI_SECTION_USER_INTERFACE:
1491 Index = sizeof (EFI_COMMON_SECTION_HEADER);
1492 //
1493 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1494 //
1495 Index += (strlen (StringBuffer) * 2) + 2;
1496 OutFileBuffer = (UINT8 *) malloc (Index);
1497 if (OutFileBuffer == NULL) {
1498 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1499 goto Finish;
1500 }
1501 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
1502 UiSect->CommonHeader.Type = SectType;
1503 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
1504 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
1505 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
1506 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
1507 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
1508 break;
1509
1510 case EFI_SECTION_ALL:
1511 //
1512 // read all input file contents into a buffer
1513 // first get the size of all file contents
1514 //
1515 Status = GetSectionContents (
1516 InputFileName,
1517 InputFileAlign,
1518 InputFileNum,
1519 OutFileBuffer,
1520 &InputLength
1521 );
1522
1523 if (Status == EFI_BUFFER_TOO_SMALL) {
1524 OutFileBuffer = (UINT8 *) malloc (InputLength);
1525 if (OutFileBuffer == NULL) {
1526 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1527 goto Finish;
1528 }
1529 //
1530 // read all input file contents into a buffer
1531 //
1532 Status = GetSectionContents (
1533 InputFileName,
1534 InputFileAlign,
1535 InputFileNum,
1536 OutFileBuffer,
1537 &InputLength
1538 );
1539 }
1540 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);
1541 break;
1542 default:
1543 //
1544 // All other section types are caught by default (they're all the same)
1545 //
1546 Status = GenSectionCommonLeafSection (
1547 InputFileName,
1548 InputFileNum,
1549 SectType,
1550 &OutFileBuffer
1551 );
1552 break;
1553 }
1554
1555 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {
1556 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);
1557 goto Finish;
1558 }
1559
1560 //
1561 // Get output file length
1562 //
1563 if (SectType != EFI_SECTION_ALL) {
1564 SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;
1565 InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;
1566 if (InputLength == 0xffffff) {
1567 InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
1568 }
1569 }
1570
1571 //
1572 // Write the output file
1573 //
1574 OutFile = fopen (LongFilePath (OutputFileName), "wb");
1575 if (OutFile == NULL) {
1576 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
1577 goto Finish;
1578 }
1579
1580 fwrite (OutFileBuffer, InputLength, 1, OutFile);
1581
1582 Finish:
1583 if (InputFileName != NULL) {
1584 free (InputFileName);
1585 }
1586
1587 if (InputFileAlign != NULL) {
1588 free (InputFileAlign);
1589 }
1590
1591 if (OutFileBuffer != NULL) {
1592 free (OutFileBuffer);
1593 }
1594
1595 if (OutFile != NULL) {
1596 fclose (OutFile);
1597 }
1598
1599 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
1600
1601 return GetUtilityStatus ();
1602 }