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