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