]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenSec/GenSec.c
BaseTools: extend FFS alignment to 16M
[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", "128K", "256K",
78 "512K", "1M", "2M", "4M", "8M", "16M"
79 };
80
81 //
82 // Crc32 GUID section related definitions.
83 //
84 typedef struct {
85 EFI_GUID_DEFINED_SECTION GuidSectionHeader;
86 UINT32 CRC32Checksum;
87 } CRC32_SECTION_HEADER;
88
89 typedef struct {
90 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;
91 UINT32 CRC32Checksum;
92 } CRC32_SECTION_HEADER2;
93
94 STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
95 STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
96
97 STATIC
98 VOID
99 Version (
100 VOID
101 )
102 /*++
103
104 Routine Description:
105
106 Print out version information for this utility.
107
108 Arguments:
109
110 None
111
112 Returns:
113
114 None
115
116 --*/
117 {
118 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
119 }
120
121 STATIC
122 VOID
123 Usage (
124 VOID
125 )
126 /*++
127
128 Routine Description:
129
130 Print Help message.
131
132 Arguments:
133
134 VOID
135
136 Returns:
137
138 None
139
140 --*/
141 {
142 //
143 // Summary usage
144 //
145 fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);
146
147 //
148 // Copyright declaration
149 //
150 fprintf (stdout, "Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.\n\n");
151
152 //
153 // Details Option
154 //
155 fprintf (stdout, "Options:\n");
156 fprintf (stdout, " -o FileName, --outputfile FileName\n\
157 File is the SectionFile to be created.\n");
158 fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\
159 SectionType defined in PI spec is one type of\n\
160 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
161 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
162 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
163 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
164 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
165 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
166 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
167 if -s option is not given, \n\
168 EFI_SECTION_ALL is default section type.\n");
169 fprintf (stdout, " -c [Type], --compress [Type]\n\
170 Compress method type can be PI_NONE or PI_STD.\n\
171 if -c option is not given, PI_STD is default type.\n");
172 fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\
173 GuidValue is one specific vendor guid value.\n\
174 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
175 fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
176 GuidHeaderLength is the size of header of guided data\n");
177 fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\
178 GuidAttr is guid section atttributes, which may be\n\
179 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
180 if -r option is not given, default PROCESSING_REQUIRED\n");
181 fprintf (stdout, " -n String, --name String\n\
182 String is a NULL terminated string used in Ui section.\n");
183 fprintf (stdout, " -j Number, --buildnumber Number\n\
184 Number is an integer value between 0 and 65535\n\
185 used in Ver section.\n");
186 fprintf (stdout, " --sectionalign SectionAlign\n\
187 SectionAlign points to section alignment, which support\n\
188 the alignment scope 1~16M. It is specified in same\n\
189 order that the section file is input.\n");
190 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
191 fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
192 fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
193 fprintf (stdout, " --version Show program's version number and exit.\n");
194 fprintf (stdout, " -h, --help Show this help message and exit.\n");
195 }
196
197 VOID
198 Ascii2UnicodeString (
199 CHAR8 *String,
200 CHAR16 *UniString
201 )
202 /*++
203
204 Routine Description:
205
206 Write ascii string as unicode string format to FILE
207
208 Arguments:
209
210 String - Pointer to string that is written to FILE.
211 UniString - Pointer to unicode string
212
213 Returns:
214
215 NULL
216
217 --*/
218 {
219 while (*String != '\0') {
220 *(UniString++) = (CHAR16) *(String++);
221 }
222 //
223 // End the UniString with a NULL.
224 //
225 *UniString = '\0';
226 }
227
228 STATUS
229 GenSectionCommonLeafSection (
230 CHAR8 **InputFileName,
231 UINT32 InputFileNum,
232 UINT8 SectionType,
233 UINT8 **OutFileBuffer
234 )
235 /*++
236
237 Routine Description:
238
239 Generate a leaf section of type other than EFI_SECTION_VERSION
240 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
241 The function won't validate the input file's contents. For
242 common leaf sections, the input file may be a binary file.
243 The utility will add section header to the file.
244
245 Arguments:
246
247 InputFileName - Name of the input file.
248
249 InputFileNum - Number of input files. Should be 1 for leaf section.
250
251 SectionType - A valid section type string
252
253 OutFileBuffer - Buffer pointer to Output file contents
254
255 Returns:
256
257 STATUS_ERROR - can't continue
258 STATUS_SUCCESS - successful return
259
260 --*/
261 {
262 UINT32 InputFileLength;
263 FILE *InFile;
264 UINT8 *Buffer;
265 UINT32 TotalLength;
266 UINT32 HeaderLength;
267 EFI_COMMON_SECTION_HEADER *CommonSect;
268 STATUS Status;
269
270 if (InputFileNum > 1) {
271 Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");
272 return STATUS_ERROR;
273 } else if (InputFileNum < 1) {
274 Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");
275 return STATUS_ERROR;
276 }
277 //
278 // Open the input file
279 //
280 InFile = fopen (LongFilePath (InputFileName[0]), "rb");
281 if (InFile == NULL) {
282 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);
283 return STATUS_ERROR;
284 }
285
286 Status = STATUS_ERROR;
287 Buffer = NULL;
288 //
289 // Seek to the end of the input file so we can determine its size
290 //
291 fseek (InFile, 0, SEEK_END);
292 InputFileLength = ftell (InFile);
293 fseek (InFile, 0, SEEK_SET);
294 DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength);
295 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;
296 //
297 // Size must fit in 3 bytes
298 //
299 //if (TotalLength >= MAX_SECTION_SIZE) {
300 // Error (NULL, 0, 2000, "Invalid parameter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);
301 // goto Done;
302 //}
303 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);
304 if (TotalLength >= MAX_SECTION_SIZE) {
305 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;
306 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);
307 }
308 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
309 //
310 // Fill in the fields in the local section header structure
311 //
312 Buffer = (UINT8 *) malloc ((size_t) TotalLength);
313 if (Buffer == NULL) {
314 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
315 goto Done;
316 }
317 CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;
318 CommonSect->Type = SectionType;
319 if (TotalLength < MAX_SECTION_SIZE) {
320 CommonSect->Size[0] = (UINT8) (TotalLength & 0xff);
321 CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
322 CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
323 } else {
324 memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3);
325 ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength;
326 }
327
328 //
329 // read data from the input file.
330 //
331 if (InputFileLength != 0) {
332 if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {
333 Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);
334 goto Done;
335 }
336 }
337
338 //
339 // Set OutFileBuffer
340 //
341 *OutFileBuffer = Buffer;
342 Status = STATUS_SUCCESS;
343
344 Done:
345 fclose (InFile);
346
347 return Status;
348 }
349
350 STATIC
351 EFI_STATUS
352 StringtoAlignment (
353 IN CHAR8 *AlignBuffer,
354 OUT UINT32 *AlignNumber
355 )
356 /*++
357
358 Routine Description:
359
360 Converts Align String to align value (1~16M).
361
362 Arguments:
363
364 AlignBuffer - Pointer to Align string.
365 AlignNumber - Pointer to Align value.
366
367 Returns:
368
369 EFI_SUCCESS Successfully convert align string to align value.
370 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
371
372 --*/
373 {
374 UINT32 Index = 0;
375 //
376 // Check AlignBuffer
377 //
378 if (AlignBuffer == NULL) {
379 return EFI_INVALID_PARAMETER;
380 }
381 for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {
382 if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {
383 *AlignNumber = 1 << Index;
384 return EFI_SUCCESS;
385 }
386 }
387 return EFI_INVALID_PARAMETER;
388 }
389
390 EFI_STATUS
391 GetSectionContents (
392 CHAR8 **InputFileName,
393 UINT32 *InputFileAlign,
394 UINT32 InputFileNum,
395 UINT8 *FileBuffer,
396 UINT32 *BufferLength
397 )
398 /*++
399
400 Routine Description:
401
402 Get the contents of all section files specified in InputFileName
403 into FileBuffer.
404
405 Arguments:
406
407 InputFileName - Name of the input file.
408
409 InputFileAlign - Alignment required by the input file data.
410
411 InputFileNum - Number of input files. Should be at least 1.
412
413 FileBuffer - Output buffer to contain data
414
415 BufferLength - On input, this is size of the FileBuffer.
416 On output, this is the actual length of the data.
417
418 Returns:
419
420 EFI_SUCCESS on successful return
421 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
422 EFI_ABORTED if unable to open input file.
423 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
424 --*/
425 {
426 UINT32 Size;
427 UINT32 Offset;
428 UINT32 FileSize;
429 UINT32 Index;
430 FILE *InFile;
431 EFI_COMMON_SECTION_HEADER *SectHeader;
432 EFI_COMMON_SECTION_HEADER2 TempSectHeader;
433 EFI_TE_IMAGE_HEADER TeHeader;
434 UINT32 TeOffset;
435 EFI_GUID_DEFINED_SECTION GuidSectHeader;
436 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2;
437 UINT32 HeaderSize;
438
439 if (InputFileNum < 1) {
440 Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file");
441 return EFI_INVALID_PARAMETER;
442 }
443
444 if (BufferLength == NULL) {
445 Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");
446 return EFI_INVALID_PARAMETER;
447 }
448
449 Size = 0;
450 Offset = 0;
451 TeOffset = 0;
452 //
453 // Go through our array of file names and copy their contents
454 // to the output buffer.
455 //
456 for (Index = 0; Index < InputFileNum; Index++) {
457 //
458 // make sure section ends on a DWORD boundary
459 //
460 while ((Size & 0x03) != 0) {
461 if (FileBuffer != NULL && Size < *BufferLength) {
462 FileBuffer[Size] = 0;
463 }
464 Size++;
465 }
466
467 //
468 // Open file and read contents
469 //
470 InFile = fopen (LongFilePath (InputFileName[Index]), "rb");
471 if (InFile == NULL) {
472 Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);
473 return EFI_ABORTED;
474 }
475
476 fseek (InFile, 0, SEEK_END);
477 FileSize = ftell (InFile);
478 fseek (InFile, 0, SEEK_SET);
479 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize);
480 //
481 // Adjust section buffer when section alignment is required.
482 //
483 if (InputFileAlign != NULL) {
484 //
485 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
486 //
487 TeOffset = 0;
488 //
489 // The section might be EFI_COMMON_SECTION_HEADER2
490 // But only Type needs to be checked
491 //
492 if (FileSize >= MAX_SECTION_SIZE) {
493 HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
494 } else {
495 HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
496 }
497 fread (&TempSectHeader, 1, HeaderSize, InFile);
498 if (TempSectHeader.Type == EFI_SECTION_TE) {
499 fread (&TeHeader, 1, sizeof (TeHeader), InFile);
500 if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
501 TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);
502 }
503 } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {
504 fseek (InFile, 0, SEEK_SET);
505 if (FileSize >= MAX_SECTION_SIZE) {
506 fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile);
507 if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
508 HeaderSize = GuidSectHeader2.DataOffset;
509 }
510 } else {
511 fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);
512 if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
513 HeaderSize = GuidSectHeader.DataOffset;
514 }
515 }
516 }
517
518 fseek (InFile, 0, SEEK_SET);
519
520 //
521 // Revert TeOffset to the converse value relative to Alignment
522 // This is to assure the original PeImage Header at Alignment.
523 //
524 if (TeOffset != 0) {
525 TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);
526 TeOffset = TeOffset % InputFileAlign [Index];
527 }
528
529 //
530 // make sure section data meet its alignment requirement by adding one raw pad section.
531 //
532 if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {
533 Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);
534 Offset = Offset - Size - HeaderSize - TeOffset;
535
536 if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {
537 //
538 // The maximal alignment is 64K, the raw section size must be less than 0xffffff
539 //
540 memset (FileBuffer + Size, 0, Offset);
541 SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);
542 SectHeader->Type = EFI_SECTION_RAW;
543 SectHeader->Size[0] = (UINT8) (Offset & 0xff);
544 SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);
545 SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);
546 }
547 DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset);
548
549 Size = Size + Offset;
550 }
551 }
552
553 //
554 // Now read the contents of the file into the buffer
555 // Buffer must be enough to contain the file content.
556 //
557 if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {
558 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
559 Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);
560 fclose (InFile);
561 return EFI_ABORTED;
562 }
563 }
564
565 fclose (InFile);
566 Size += FileSize;
567 }
568
569 //
570 // Set the real required buffer size.
571 //
572 if (Size > *BufferLength) {
573 *BufferLength = Size;
574 return EFI_BUFFER_TOO_SMALL;
575 } else {
576 *BufferLength = Size;
577 return EFI_SUCCESS;
578 }
579 }
580
581 EFI_STATUS
582 GenSectionCompressionSection (
583 CHAR8 **InputFileName,
584 UINT32 *InputFileAlign,
585 UINT32 InputFileNum,
586 UINT8 SectCompSubType,
587 UINT8 **OutFileBuffer
588 )
589 /*++
590
591 Routine Description:
592
593 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
594 Input file must be already sectioned. The function won't validate
595 the input files' contents. Caller should hand in files already
596 with section header.
597
598 Arguments:
599
600 InputFileName - Name of the input file.
601
602 InputFileAlign - Alignment required by the input file data.
603
604 InputFileNum - Number of input files. Should be at least 1.
605
606 SectCompSubType - Specify the compression algorithm requested.
607
608 OutFileBuffer - Buffer pointer to Output file contents
609
610 Returns:
611
612 EFI_SUCCESS on successful return
613 EFI_INVALID_PARAMETER if InputFileNum is less than 1
614 EFI_ABORTED if unable to open input file.
615 EFI_OUT_OF_RESOURCES No resource to complete the operation.
616 --*/
617 {
618 UINT32 TotalLength;
619 UINT32 InputLength;
620 UINT32 CompressedLength;
621 UINT32 HeaderLength;
622 UINT8 *FileBuffer;
623 UINT8 *OutputBuffer;
624 EFI_STATUS Status;
625 EFI_COMPRESSION_SECTION *CompressionSect;
626 EFI_COMPRESSION_SECTION2 *CompressionSect2;
627 COMPRESS_FUNCTION CompressFunction;
628
629 InputLength = 0;
630 FileBuffer = NULL;
631 OutputBuffer = NULL;
632 CompressedLength = 0;
633 TotalLength = 0;
634 //
635 // read all input file contents into a buffer
636 // first get the size of all file contents
637 //
638 Status = GetSectionContents (
639 InputFileName,
640 InputFileAlign,
641 InputFileNum,
642 FileBuffer,
643 &InputLength
644 );
645
646 if (Status == EFI_BUFFER_TOO_SMALL) {
647 FileBuffer = (UINT8 *) malloc (InputLength);
648 if (FileBuffer == NULL) {
649 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
650 return EFI_OUT_OF_RESOURCES;
651 }
652 //
653 // read all input file contents into a buffer
654 //
655 Status = GetSectionContents (
656 InputFileName,
657 InputFileAlign,
658 InputFileNum,
659 FileBuffer,
660 &InputLength
661 );
662 }
663
664 if (EFI_ERROR (Status)) {
665 if (FileBuffer != NULL) {
666 free (FileBuffer);
667 }
668 return Status;
669 }
670
671 if (FileBuffer == NULL) {
672 return EFI_OUT_OF_RESOURCES;
673 }
674
675 CompressFunction = NULL;
676
677 //
678 // Now data is in FileBuffer, compress the data
679 //
680 switch (SectCompSubType) {
681 case EFI_NOT_COMPRESSED:
682 CompressedLength = InputLength;
683 HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
684 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
685 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
686 }
687 TotalLength = CompressedLength + HeaderLength;
688 //
689 // Copy file buffer to the none compressed data.
690 //
691 OutputBuffer = malloc (TotalLength);
692 if (OutputBuffer == NULL) {
693 free (FileBuffer);
694 return EFI_OUT_OF_RESOURCES;
695 }
696 memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);
697 free (FileBuffer);
698 FileBuffer = OutputBuffer;
699 break;
700
701 case EFI_STANDARD_COMPRESSION:
702 CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
703 break;
704
705 default:
706 Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");
707 free (FileBuffer);
708 return EFI_ABORTED;
709 }
710
711 if (CompressFunction != NULL) {
712
713 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
714 if (Status == EFI_BUFFER_TOO_SMALL) {
715 HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
716 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
717 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
718 }
719 TotalLength = CompressedLength + HeaderLength;
720 OutputBuffer = malloc (TotalLength);
721 if (!OutputBuffer) {
722 free (FileBuffer);
723 return EFI_OUT_OF_RESOURCES;
724 }
725
726 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);
727 }
728
729 free (FileBuffer);
730 FileBuffer = OutputBuffer;
731
732 if (EFI_ERROR (Status)) {
733 if (FileBuffer != NULL) {
734 free (FileBuffer);
735 }
736
737 return Status;
738 }
739
740 if (FileBuffer == NULL) {
741 return EFI_OUT_OF_RESOURCES;
742 }
743 }
744
745 DebugMsg (NULL, 0, 9, "comprss file size",
746 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);
747
748 //if (TotalLength >= MAX_SECTION_SIZE) {
749 // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
750 // if (FileBuffer != NULL) {
751 // free (FileBuffer);
752 // }
753 // if (OutputBuffer != NULL) {
754 // free (OutputBuffer);
755 // }
756 // return STATUS_ERROR;
757 //}
758 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
759
760 //
761 // Add the section header for the compressed data
762 //
763 if (TotalLength >= MAX_SECTION_SIZE) {
764 CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;
765
766 memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);
767 CompressionSect2->CommonHeader.Type = EFI_SECTION_COMPRESSION;
768 CompressionSect2->CommonHeader.ExtendedSize = TotalLength;
769 CompressionSect2->CompressionType = SectCompSubType;
770 CompressionSect2->UncompressedLength = InputLength;
771 } else {
772 CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;
773
774 CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION;
775 CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
776 CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
777 CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
778 CompressionSect->CompressionType = SectCompSubType;
779 CompressionSect->UncompressedLength = InputLength;
780 }
781
782 //
783 // Set OutFileBuffer
784 //
785 *OutFileBuffer = FileBuffer;
786
787 return EFI_SUCCESS;
788 }
789
790 EFI_STATUS
791 GenSectionGuidDefinedSection (
792 CHAR8 **InputFileName,
793 UINT32 *InputFileAlign,
794 UINT32 InputFileNum,
795 EFI_GUID *VendorGuid,
796 UINT16 DataAttribute,
797 UINT32 DataHeaderSize,
798 UINT8 **OutFileBuffer
799 )
800 /*++
801
802 Routine Description:
803
804 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
805 Input file must be already sectioned. The function won't validate
806 the input files' contents. Caller should hand in files already
807 with section header.
808
809 Arguments:
810
811 InputFileName - Name of the input file.
812
813 InputFileAlign - Alignment required by the input file data.
814
815 InputFileNum - Number of input files. Should be at least 1.
816
817 VendorGuid - Specify vendor guid value.
818
819 DataAttribute - Specify attribute for the vendor guid data.
820
821 DataHeaderSize- Guided Data Header Size
822
823 OutFileBuffer - Buffer pointer to Output file contents
824
825 Returns:
826
827 EFI_SUCCESS on successful return
828 EFI_INVALID_PARAMETER if InputFileNum is less than 1
829 EFI_ABORTED if unable to open input file.
830 EFI_OUT_OF_RESOURCES No resource to complete the operation.
831
832 --*/
833 {
834 UINT32 TotalLength;
835 UINT32 InputLength;
836 UINT32 Offset;
837 UINT8 *FileBuffer;
838 UINT32 Crc32Checksum;
839 EFI_STATUS Status;
840 CRC32_SECTION_HEADER *Crc32GuidSect;
841 CRC32_SECTION_HEADER2 *Crc32GuidSect2;
842 EFI_GUID_DEFINED_SECTION *VendorGuidSect;
843 EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2;
844
845 InputLength = 0;
846 Offset = 0;
847 FileBuffer = NULL;
848 TotalLength = 0;
849
850 //
851 // read all input file contents into a buffer
852 // first get the size of all file contents
853 //
854 Status = GetSectionContents (
855 InputFileName,
856 InputFileAlign,
857 InputFileNum,
858 FileBuffer,
859 &InputLength
860 );
861
862 if (Status == EFI_BUFFER_TOO_SMALL) {
863 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
864 Offset = sizeof (CRC32_SECTION_HEADER);
865 if (InputLength + Offset >= MAX_SECTION_SIZE) {
866 Offset = sizeof (CRC32_SECTION_HEADER2);
867 }
868 } else {
869 Offset = sizeof (EFI_GUID_DEFINED_SECTION);
870 if (InputLength + Offset >= MAX_SECTION_SIZE) {
871 Offset = sizeof (EFI_GUID_DEFINED_SECTION2);
872 }
873 }
874 TotalLength = InputLength + Offset;
875
876 FileBuffer = (UINT8 *) malloc (InputLength + Offset);
877 if (FileBuffer == NULL) {
878 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
879 return EFI_OUT_OF_RESOURCES;
880 }
881 //
882 // read all input file contents into a buffer
883 //
884 Status = GetSectionContents (
885 InputFileName,
886 InputFileAlign,
887 InputFileNum,
888 FileBuffer + Offset,
889 &InputLength
890 );
891 }
892
893 if (EFI_ERROR (Status)) {
894 if (FileBuffer != NULL) {
895 free (FileBuffer);
896 }
897 Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);
898 return Status;
899 }
900
901 if (InputLength == 0) {
902 if (FileBuffer != NULL) {
903 free (FileBuffer);
904 }
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 // InputLength != 0, but FileBuffer == NULL means out of resources.
911 //
912 if (FileBuffer == NULL) {
913 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
914 return EFI_OUT_OF_RESOURCES;
915 }
916
917 //
918 // Now data is in FileBuffer + Offset
919 //
920 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
921 //
922 // Default Guid section is CRC32.
923 //
924 Crc32Checksum = 0;
925 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
926
927 if (TotalLength >= MAX_SECTION_SIZE) {
928 Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;
929 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
930 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) 0xff;
931 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) 0xff;
932 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) 0xff;
933 Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;
934 memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
935 Crc32GuidSect2->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
936 Crc32GuidSect2->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER2);
937 Crc32GuidSect2->CRC32Checksum = Crc32Checksum;
938 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);
939 } else {
940 Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
941 Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
942 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
943 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
944 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
945 memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
946 Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
947 Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);
948 Crc32GuidSect->CRC32Checksum = Crc32Checksum;
949 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);
950 }
951 } else {
952 if (TotalLength >= MAX_SECTION_SIZE) {
953 VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;
954 VendorGuidSect2->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
955 VendorGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff;
956 VendorGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff;
957 VendorGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff;
958 VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);
959 memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
960 VendorGuidSect2->Attributes = DataAttribute;
961 VendorGuidSect2->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);
962 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);
963 } else {
964 VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
965 VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
966 VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
967 VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
968 VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
969 memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
970 VendorGuidSect->Attributes = DataAttribute;
971 VendorGuidSect->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);
972 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);
973 }
974 }
975 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
976
977 //
978 // Set OutFileBuffer
979 //
980 *OutFileBuffer = FileBuffer;
981
982 return EFI_SUCCESS;
983 }
984
985 int
986 main (
987 int argc,
988 char *argv[]
989 )
990 /*++
991
992 Routine Description:
993
994 Main
995
996 Arguments:
997
998 command line parameters
999
1000 Returns:
1001
1002 EFI_SUCCESS Section header successfully generated and section concatenated.
1003 EFI_ABORTED Could not generate the section
1004 EFI_OUT_OF_RESOURCES No resource to complete the operation.
1005
1006 --*/
1007 {
1008 UINT32 Index;
1009 UINT32 InputFileNum;
1010 FILE *OutFile;
1011 CHAR8 **InputFileName;
1012 CHAR8 *OutputFileName;
1013 CHAR8 *SectionName;
1014 CHAR8 *CompressionName;
1015 CHAR8 *StringBuffer;
1016 EFI_GUID VendorGuid = mZeroGuid;
1017 int VersionNumber;
1018 UINT8 SectType;
1019 UINT8 SectCompSubType;
1020 UINT16 SectGuidAttribute;
1021 UINT64 SectGuidHeaderLength;
1022 EFI_VERSION_SECTION *VersionSect;
1023 EFI_USER_INTERFACE_SECTION *UiSect;
1024 UINT32 InputLength;
1025 UINT8 *OutFileBuffer;
1026 EFI_STATUS Status;
1027 UINT64 LogLevel;
1028 UINT32 *InputFileAlign;
1029 UINT32 InputFileAlignNum;
1030 EFI_COMMON_SECTION_HEADER *SectionHeader;
1031
1032 InputFileAlign = NULL;
1033 InputFileAlignNum = 0;
1034 InputFileName = NULL;
1035 OutputFileName = NULL;
1036 SectionName = NULL;
1037 CompressionName = NULL;
1038 StringBuffer = "";
1039 OutFile = NULL;
1040 VersionNumber = 0;
1041 InputFileNum = 0;
1042 SectType = EFI_SECTION_ALL;
1043 SectCompSubType = 0;
1044 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;
1045 OutFileBuffer = NULL;
1046 InputLength = 0;
1047 Status = STATUS_SUCCESS;
1048 LogLevel = 0;
1049 SectGuidHeaderLength = 0;
1050 VersionSect = NULL;
1051 UiSect = NULL;
1052
1053 SetUtilityName (UTILITY_NAME);
1054
1055 if (argc == 1) {
1056 Error (NULL, 0, 1001, "Missing options", "No options input");
1057 Usage ();
1058 return STATUS_ERROR;
1059 }
1060
1061 //
1062 // Parse command line
1063 //
1064 argc --;
1065 argv ++;
1066
1067 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
1068 Version ();
1069 Usage ();
1070 return STATUS_SUCCESS;
1071 }
1072
1073 if (stricmp (argv[0], "--version") == 0) {
1074 Version ();
1075 return STATUS_SUCCESS;
1076 }
1077
1078 while (argc > 0) {
1079 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
1080 SectionName = argv[1];
1081 if (SectionName == NULL) {
1082 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
1083 goto Finish;
1084 }
1085 argc -= 2;
1086 argv += 2;
1087 continue;
1088 }
1089
1090 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
1091 OutputFileName = argv[1];
1092 if (OutputFileName == NULL) {
1093 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
1094 goto Finish;
1095 }
1096 argc -= 2;
1097 argv += 2;
1098 continue;
1099 }
1100
1101 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
1102 CompressionName = argv[1];
1103 if (CompressionName == NULL) {
1104 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1105 goto Finish;
1106 }
1107 argc -= 2;
1108 argv += 2;
1109 continue;
1110 }
1111
1112 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
1113 Status = StringToGuid (argv[1], &VendorGuid);
1114 if (EFI_ERROR (Status)) {
1115 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1116 goto Finish;
1117 }
1118 argc -= 2;
1119 argv += 2;
1120 continue;
1121 }
1122
1123 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
1124 if (argv[1] == NULL) {
1125 Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");
1126 goto Finish;
1127 }
1128 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
1129 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
1130 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
1131 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
1132 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
1133 //
1134 // NONE attribute
1135 //
1136 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
1137 } else {
1138 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1139 goto Finish;
1140 }
1141 argc -= 2;
1142 argv += 2;
1143 continue;
1144 }
1145
1146 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
1147 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
1148 if (EFI_ERROR (Status)) {
1149 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
1150 goto Finish;
1151 }
1152 argc -= 2;
1153 argv += 2;
1154 continue;
1155 }
1156
1157 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
1158 StringBuffer = argv[1];
1159 if (StringBuffer == NULL) {
1160 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
1161 goto Finish;
1162 }
1163 argc -= 2;
1164 argv += 2;
1165 continue;
1166 }
1167
1168 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
1169 if (argv[1] == NULL) {
1170 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
1171 goto Finish;
1172 }
1173 //
1174 // Verify string is a integrator number
1175 //
1176 for (Index = 0; Index < strlen (argv[1]); Index++) {
1177 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {
1178 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1179 goto Finish;
1180 }
1181 }
1182
1183 sscanf (argv[1], "%d", &VersionNumber);
1184 argc -= 2;
1185 argv += 2;
1186 continue;
1187 }
1188
1189 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
1190 SetPrintLevel (VERBOSE_LOG_LEVEL);
1191 VerboseMsg ("Verbose output Mode Set!");
1192 argc --;
1193 argv ++;
1194 continue;
1195 }
1196
1197 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
1198 SetPrintLevel (KEY_LOG_LEVEL);
1199 KeyMsg ("Quiet output Mode Set!");
1200 argc --;
1201 argv ++;
1202 continue;
1203 }
1204
1205 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
1206 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
1207 if (EFI_ERROR (Status)) {
1208 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1209 goto Finish;
1210 }
1211 if (LogLevel > 9) {
1212 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);
1213 goto Finish;
1214 }
1215 SetPrintLevel (LogLevel);
1216 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
1217 argc -= 2;
1218 argv += 2;
1219 continue;
1220 }
1221
1222 //
1223 // Section File alignment requirement
1224 //
1225 if (stricmp (argv[0], "--sectionalign") == 0) {
1226 if (InputFileAlignNum == 0) {
1227 InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
1228 if (InputFileAlign == NULL) {
1229 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1230 goto Finish;
1231 }
1232 memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
1233 } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1234 InputFileAlign = (UINT32 *) realloc (
1235 InputFileAlign,
1236 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)
1237 );
1238
1239 if (InputFileAlign == NULL) {
1240 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1241 goto Finish;
1242 }
1243 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));
1244 }
1245
1246 Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));
1247 if (EFI_ERROR (Status)) {
1248 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1249 goto Finish;
1250 }
1251 argc -= 2;
1252 argv += 2;
1253 InputFileAlignNum ++;
1254 continue;
1255 }
1256
1257 //
1258 // Get Input file name
1259 //
1260 if ((InputFileNum == 0) && (InputFileName == NULL)) {
1261 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
1262 if (InputFileName == NULL) {
1263 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1264 goto Finish;
1265 }
1266 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1267 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1268 //
1269 // InputFileName buffer too small, need to realloc
1270 //
1271 InputFileName = (CHAR8 **) realloc (
1272 InputFileName,
1273 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
1274 );
1275
1276 if (InputFileName == NULL) {
1277 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1278 goto Finish;
1279 }
1280 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1281 }
1282
1283 InputFileName[InputFileNum++] = argv[0];
1284 argc --;
1285 argv ++;
1286 }
1287
1288 if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {
1289 Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");
1290 goto Finish;
1291 }
1292
1293 VerboseMsg ("%s tool start.", UTILITY_NAME);
1294
1295 //
1296 // Parse all command line parameters to get the corresponding section type.
1297 //
1298 VerboseMsg ("Section type is %s", SectionName);
1299 if (SectionName == NULL) {
1300 //
1301 // No specified Section type, default is SECTION_ALL.
1302 //
1303 SectType = EFI_SECTION_ALL;
1304 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
1305 SectType = EFI_SECTION_COMPRESSION;
1306 if (CompressionName == NULL) {
1307 //
1308 // Default is PI_STD compression algorithm.
1309 //
1310 SectCompSubType = EFI_STANDARD_COMPRESSION;
1311 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
1312 SectCompSubType = EFI_NOT_COMPRESSED;
1313 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
1314 SectCompSubType = EFI_STANDARD_COMPRESSION;
1315 } else {
1316 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
1317 goto Finish;
1318 }
1319 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
1320 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
1321 SectType = EFI_SECTION_GUID_DEFINED;
1322
1323 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
1324 //
1325 // NONE attribute, clear attribute value.
1326 //
1327 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;
1328 }
1329 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1330 (unsigned) VendorGuid.Data1,
1331 VendorGuid.Data2,
1332 VendorGuid.Data3,
1333 VendorGuid.Data4[0],
1334 VendorGuid.Data4[1],
1335 VendorGuid.Data4[2],
1336 VendorGuid.Data4[3],
1337 VendorGuid.Data4[4],
1338 VendorGuid.Data4[5],
1339 VendorGuid.Data4[6],
1340 VendorGuid.Data4[7]);
1341 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
1342 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
1343 }
1344 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
1345 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
1346 }
1347 if (SectGuidHeaderLength != 0) {
1348 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);
1349 }
1350 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
1351 SectType = EFI_SECTION_PE32;
1352 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
1353 SectType = EFI_SECTION_PIC;
1354 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
1355 SectType = EFI_SECTION_TE;
1356 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
1357 SectType = EFI_SECTION_DXE_DEPEX;
1358 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {
1359 SectType = EFI_SECTION_SMM_DEPEX;
1360 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
1361 SectType = EFI_SECTION_VERSION;
1362 if (VersionNumber < 0 || VersionNumber > 65535) {
1363 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);
1364 goto Finish;
1365 }
1366 VerboseMsg ("Version section number is %d", VersionNumber);
1367 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
1368 SectType = EFI_SECTION_USER_INTERFACE;
1369 if (StringBuffer[0] == '\0') {
1370 Error (NULL, 0, 1001, "Missing option", "user interface string");
1371 goto Finish;
1372 }
1373 VerboseMsg ("UI section string name is %s", StringBuffer);
1374 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
1375 SectType = EFI_SECTION_COMPATIBILITY16;
1376 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
1377 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
1378 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
1379 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
1380 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
1381 SectType = EFI_SECTION_RAW;
1382 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
1383 SectType = EFI_SECTION_PEI_DEPEX;
1384 } else {
1385 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
1386 goto Finish;
1387 }
1388
1389 //
1390 // GuidValue is only required by Guided section.
1391 //
1392 if ((SectType != EFI_SECTION_GUID_DEFINED) &&
1393 (SectionName != NULL) &&
1394 (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1395 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
1396 }
1397
1398 //
1399 // Check whether there is input file
1400 //
1401 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
1402 //
1403 // The input file are required for other section type.
1404 //
1405 if (InputFileNum == 0) {
1406 Error (NULL, 0, 1001, "Missing options", "Input files");
1407 goto Finish;
1408 }
1409 }
1410 //
1411 // Check whether there is output file
1412 //
1413 for (Index = 0; Index < InputFileNum; Index ++) {
1414 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);
1415 }
1416 if (OutputFileName == NULL) {
1417 Error (NULL, 0, 1001, "Missing options", "Output file");
1418 goto Finish;
1419 // OutFile = stdout;
1420 }
1421 VerboseMsg ("Output file name is %s", OutputFileName);
1422
1423 //
1424 // At this point, we've fully validated the command line, and opened appropriate
1425 // files, so let's go and do what we've been asked to do...
1426 //
1427 //
1428 // Within this switch, build and write out the section header including any
1429 // section type specific pieces. If there's an input file, it's tacked on later
1430 //
1431 switch (SectType) {
1432 case EFI_SECTION_COMPRESSION:
1433 if (InputFileAlign != NULL) {
1434 free (InputFileAlign);
1435 InputFileAlign = NULL;
1436 }
1437 Status = GenSectionCompressionSection (
1438 InputFileName,
1439 InputFileAlign,
1440 InputFileNum,
1441 SectCompSubType,
1442 &OutFileBuffer
1443 );
1444 break;
1445
1446 case EFI_SECTION_GUID_DEFINED:
1447 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1448 //
1449 // Only process alignment for the default known CRC32 guided section.
1450 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1451 //
1452 free (InputFileAlign);
1453 InputFileAlign = NULL;
1454 }
1455 Status = GenSectionGuidDefinedSection (
1456 InputFileName,
1457 InputFileAlign,
1458 InputFileNum,
1459 &VendorGuid,
1460 SectGuidAttribute,
1461 (UINT32) SectGuidHeaderLength,
1462 &OutFileBuffer
1463 );
1464 break;
1465
1466 case EFI_SECTION_VERSION:
1467 Index = sizeof (EFI_COMMON_SECTION_HEADER);
1468 //
1469 // 2 bytes for the build number UINT16
1470 //
1471 Index += 2;
1472 //
1473 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1474 //
1475 Index += (strlen (StringBuffer) * 2) + 2;
1476 OutFileBuffer = (UINT8 *) malloc (Index);
1477 if (OutFileBuffer == NULL) {
1478 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1479 goto Finish;
1480 }
1481 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
1482 VersionSect->CommonHeader.Type = SectType;
1483 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
1484 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
1485 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
1486 VersionSect->BuildNumber = (UINT16) VersionNumber;
1487 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
1488 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
1489 break;
1490
1491 case EFI_SECTION_USER_INTERFACE:
1492 Index = sizeof (EFI_COMMON_SECTION_HEADER);
1493 //
1494 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1495 //
1496 Index += (strlen (StringBuffer) * 2) + 2;
1497 OutFileBuffer = (UINT8 *) malloc (Index);
1498 if (OutFileBuffer == NULL) {
1499 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1500 goto Finish;
1501 }
1502 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
1503 UiSect->CommonHeader.Type = SectType;
1504 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
1505 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
1506 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
1507 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
1508 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
1509 break;
1510
1511 case EFI_SECTION_ALL:
1512 //
1513 // read all input file contents into a buffer
1514 // first get the size of all file contents
1515 //
1516 Status = GetSectionContents (
1517 InputFileName,
1518 InputFileAlign,
1519 InputFileNum,
1520 OutFileBuffer,
1521 &InputLength
1522 );
1523
1524 if (Status == EFI_BUFFER_TOO_SMALL) {
1525 OutFileBuffer = (UINT8 *) malloc (InputLength);
1526 if (OutFileBuffer == NULL) {
1527 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1528 goto Finish;
1529 }
1530 //
1531 // read all input file contents into a buffer
1532 //
1533 Status = GetSectionContents (
1534 InputFileName,
1535 InputFileAlign,
1536 InputFileNum,
1537 OutFileBuffer,
1538 &InputLength
1539 );
1540 }
1541 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);
1542 break;
1543 default:
1544 //
1545 // All other section types are caught by default (they're all the same)
1546 //
1547 Status = GenSectionCommonLeafSection (
1548 InputFileName,
1549 InputFileNum,
1550 SectType,
1551 &OutFileBuffer
1552 );
1553 break;
1554 }
1555
1556 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {
1557 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);
1558 goto Finish;
1559 }
1560
1561 //
1562 // Get output file length
1563 //
1564 if (SectType != EFI_SECTION_ALL) {
1565 SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;
1566 InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;
1567 if (InputLength == 0xffffff) {
1568 InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
1569 }
1570 }
1571
1572 //
1573 // Write the output file
1574 //
1575 OutFile = fopen (LongFilePath (OutputFileName), "wb");
1576 if (OutFile == NULL) {
1577 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
1578 goto Finish;
1579 }
1580
1581 fwrite (OutFileBuffer, InputLength, 1, OutFile);
1582
1583 Finish:
1584 if (InputFileName != NULL) {
1585 free (InputFileName);
1586 }
1587
1588 if (InputFileAlign != NULL) {
1589 free (InputFileAlign);
1590 }
1591
1592 if (OutFileBuffer != NULL) {
1593 free (OutFileBuffer);
1594 }
1595
1596 if (OutFile != NULL) {
1597 fclose (OutFile);
1598 }
1599
1600 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
1601
1602 return GetUtilityStatus ();
1603 }