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