]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenSec/GenSec.c
Check In tool source code based on Build tool project revision r1655.
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
1 /** @file
2
3 Copyright (c) 2004 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 GenSection.c
15
16 Abstract:
17
18 Creates output file that is a properly formed section per the PI spec.
19
20 **/
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26
27 #include <Common/UefiBaseTypes.h>
28 #include <Common/PiFirmwareFile.h>
29 #include <Protocol/GuidedSectionExtraction.h>
30
31 #include "CommonLib.h"
32 #include "Compress.h"
33 #include "Crc32.h"
34 #include "EfiUtilityMsgs.h"
35 #include "ParseInf.h"
36
37 //
38 // GenSec Tool Information
39 //
40 #define UTILITY_NAME "GenSec"
41 #define UTILITY_MAJOR_VERSION 0
42 #define UTILITY_MINOR_VERSION 1
43
44 #define MAX_SECTION_SIZE 0x1000000
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 //
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 STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
92 STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
93
94 STATIC
95 VOID
96 Version (
97 VOID
98 )
99 /*++
100
101 Routine Description:
102
103 Print out version information for this utility.
104
105 Arguments:
106
107 None
108
109 Returns:
110
111 None
112
113 --*/
114 {
115 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
116 }
117
118 STATIC
119 VOID
120 Usage (
121 VOID
122 )
123 /*++
124
125 Routine Description:
126
127 Print Help message.
128
129 Arguments:
130
131 VOID
132
133 Returns:
134
135 None
136
137 --*/
138 {
139 //
140 // Summary usage
141 //
142 fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);
143
144 //
145 // Copyright declaration
146 //
147 fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
148
149 //
150 // Details Option
151 //
152 fprintf (stdout, "Options:\n");
153 fprintf (stdout, " -o FileName, --outputfile FileName\n\
154 File is the SectionFile to be created.\n");
155 fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\
156 SectionType defined in PI spec is one type of\n\
157 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
158 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
159 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
160 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
161 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
162 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
163 EFI_SECTION_PEI_DEPEX. if -s option is not given, \n\
164 EFI_SECTION_ALL is default section type.\n");
165 fprintf (stdout, " -c [Type], --compress [Type]\n\
166 Compress method type can be PI_NONE or PI_STD.\n\
167 if -c option is not given, PI_STD is default type.\n");
168 fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\
169 GuidValue is one specific vendor guid value.\n\
170 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
171 fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
172 GuidHeaderLength is the size of header of guided data\n");
173 fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\
174 GuidAttr is guid section atttributes, which may be\n\
175 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
176 if -r option is not given, default PROCESSING_REQUIRED\n");
177 fprintf (stdout, " -n String, --name String\n\
178 String is a NULL terminated string used in Ui section.\n");
179 fprintf (stdout, " -j Number, --buildnumber Number\n\
180 Number is an integer value between 0000 and 9999\n\
181 used in Ver section.\n");
182 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
183 fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
184 fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
185 fprintf (stdout, " --version Show program's version number and exit.\n");
186 fprintf (stdout, " -h, --help Show this help message and exit.\n");
187 }
188
189 VOID
190 Ascii2UnicodeString (
191 CHAR8 *String,
192 CHAR16 *UniString
193 )
194 /*++
195
196 Routine Description:
197
198 Write ascii string as unicode string format to FILE
199
200 Arguments:
201
202 String - Pointer to string that is written to FILE.
203 UniString - Pointer to unicode string
204
205 Returns:
206
207 NULL
208
209 --*/
210 {
211 while (*String != '\0') {
212 *(UniString++) = (CHAR16) *(String++);
213 }
214 //
215 // End the UniString with a NULL.
216 //
217 *UniString = '\0';
218 }
219
220 STATUS
221 GenSectionCommonLeafSection (
222 CHAR8 **InputFileName,
223 UINT32 InputFileNum,
224 UINT8 SectionType,
225 UINT8 **OutFileBuffer
226 )
227 /*++
228
229 Routine Description:
230
231 Generate a leaf section of type other than EFI_SECTION_VERSION
232 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
233 The function won't validate the input file's contents. For
234 common leaf sections, the input file may be a binary file.
235 The utility will add section header to the file.
236
237 Arguments:
238
239 InputFileName - Name of the input file.
240
241 InputFileNum - Number of input files. Should be 1 for leaf section.
242
243 SectionType - A valid section type string
244
245 OutFileBuffer - Buffer pointer to Output file contents
246
247 Returns:
248
249 STATUS_ERROR - can't continue
250 STATUS_SUCCESS - successful return
251
252 --*/
253 {
254 UINT32 InputFileLength;
255 FILE *InFile;
256 UINT8 *Buffer;
257 UINT32 TotalLength;
258 EFI_COMMON_SECTION_HEADER *CommonSect;
259 STATUS Status;
260
261 if (InputFileNum > 1) {
262 Error (NULL, 0, 2000, "Invalid paramter", "more than one input file specified");
263 return STATUS_ERROR;
264 } else if (InputFileNum < 1) {
265 Error (NULL, 0, 2000, "Invalid paramter", "no input file specified");
266 return STATUS_ERROR;
267 }
268 //
269 // Open the input file
270 //
271 InFile = fopen (InputFileName[0], "rb");
272 if (InFile == NULL) {
273 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);
274 return STATUS_ERROR;
275 }
276
277 Status = STATUS_ERROR;
278 Buffer = NULL;
279 //
280 // Seek to the end of the input file so we can determine its size
281 //
282 fseek (InFile, 0, SEEK_END);
283 InputFileLength = ftell (InFile);
284 fseek (InFile, 0, SEEK_SET);
285 DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %d bytes", InputFileName[0], InputFileLength);
286 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;
287 //
288 // Size must fit in 3 bytes
289 //
290 if (TotalLength >= MAX_SECTION_SIZE) {
291 Error (NULL, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%dM).", InputFileName[0], TotalLength, MAX_SECTION_SIZE>>20);
292 goto Done;
293 }
294 VerboseMsg ("the size of the created section file is %d bytes", TotalLength);
295 //
296 // Fill in the fields in the local section header structure
297 //
298 Buffer = (UINT8 *) malloc ((size_t) TotalLength);
299 if (Buffer == NULL) {
300 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
301 goto Done;
302 }
303 CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;
304 CommonSect->Type = SectionType;
305 CommonSect->Size[0] = (UINT8) (TotalLength & 0xff);
306 CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
307 CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
308
309 //
310 // read data from the input file.
311 //
312 if (InputFileLength != 0) {
313 if (fread (Buffer + sizeof (EFI_COMMON_SECTION_HEADER), (size_t) InputFileLength, 1, InFile) != 1) {
314 Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);
315 goto Done;
316 }
317 }
318
319 //
320 // Set OutFileBuffer
321 //
322 *OutFileBuffer = Buffer;
323 Status = STATUS_SUCCESS;
324
325 Done:
326 fclose (InFile);
327
328 return Status;
329 }
330
331 EFI_STATUS
332 GetSectionContents (
333 CHAR8 **InputFileName,
334 UINT32 InputFileNum,
335 UINT8 *FileBuffer,
336 UINT32 *BufferLength
337 )
338 /*++
339
340 Routine Description:
341
342 Get the contents of all section files specified in InputFileName
343 into FileBuffer.
344
345 Arguments:
346
347 InputFileName - Name of the input file.
348
349 InputFileNum - Number of input files. Should be at least 1.
350
351 FileBuffer - Output buffer to contain data
352
353 BufferLength - On input, this is size of the FileBuffer.
354 On output, this is the actual length of the data.
355
356 Returns:
357
358 EFI_SUCCESS on successful return
359 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
360 EFI_ABORTED if unable to open input file.
361 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
362 --*/
363 {
364 UINT32 Size;
365 UINT32 FileSize;
366 UINT32 Index;
367 FILE *InFile;
368
369 if (InputFileNum < 1) {
370 Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file");
371 return EFI_INVALID_PARAMETER;
372 }
373
374 if (BufferLength == NULL) {
375 Error (NULL, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");
376 return EFI_INVALID_PARAMETER;
377 }
378
379 Size = 0;
380 //
381 // Go through our array of file names and copy their contents
382 // to the output buffer.
383 //
384 for (Index = 0; Index < InputFileNum; Index++) {
385 //
386 // make sure section ends on a DWORD boundary
387 //
388 while ((Size & 0x03) != 0) {
389 if (FileBuffer != NULL && Size < *BufferLength) {
390 FileBuffer[Size] = 0;
391 }
392 Size++;
393 }
394
395 //
396 // Open file and read contents
397 //
398 InFile = fopen (InputFileName[Index], "rb");
399 if (InFile == NULL) {
400 Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);
401 return EFI_ABORTED;
402 }
403
404 fseek (InFile, 0, SEEK_END);
405 FileSize = ftell (InFile);
406 fseek (InFile, 0, SEEK_SET);
407 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %d bytes", InputFileName[Index], FileSize);
408 //
409 // Now read the contents of the file into the buffer
410 // Buffer must be enough to contain the file content.
411 //
412 if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) {
413 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
414 Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);
415 fclose (InFile);
416 return EFI_ABORTED;
417 }
418 }
419
420 fclose (InFile);
421 Size += FileSize;
422 }
423
424 //
425 // Set the real required buffer size.
426 //
427 if (Size > *BufferLength) {
428 *BufferLength = Size;
429 return EFI_BUFFER_TOO_SMALL;
430 } else {
431 *BufferLength = Size;
432 return EFI_SUCCESS;
433 }
434 }
435
436 EFI_STATUS
437 GenSectionCompressionSection (
438 CHAR8 **InputFileName,
439 UINT32 InputFileNum,
440 UINT8 SectCompSubType,
441 UINT8 **OutFileBuffer
442 )
443 /*++
444
445 Routine Description:
446
447 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
448 Input file must be already sectioned. The function won't validate
449 the input files' contents. Caller should hand in files already
450 with section header.
451
452 Arguments:
453
454 InputFileName - Name of the input file.
455
456 InputFileNum - Number of input files. Should be at least 1.
457
458 SectCompSubType - Specify the compression algorithm requested.
459
460 OutFileBuffer - Buffer pointer to Output file contents
461
462 Returns:
463
464 EFI_SUCCESS on successful return
465 EFI_INVALID_PARAMETER if InputFileNum is less than 1
466 EFI_ABORTED if unable to open input file.
467 EFI_OUT_OF_RESOURCES No resource to complete the operation.
468 --*/
469 {
470 UINT32 TotalLength;
471 UINT32 InputLength;
472 UINT32 CompressedLength;
473 UINT8 *FileBuffer;
474 UINT8 *OutputBuffer;
475 EFI_STATUS Status;
476 EFI_COMPRESSION_SECTION *CompressionSect;
477 COMPRESS_FUNCTION CompressFunction;
478
479 InputLength = 0;
480 FileBuffer = NULL;
481 OutputBuffer = NULL;
482 CompressedLength = 0;
483 //
484 // read all input file contents into a buffer
485 // first get the size of all file contents
486 //
487 Status = GetSectionContents (
488 InputFileName,
489 InputFileNum,
490 FileBuffer,
491 &InputLength
492 );
493
494 if (Status == EFI_BUFFER_TOO_SMALL) {
495 FileBuffer = (UINT8 *) malloc (InputLength);
496 if (FileBuffer == NULL) {
497 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
498 return EFI_OUT_OF_RESOURCES;
499 }
500 //
501 // read all input file contents into a buffer
502 //
503 Status = GetSectionContents (
504 InputFileName,
505 InputFileNum,
506 FileBuffer,
507 &InputLength
508 );
509 }
510
511 if (EFI_ERROR (Status)) {
512 if (FileBuffer != NULL) {
513 free (FileBuffer);
514 }
515 return Status;
516 }
517
518 CompressFunction = NULL;
519
520 //
521 // Now data is in FileBuffer, compress the data
522 //
523 switch (SectCompSubType) {
524 case EFI_NOT_COMPRESSED:
525 CompressedLength = InputLength;
526 break;
527
528 case EFI_STANDARD_COMPRESSION:
529 CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
530 break;
531
532 default:
533 Error (NULL, 0, 2000, "Invalid paramter", "unknown compression type");
534 free (FileBuffer);
535 return EFI_ABORTED;
536 }
537
538 if (CompressFunction != NULL) {
539
540 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
541 if (Status == EFI_BUFFER_TOO_SMALL) {
542 OutputBuffer = malloc (CompressedLength + sizeof (EFI_COMPRESSION_SECTION));
543 if (!OutputBuffer) {
544 free (FileBuffer);
545 return EFI_OUT_OF_RESOURCES;
546 }
547
548 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + sizeof (EFI_COMPRESSION_SECTION), &CompressedLength);
549 }
550
551 free (FileBuffer);
552 FileBuffer = OutputBuffer;
553
554 if (EFI_ERROR (Status)) {
555 if (FileBuffer != NULL) {
556 free (FileBuffer);
557 }
558
559 return Status;
560 }
561 }
562
563 DebugMsg (NULL, 0, 9, "comprss file size",
564 "the original section size is %d bytes and the compressed section size is %d bytes", InputLength, CompressedLength);
565 TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);
566 if (TotalLength >= MAX_SECTION_SIZE) {
567 Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
568 if (FileBuffer != NULL) {
569 free (FileBuffer);
570 }
571 if (OutputBuffer != NULL) {
572 free (OutputBuffer);
573 }
574 return STATUS_ERROR;
575 }
576 VerboseMsg ("the size of the created section file is %d bytes", TotalLength);
577
578 //
579 // Add the section header for the compressed data
580 //
581 CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;
582
583 CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION;
584 CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
585 CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
586 CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
587 CompressionSect->CompressionType = SectCompSubType;
588 CompressionSect->UncompressedLength = InputLength;
589
590 //
591 // Set OutFileBuffer
592 //
593 *OutFileBuffer = FileBuffer;
594
595 return EFI_SUCCESS;
596 }
597
598 EFI_STATUS
599 GenSectionGuidDefinedSection (
600 CHAR8 **InputFileName,
601 UINT32 InputFileNum,
602 EFI_GUID *VendorGuid,
603 UINT16 DataAttribute,
604 UINT32 DataHeaderSize,
605 UINT8 **OutFileBuffer
606 )
607 /*++
608
609 Routine Description:
610
611 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
612 Input file must be already sectioned. The function won't validate
613 the input files' contents. Caller should hand in files already
614 with section header.
615
616 Arguments:
617
618 InputFileName - Name of the input file.
619
620 InputFileNum - Number of input files. Should be at least 1.
621
622 VendorGuid - Specify vendor guid value.
623
624 DataAttribute - Specify attribute for the vendor guid data.
625
626 DataHeaderSize- Guided Data Header Size
627
628 OutFileBuffer - Buffer pointer to Output file contents
629
630 Returns:
631
632 EFI_SUCCESS on successful return
633 EFI_INVALID_PARAMETER if InputFileNum is less than 1
634 EFI_ABORTED if unable to open input file.
635 EFI_OUT_OF_RESOURCES No resource to complete the operation.
636
637 --*/
638 {
639 UINT32 TotalLength;
640 UINT32 InputLength;
641 UINT32 Offset;
642 UINT8 *FileBuffer;
643 UINT32 Crc32Checksum;
644 EFI_STATUS Status;
645 CRC32_SECTION_HEADER *Crc32GuidSect;
646 EFI_GUID_DEFINED_SECTION *VendorGuidSect;
647
648 InputLength = 0;
649 Offset = 0;
650 FileBuffer = NULL;
651
652 if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {
653 Offset = sizeof (CRC32_SECTION_HEADER);
654 } else {
655 Offset = sizeof (EFI_GUID_DEFINED_SECTION);
656 }
657
658 //
659 // read all input file contents into a buffer
660 // first get the size of all file contents
661 //
662 Status = GetSectionContents (
663 InputFileName,
664 InputFileNum,
665 FileBuffer,
666 &InputLength
667 );
668
669 if (Status == EFI_BUFFER_TOO_SMALL) {
670 FileBuffer = (UINT8 *) malloc (InputLength + Offset);
671 if (FileBuffer == NULL) {
672 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
673 return EFI_OUT_OF_RESOURCES;
674 }
675 //
676 // read all input file contents into a buffer
677 //
678 Status = GetSectionContents (
679 InputFileName,
680 InputFileNum,
681 FileBuffer + Offset,
682 &InputLength
683 );
684 }
685
686 if (EFI_ERROR (Status)) {
687 if (FileBuffer != NULL) {
688 free (FileBuffer);
689 }
690 Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);
691 return Status;
692 }
693
694 if (InputLength == 0) {
695 Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);
696 return EFI_NOT_FOUND;
697 }
698
699 //
700 // Now data is in FileBuffer + Offset
701 //
702 if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {
703 //
704 // Default Guid section is CRC32.
705 //
706 Crc32Checksum = 0;
707 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
708
709 TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);
710 if (TotalLength >= MAX_SECTION_SIZE) {
711 Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
712 free (FileBuffer);
713 return STATUS_ERROR;
714 }
715
716 Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
717 Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
718 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
719 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
720 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
721 memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
722 Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
723 Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);
724 Crc32GuidSect->CRC32Checksum = Crc32Checksum;
725 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", Crc32GuidSect->GuidSectionHeader.DataOffset);
726
727 } else {
728 TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION);
729 if (TotalLength >= MAX_SECTION_SIZE) {
730 Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
731 free (FileBuffer);
732 return STATUS_ERROR;
733 }
734
735 VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
736 VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
737 VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
738 VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
739 VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
740 memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
741 VendorGuidSect->Attributes = DataAttribute;
742 VendorGuidSect->DataOffset = sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize;
743 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", VendorGuidSect->DataOffset);
744 }
745 VerboseMsg ("the size of the created section file is %d bytes", TotalLength);
746
747 //
748 // Set OutFileBuffer
749 //
750 *OutFileBuffer = FileBuffer;
751
752 return EFI_SUCCESS;
753 }
754
755 int
756 main (
757 int argc,
758 char *argv[]
759 )
760 /*++
761
762 Routine Description:
763
764 Main
765
766 Arguments:
767
768 command line parameters
769
770 Returns:
771
772 EFI_SUCCESS Section header successfully generated and section concatenated.
773 EFI_ABORTED Could not generate the section
774 EFI_OUT_OF_RESOURCES No resource to complete the operation.
775
776 --*/
777 {
778 UINT32 Index;
779 UINT32 InputFileNum;
780 FILE *InFile;
781 FILE *OutFile;
782 CHAR8 **InputFileName;
783 CHAR8 *OutputFileName;
784 CHAR8 *SectionName;
785 CHAR8 *CompressionName;
786 CHAR8 *StringBuffer;
787 EFI_GUID VendorGuid = mZeroGuid;
788 INT32 VersionNumber;
789 UINT8 SectType;
790 UINT8 SectCompSubType;
791 UINT16 SectGuidAttribute;
792 UINT64 SectGuidHeaderLength;
793 EFI_VERSION_SECTION *VersionSect;
794 EFI_USER_INTERFACE_SECTION *UiSect;
795 UINT32 InputLength;
796 UINT8 *OutFileBuffer;
797 EFI_STATUS Status;
798 UINT64 LogLevel;
799
800 InputFileName = NULL;
801 OutputFileName = NULL;
802 SectionName = NULL;
803 CompressionName = NULL;
804 StringBuffer = "";
805 InFile = NULL;
806 OutFile = NULL;
807 VersionNumber = 0;
808 InputFileNum = 0;
809 SectType = EFI_SECTION_ALL;
810 SectCompSubType = 0;
811 SectGuidAttribute = 0;
812 OutFileBuffer = NULL;
813 InputLength = 0;
814 Status = STATUS_SUCCESS;
815 LogLevel = 0;
816 SectGuidHeaderLength = 0;
817 VersionSect = NULL;
818 UiSect = NULL;
819
820 SetUtilityName (UTILITY_NAME);
821
822 if (argc == 1) {
823 Error (NULL, 0, 1001, "Missing options", "No options input");
824 Usage ();
825 return STATUS_ERROR;
826 }
827
828 //
829 // Parse command line
830 //
831 argc --;
832 argv ++;
833
834 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
835 Version ();
836 Usage ();
837 return STATUS_SUCCESS;
838 }
839
840 if (stricmp (argv[0], "--version") == 0) {
841 Version ();
842 return STATUS_SUCCESS;
843 }
844
845 while (argc > 0) {
846 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
847 SectionName = argv[1];
848 if (SectionName == NULL) {
849 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
850 goto Finish;
851 }
852 argc -= 2;
853 argv += 2;
854 continue;
855 }
856
857 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
858 OutputFileName = argv[1];
859 if (OutputFileName == NULL) {
860 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
861 goto Finish;
862 }
863 argc -= 2;
864 argv += 2;
865 continue;
866 }
867
868 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
869 CompressionName = argv[1];
870 if (CompressionName == NULL) {
871 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
872 goto Finish;
873 }
874 argc -= 2;
875 argv += 2;
876 continue;
877 }
878
879 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
880 Status = StringToGuid (argv[1], &VendorGuid);
881 if (EFI_ERROR (Status)) {
882 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
883 goto Finish;
884 }
885 argc -= 2;
886 argv += 2;
887 continue;
888 }
889
890 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
891 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
892 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
893 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
894 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
895 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
896 //
897 // NONE attribute
898 //
899 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
900 } else {
901 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
902 goto Finish;
903 }
904 argc -= 2;
905 argv += 2;
906 continue;
907 }
908
909 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
910 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
911 if (EFI_ERROR (Status)) {
912 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
913 goto Finish;
914 }
915 argc -= 2;
916 argv += 2;
917 continue;
918 }
919
920 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
921 StringBuffer = argv[1];
922 if (StringBuffer == NULL) {
923 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
924 goto Finish;
925 }
926 argc -= 2;
927 argv += 2;
928 continue;
929 }
930
931 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
932 if (argv[1] == NULL) {
933 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
934 goto Finish;
935 }
936 //
937 // Verify string is a integrator number
938 //
939 for (Index = 0; Index < strlen (argv[1]); Index++) {
940 if ((argv[1][Index] != '-') && (isdigit (argv[1][Index]) == 0)) {
941 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
942 goto Finish;
943 }
944 }
945
946 sscanf (argv[1], "%d", &VersionNumber);
947 argc -= 2;
948 argv += 2;
949 continue;
950 }
951
952 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
953 SetPrintLevel (VERBOSE_LOG_LEVEL);
954 VerboseMsg ("Verbose output Mode Set!");
955 argc --;
956 argv ++;
957 continue;
958 }
959
960 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
961 SetPrintLevel (KEY_LOG_LEVEL);
962 KeyMsg ("Quiet output Mode Set!");
963 argc --;
964 argv ++;
965 continue;
966 }
967
968 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
969 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
970 if (EFI_ERROR (Status)) {
971 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
972 goto Finish;
973 }
974 if (LogLevel > 9) {
975 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", LogLevel);
976 goto Finish;
977 }
978 SetPrintLevel (LogLevel);
979 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
980 argc -= 2;
981 argv += 2;
982 continue;
983 }
984
985 //
986 // Get Input file name
987 //
988 if ((InputFileNum == 0) && (InputFileName == NULL)) {
989 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
990 if (InputFileName == NULL) {
991 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
992 return 1;
993 }
994
995 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
996 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
997 //
998 // InputFileName buffer too small, need to realloc
999 //
1000 InputFileName = (CHAR8 **) realloc (
1001 InputFileName,
1002 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
1003 );
1004
1005 if (InputFileName == NULL) {
1006 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1007 return 1;
1008 }
1009
1010 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1011 }
1012
1013 InputFileName[InputFileNum++] = argv[0];
1014 argc --;
1015 argv ++;
1016 }
1017
1018 VerboseMsg ("%s tool start.", UTILITY_NAME);
1019
1020 //
1021 // Parse all command line parameters to get the corresponding section type.
1022 //
1023 VerboseMsg ("Section type is %s", SectionName);
1024 if (SectionName == NULL) {
1025 //
1026 // No specified Section type, default is SECTION_ALL.
1027 //
1028 SectType = EFI_SECTION_ALL;
1029 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
1030 SectType = EFI_SECTION_COMPRESSION;
1031 if (CompressionName == NULL) {
1032 //
1033 // Default is PI_STD compression algorithm.
1034 //
1035 SectCompSubType = EFI_STANDARD_COMPRESSION;
1036 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
1037 SectCompSubType = EFI_NOT_COMPRESSED;
1038 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
1039 SectCompSubType = EFI_STANDARD_COMPRESSION;
1040 } else {
1041 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
1042 goto Finish;
1043 }
1044 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
1045 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
1046 SectType = EFI_SECTION_GUID_DEFINED;
1047
1048 if (CompareGuid (&VendorGuid, &mZeroGuid) == 0) {
1049 memcpy (&VendorGuid, &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
1050 }
1051
1052 if (SectGuidAttribute == 0) {
1053 SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
1054 }
1055 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
1056 //
1057 // NONE attribute, clear attribute value.
1058 //
1059 SectGuidAttribute = 0;
1060 }
1061 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1062 VendorGuid.Data1,
1063 VendorGuid.Data2,
1064 VendorGuid.Data3,
1065 VendorGuid.Data4[0],
1066 VendorGuid.Data4[1],
1067 VendorGuid.Data4[2],
1068 VendorGuid.Data4[3],
1069 VendorGuid.Data4[4],
1070 VendorGuid.Data4[5],
1071 VendorGuid.Data4[6],
1072 VendorGuid.Data4[7]);
1073 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
1074 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
1075 }
1076 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
1077 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
1078 }
1079 if (SectGuidHeaderLength != 0) {
1080 VerboseMsg ("Guid Data Header size is 0x%x", SectGuidHeaderLength);
1081 }
1082 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
1083 SectType = EFI_SECTION_PE32;
1084 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
1085 SectType = EFI_SECTION_PIC;
1086 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
1087 SectType = EFI_SECTION_TE;
1088 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
1089 SectType = EFI_SECTION_DXE_DEPEX;
1090 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
1091 SectType = EFI_SECTION_VERSION;
1092 if (VersionNumber < 0 || VersionNumber > 9999) {
1093 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber);
1094 goto Finish;
1095 }
1096 VerboseMsg ("Version section number is %d", VersionNumber);
1097 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
1098 SectType = EFI_SECTION_USER_INTERFACE;
1099 if (StringBuffer[0] == '\0') {
1100 Error (NULL, 0, 1001, "Missing option", "user interface string");
1101 goto Finish;
1102 }
1103 VerboseMsg ("UI section string name is %s", StringBuffer);
1104 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
1105 SectType = EFI_SECTION_COMPATIBILITY16;
1106 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
1107 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
1108 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
1109 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
1110 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
1111 SectType = EFI_SECTION_RAW;
1112 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
1113 SectType = EFI_SECTION_PEI_DEPEX;
1114 } else {
1115 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
1116 goto Finish;
1117 }
1118
1119 //
1120 // GuidValue is only required by Guided section.
1121 //
1122 if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1123 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
1124 }
1125
1126 //
1127 // Check whether there is input file
1128 //
1129 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
1130 //
1131 // The input file are required for other section type.
1132 //
1133 if (InputFileNum == 0) {
1134 Error (NULL, 0, 1001, "Missing options", "Input files");
1135 goto Finish;
1136 }
1137 }
1138 //
1139 // Check whether there is output file
1140 //
1141 for (Index = 0; Index < InputFileNum; Index ++) {
1142 VerboseMsg ("the %dth input file name is %s", Index, InputFileName[Index]);
1143 }
1144 if (OutputFileName == NULL) {
1145 Error (NULL, 0, 1001, "Missing options", "Output file");
1146 goto Finish;
1147 // OutFile = stdout;
1148 }
1149 VerboseMsg ("Output file name is %s", OutputFileName);
1150
1151 //
1152 // At this point, we've fully validated the command line, and opened appropriate
1153 // files, so let's go and do what we've been asked to do...
1154 //
1155 //
1156 // Within this switch, build and write out the section header including any
1157 // section type specific pieces. If there's an input file, it's tacked on later
1158 //
1159 switch (SectType) {
1160 case EFI_SECTION_COMPRESSION:
1161 Status = GenSectionCompressionSection (
1162 InputFileName,
1163 InputFileNum,
1164 SectCompSubType,
1165 &OutFileBuffer
1166 );
1167 break;
1168
1169 case EFI_SECTION_GUID_DEFINED:
1170 Status = GenSectionGuidDefinedSection (
1171 InputFileName,
1172 InputFileNum,
1173 &VendorGuid,
1174 SectGuidAttribute,
1175 (UINT32) SectGuidHeaderLength,
1176 &OutFileBuffer
1177 );
1178 break;
1179
1180 case EFI_SECTION_VERSION:
1181 Index = sizeof (EFI_COMMON_SECTION_HEADER);
1182 //
1183 // 2 bytes for the build number UINT16
1184 //
1185 Index += 2;
1186 //
1187 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1188 //
1189 Index += (strlen (StringBuffer) * 2) + 2;
1190 OutFileBuffer = (UINT8 *) malloc (Index);
1191 if (OutFileBuffer == NULL) {
1192 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1193 goto Finish;
1194 }
1195 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
1196 VersionSect->CommonHeader.Type = SectType;
1197 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
1198 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
1199 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
1200 VersionSect->BuildNumber = (UINT16) VersionNumber;
1201 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
1202 VerboseMsg ("the size of the created section file is %d bytes", Index);
1203 break;
1204
1205 case EFI_SECTION_USER_INTERFACE:
1206 Index = sizeof (EFI_COMMON_SECTION_HEADER);
1207 //
1208 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1209 //
1210 Index += (strlen (StringBuffer) * 2) + 2;
1211 OutFileBuffer = (UINT8 *) malloc (Index);
1212 if (OutFileBuffer == NULL) {
1213 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1214 goto Finish;
1215 }
1216 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
1217 UiSect->CommonHeader.Type = SectType;
1218 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
1219 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
1220 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
1221 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
1222 VerboseMsg ("the size of the created section file is %d bytes", Index);
1223 break;
1224
1225 case EFI_SECTION_ALL:
1226 //
1227 // read all input file contents into a buffer
1228 // first get the size of all file contents
1229 //
1230 Status = GetSectionContents (
1231 InputFileName,
1232 InputFileNum,
1233 OutFileBuffer,
1234 &InputLength
1235 );
1236
1237 if (Status == EFI_BUFFER_TOO_SMALL) {
1238 OutFileBuffer = (UINT8 *) malloc (InputLength);
1239 if (OutFileBuffer == NULL) {
1240 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1241 goto Finish;
1242 }
1243 //
1244 // read all input file contents into a buffer
1245 //
1246 Status = GetSectionContents (
1247 InputFileName,
1248 InputFileNum,
1249 OutFileBuffer,
1250 &InputLength
1251 );
1252 }
1253 VerboseMsg ("the size of the created section file is %d bytes", InputLength);
1254 break;
1255 default:
1256 //
1257 // All other section types are caught by default (they're all the same)
1258 //
1259 Status = GenSectionCommonLeafSection (
1260 InputFileName,
1261 InputFileNum,
1262 SectType,
1263 &OutFileBuffer
1264 );
1265 break;
1266 }
1267
1268 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {
1269 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (UINTN) Status);
1270 goto Finish;
1271 }
1272
1273 //
1274 // Get output file length
1275 //
1276 if (SectType != EFI_SECTION_ALL) {
1277 InputLength = SECTION_SIZE (OutFileBuffer);
1278 }
1279
1280 //
1281 // Write the output file
1282 //
1283 OutFile = fopen (OutputFileName, "wb");
1284 if (OutFile == NULL) {
1285 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
1286 goto Finish;
1287 }
1288
1289 fwrite (OutFileBuffer, InputLength, 1, OutFile);
1290
1291 Finish:
1292 if (InputFileName != NULL) {
1293 free (InputFileName);
1294 }
1295
1296 if (OutFileBuffer != NULL) {
1297 free (OutFileBuffer);
1298 }
1299
1300 if (OutFile != NULL) {
1301 fclose (OutFile);
1302 }
1303
1304 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
1305
1306 return GetUtilityStatus ();
1307 }