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