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