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