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