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