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