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