]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/CCode/Source/GenSection/GenSection.c
1. Refresh applicable library instances after one illegal library instance is removed.
[mirror_edk2.git] / Tools / CCode / Source / GenSection / GenSection.c
1 /*++
2
3 Copyright (c) 2004, 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 FV spec.
19
20 --*/
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <Common/UefiBaseTypes.h>
27 #include <Common/FirmwareVolumeImageFormat.h>
28 #include <Protocol/GuidedSectionExtraction.h>
29
30 #include "CommonLib.h"
31 #include "Compress.h"
32 #include "EfiCustomizedCompress.h"
33 #include "Crc32.h"
34 #include "EfiUtilityMsgs.h"
35 #include "GenSection.h"
36
37
38 #define UTILITY_NAME "GenSection"
39 #define UTILITY_MAJOR_VERSION 0
40 #define UTILITY_MINOR_VERSION 1
41
42
43 #define PARAMETER_NOT_SPECIFIED "Parameter not specified"
44 #define MAXIMUM_INPUT_FILE_NUM 10
45
46 char *SectionTypeName[] = {
47 NULL, // 0x00 - reserved
48 "EFI_SECTION_COMPRESSION", // 0x01
49 "EFI_SECTION_GUID_DEFINED", // 0x02
50 NULL, // 0x03 - reserved
51 NULL, // 0x04 - reserved
52 NULL, // 0x05 - reserved
53 NULL, // 0x06 - reserved
54 NULL, // 0x07 - reserved
55 NULL, // 0x08 - reserved
56 NULL, // 0x09 - reserved
57 NULL, // 0x0A - reserved
58 NULL, // 0x0B - reserved
59 NULL, // 0x0C - reserved
60 NULL, // 0x0D - reserved
61 NULL, // 0x0E - reserved
62 NULL, // 0x0F - reserved
63 "EFI_SECTION_PE32", // 0x10
64 "EFI_SECTION_PIC", // 0x11
65 "EFI_SECTION_TE", // 0x12
66 "EFI_SECTION_DXE_DEPEX", // 0x13
67 "EFI_SECTION_VERSION", // 0x14
68 "EFI_SECTION_USER_INTERFACE", // 0x15
69 "EFI_SECTION_COMPATIBILITY16", // 0x16
70 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
71 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
72 "EFI_SECTION_RAW", // 0x19
73 NULL, // 0x1A
74 "EFI_SECTION_PEI_DEPEX" // 0x1B
75 };
76
77 char *CompressionTypeName[] = { "NONE", "STANDARD" };
78 char *GUIDedSectionTypeName[] = { "CRC32" };
79 EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
80
81 static
82 void
83 Version(
84 void
85 )
86 /*++
87
88 Routine Description:
89
90 Print out version information for this utility.
91
92 Arguments:
93
94 None
95
96 Returns:
97
98 None
99
100 --*/
101 {
102 printf ("%s v%d.%d -Utility to create output file with formed section per the FV spec.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
103 printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
104 }
105
106 static
107 VOID
108 Usage (
109 VOID
110 )
111 {
112 UINTN SectionType;
113 UINTN DisplayCount;
114
115 Version();
116
117 printf ("\nUsage: "UTILITY_NAME " -i InputFile -o OutputFile -s SectionType [SectionType params]\n\n");
118 printf (" Where SectionType is one of the following section types:\n\n");
119
120 DisplayCount = 0;
121 for (SectionType = 0; SectionType <= EFI_SECTION_LAST_SECTION_TYPE; SectionType++) {
122 if (SectionTypeName[SectionType] != NULL) {
123 printf (" %s\n", SectionTypeName[SectionType]);
124 }
125 }
126
127 printf ("\n and SectionType dependent parameters are as follows:\n\n");
128 printf (
129 " %s: -t < %s | %s >\n",
130 SectionTypeName[EFI_SECTION_COMPRESSION],
131 CompressionTypeName[EFI_NOT_COMPRESSED],
132 CompressionTypeName[EFI_STANDARD_COMPRESSION]
133 );
134 printf (
135 " %s: -t < %s >\n"" // Currently only CRC32 is supported\n\n",
136 SectionTypeName[EFI_SECTION_GUID_DEFINED],
137 GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]
138 );
139 printf (
140 " %s: -v VersionNumber\n"" [-a \"Version string\"]\n\n",
141 SectionTypeName[EFI_SECTION_VERSION]
142 );
143 printf (
144 " %s: -a \"Human readable name\"\n\n",
145 SectionTypeName[EFI_SECTION_USER_INTERFACE]
146 );
147 }
148
149 VOID
150 Ascii2UnicodeWriteString (
151 char *String,
152 FILE *OutFile,
153 BOOLEAN WriteLangCode
154 )
155 {
156 UINTN Index;
157 UINT8 AsciiNull;
158 //
159 // BUGBUG need to get correct language code...
160 //
161 char *EnglishLangCode = "eng";
162 AsciiNull = 0;
163 //
164 // first write the language code (english only)
165 //
166 if (WriteLangCode) {
167 fwrite (EnglishLangCode, 1, 4, OutFile);
168 }
169 //
170 // Next, write out the string... Convert ASCII to Unicode in the process.
171 //
172 Index = 0;
173 do {
174 fwrite (&String[Index], 1, 1, OutFile);
175 fwrite (&AsciiNull, 1, 1, OutFile);
176 } while (String[Index++] != 0);
177 }
178
179 STATUS
180 GenSectionCommonLeafSection (
181 char **InputFileName,
182 int InputFileNum,
183 UINTN SectionType,
184 FILE *OutFile
185 )
186 /*++
187
188 Routine Description:
189
190 Generate a leaf section of type other than EFI_SECTION_VERSION
191 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
192 The function won't validate the input file's contents. For
193 common leaf sections, the input file may be a binary file.
194 The utility will add section header to the file.
195
196 Arguments:
197
198 InputFileName - Name of the input file.
199
200 InputFileNum - Number of input files. Should be 1 for leaf section.
201
202 SectionType - A valid section type string
203
204 OutFile - Output file handle
205
206 Returns:
207
208 STATUS_ERROR - can't continue
209 STATUS_SUCCESS - successful return
210
211 --*/
212 {
213 UINT64 InputFileLength;
214 FILE *InFile;
215 UINT8 *Buffer;
216 INTN TotalLength;
217 EFI_COMMON_SECTION_HEADER CommonSect;
218 STATUS Status;
219
220 if (InputFileNum > 1) {
221 Error (NULL, 0, 0, "invalid parameter", "more than one input file specified");
222 return STATUS_ERROR;
223 } else if (InputFileNum < 1) {
224 Error (NULL, 0, 0, "no input file specified", NULL);
225 return STATUS_ERROR;
226 }
227 //
228 // Open the input file
229 //
230 InFile = fopen (InputFileName[0], "rb");
231 if (InFile == NULL) {
232 Error (NULL, 0, 0, InputFileName[0], "failed to open input file");
233 return STATUS_ERROR;
234 }
235
236 Status = STATUS_ERROR;
237 Buffer = NULL;
238 //
239 // Seek to the end of the input file so we can determine its size
240 //
241 fseek (InFile, 0, SEEK_END);
242 fgetpos (InFile, &InputFileLength);
243 fseek (InFile, 0, SEEK_SET);
244 //
245 // Fill in the fields in the local section header structure
246 //
247 CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
248 TotalLength = sizeof (CommonSect) + (INTN) InputFileLength;
249 //
250 // Size must fit in 3 bytes
251 //
252 if (TotalLength >= 0x1000000) {
253 Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit", TotalLength);
254 goto Done;
255 }
256 //
257 // Now copy the size into the section header and write out the section header
258 //
259 memcpy (&CommonSect.Size, &TotalLength, 3);
260 fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
261 //
262 // Allocate a buffer to read in the contents of the input file. Then
263 // read it in as one block and write it to the output file.
264 //
265 if (InputFileLength != 0) {
266 Buffer = (UINT8 *) malloc ((size_t) InputFileLength);
267 if (Buffer == NULL) {
268 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
269 goto Done;
270 }
271
272 if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) {
273 Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file");
274 goto Done;
275 }
276
277 if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) {
278 Error (NULL, 0, 0, "failed to write to output file", NULL);
279 goto Done;
280 }
281 }
282
283 Status = STATUS_SUCCESS;
284 Done:
285 fclose (InFile);
286 if (Buffer != NULL) {
287 free (Buffer);
288 }
289
290 return Status;
291 }
292
293 EFI_STATUS
294 GetSectionContents (
295 char **InputFileName,
296 int InputFileNum,
297 UINT8 *FileBuffer,
298 UINTN *BufferLength
299 )
300 /*++
301
302 Routine Description:
303
304 Get the contents of all section files specified in InputFileName
305 into FileBuffer.
306
307 Arguments:
308
309 InputFileName - Name of the input file.
310
311 InputFileNum - Number of input files. Should be at least 1.
312
313 FileBuffer - Output buffer to contain data
314
315 BufferLength - Actual length of the data
316
317 Returns:
318
319 EFI_SUCCESS on successful return
320 EFI_INVALID_PARAMETER if InputFileNum is less than 1
321 EFI_ABORTED if unable to open input file.
322
323 --*/
324 {
325 UINTN Size;
326 UINTN FileSize;
327 INTN Index;
328 FILE *InFile;
329
330 if (InputFileNum < 1) {
331 Error (NULL, 0, 0, "must specify at least one input file", NULL);
332 return EFI_INVALID_PARAMETER;
333 }
334
335 Size = 0;
336 //
337 // Go through our array of file names and copy their contents
338 // to the output buffer.
339 //
340 for (Index = 0; Index < InputFileNum; Index++) {
341 InFile = fopen (InputFileName[Index], "rb");
342 if (InFile == NULL) {
343 Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");
344 return EFI_ABORTED;
345 }
346
347 fseek (InFile, 0, SEEK_END);
348 FileSize = ftell (InFile);
349 fseek (InFile, 0, SEEK_SET);
350 //
351 // Now read the contents of the file into the buffer
352 //
353 if (FileSize > 0) {
354 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
355 Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");
356 fclose (InFile);
357 return EFI_ABORTED;
358 }
359 }
360
361 fclose (InFile);
362 Size += (UINTN) FileSize;
363 //
364 // make sure section ends on a DWORD boundary
365 //
366 while ((Size & 0x03) != 0) {
367 FileBuffer[Size] = 0;
368 Size++;
369 }
370 }
371
372 *BufferLength = Size;
373 return EFI_SUCCESS;
374 }
375
376 EFI_STATUS
377 GenSectionCompressionSection (
378 char **InputFileName,
379 int InputFileNum,
380 UINTN SectionType,
381 UINTN SectionSubType,
382 FILE *OutFile
383 )
384 /*++
385
386 Routine Description:
387
388 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
389 Input file must be already sectioned. The function won't validate
390 the input files' contents. Caller should hand in files already
391 with section header.
392
393 Arguments:
394
395 InputFileName - Name of the input file.
396
397 InputFileNum - Number of input files. Should be at least 1.
398
399 SectionType - Section type to generate. Should be
400 EFI_SECTION_COMPRESSION
401
402 SectionSubType - Specify the compression algorithm requested.
403
404 OutFile - Output file handle
405
406 Returns:
407
408 EFI_SUCCESS on successful return
409 EFI_INVALID_PARAMETER if InputFileNum is less than 1
410 EFI_ABORTED if unable to open input file.
411 EFI_OUT_OF_RESOURCES No resource to complete the operation.
412 --*/
413 {
414 UINTN TotalLength;
415 UINTN InputLength;
416 UINTN CompressedLength;
417 UINT8 *FileBuffer;
418 UINT8 *OutputBuffer;
419 EFI_STATUS Status;
420 EFI_COMPRESSION_SECTION CompressionSect;
421 COMPRESS_FUNCTION CompressFunction;
422
423 if (SectionType != EFI_SECTION_COMPRESSION) {
424 Error (NULL, 0, 0, "parameter must be EFI_SECTION_COMPRESSION", NULL);
425 return EFI_INVALID_PARAMETER;
426 }
427
428 InputLength = 0;
429 FileBuffer = NULL;
430 OutputBuffer = NULL;
431 CompressedLength = 0;
432 FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
433 if (FileBuffer == NULL) {
434 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
435 return EFI_OUT_OF_RESOURCES;
436 }
437 //
438 // read all input file contents into a buffer
439 //
440 Status = GetSectionContents (
441 InputFileName,
442 InputFileNum,
443 FileBuffer,
444 &InputLength
445 );
446 if (EFI_ERROR (Status)) {
447 free (FileBuffer);
448 return Status;
449 }
450
451 CompressFunction = NULL;
452
453 //
454 // Now data is in FileBuffer, compress the data
455 //
456 switch (SectionSubType) {
457 case EFI_NOT_COMPRESSED:
458 CompressedLength = InputLength;
459 break;
460
461 case EFI_STANDARD_COMPRESSION:
462 CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
463 break;
464
465 case EFI_CUSTOMIZED_COMPRESSION:
466 CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress;
467 break;
468
469 default:
470 Error (NULL, 0, 0, "unknown compression type", NULL);
471 free (FileBuffer);
472 return EFI_ABORTED;
473 }
474
475 if (CompressFunction != NULL) {
476
477 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
478 if (Status == EFI_BUFFER_TOO_SMALL) {
479 OutputBuffer = malloc (CompressedLength);
480 if (!OutputBuffer) {
481 free (FileBuffer);
482 return EFI_OUT_OF_RESOURCES;
483 }
484
485 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
486 }
487
488 free (FileBuffer);
489 FileBuffer = OutputBuffer;
490
491 if (EFI_ERROR (Status)) {
492 if (FileBuffer != NULL) {
493 free (FileBuffer);
494 }
495
496 return Status;
497 }
498 }
499
500 TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);
501 //
502 // Add the section header for the compressed data
503 //
504 CompressionSect.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType;
505 CompressionSect.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
506 CompressionSect.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
507 CompressionSect.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
508 CompressionSect.CompressionType = (UINT8) SectionSubType;
509 CompressionSect.UncompressedLength = InputLength;
510
511 fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);
512 fwrite (FileBuffer, CompressedLength, 1, OutFile);
513 free (FileBuffer);
514 return EFI_SUCCESS;
515 }
516
517 EFI_STATUS
518 GenSectionGuidDefinedSection (
519 char **InputFileName,
520 int InputFileNum,
521 UINTN SectionType,
522 UINTN SectionSubType,
523 FILE *OutFile
524 )
525 /*++
526
527 Routine Description:
528
529 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
530 Input file must be already sectioned. The function won't validate
531 the input files' contents. Caller should hand in files already
532 with section header.
533
534 Arguments:
535
536 InputFileName - Name of the input file.
537
538 InputFileNum - Number of input files. Should be at least 1.
539
540 SectionType - Section type to generate. Should be
541 EFI_SECTION_GUID_DEFINED
542
543 SectionSubType - Specify the authentication algorithm requested.
544
545 OutFile - Output file handle
546
547 Returns:
548
549 EFI_SUCCESS on successful return
550 EFI_INVALID_PARAMETER if InputFileNum is less than 1
551 EFI_ABORTED if unable to open input file.
552 EFI_OUT_OF_RESOURCES No resource to complete the operation.
553
554 --*/
555 {
556 INTN TotalLength;
557 INTN InputLength;
558 UINT8 *FileBuffer;
559 UINT32 Crc32Checksum;
560 EFI_STATUS Status;
561 CRC32_SECTION_HEADER Crc32GuidSect;
562
563 if (SectionType != EFI_SECTION_GUID_DEFINED) {
564 Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL);
565 return EFI_INVALID_PARAMETER;
566 }
567
568 InputLength = 0;
569 FileBuffer = NULL;
570 FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
571 if (FileBuffer == NULL) {
572 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
573 return EFI_OUT_OF_RESOURCES;
574 }
575 //
576 // read all input file contents into a buffer
577 //
578 Status = GetSectionContents (
579 InputFileName,
580 InputFileNum,
581 FileBuffer,
582 &InputLength
583 );
584 if (EFI_ERROR (Status)) {
585 free (FileBuffer);
586 return Status;
587 }
588 //
589 // Now data is in FileBuffer, compress the data
590 //
591 switch (SectionSubType) {
592 case EFI_SECTION_CRC32_GUID_DEFINED:
593 Crc32Checksum = 0;
594 CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);
595 if (EFI_ERROR (Status)) {
596 free (FileBuffer);
597 return Status;
598 }
599
600 TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE;
601 Crc32GuidSect.GuidSectionHeader.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType;
602 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
603 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
604 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
605 memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
606 Crc32GuidSect.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
607 Crc32GuidSect.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE;
608 Crc32GuidSect.CRC32Checksum = Crc32Checksum;
609
610 break;
611
612 default:
613 Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type");
614 free (FileBuffer);
615 return EFI_ABORTED;
616 }
617
618 fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);
619 fwrite (FileBuffer, InputLength, 1, OutFile);
620
621 free (FileBuffer);
622
623 return EFI_SUCCESS;
624 }
625
626 int
627 main (
628 int argc,
629 char *argv[]
630 )
631 /*++
632
633 Routine Description:
634
635 Main
636
637 Arguments:
638
639 command line parameters
640
641 Returns:
642
643 EFI_SUCCESS Section header successfully generated and section concatenated.
644 EFI_ABORTED Could not generate the section
645 EFI_OUT_OF_RESOURCES No resource to complete the operation.
646
647 --*/
648 {
649 INTN Index;
650 INTN VersionNumber;
651 UINTN SectionType;
652 UINTN SectionSubType;
653 BOOLEAN InputFileRequired;
654 BOOLEAN SubTypeRequired;
655 FILE *InFile;
656 FILE *OutFile;
657 INTN InputFileNum;
658
659 char **InputFileName;
660 char *OutputFileName;
661 char AuxString[500] = { 0 };
662
663 char *ParamSectionType;
664 char *ParamSectionSubType;
665 char *ParamLength;
666 char *ParamVersion;
667 char *ParamDigitalSignature;
668
669 EFI_STATUS Status;
670 EFI_COMMON_SECTION_HEADER CommonSect;
671
672 InputFileName = NULL;
673 OutputFileName = PARAMETER_NOT_SPECIFIED;
674 ParamSectionType = PARAMETER_NOT_SPECIFIED;
675 ParamSectionSubType = PARAMETER_NOT_SPECIFIED;
676 ParamLength = PARAMETER_NOT_SPECIFIED;
677 ParamVersion = PARAMETER_NOT_SPECIFIED;
678 ParamDigitalSignature = PARAMETER_NOT_SPECIFIED;
679 Status = EFI_SUCCESS;
680
681 VersionNumber = 0;
682 SectionType = 0;
683 SectionSubType = 0;
684 InputFileRequired = TRUE;
685 SubTypeRequired = FALSE;
686 InFile = NULL;
687 OutFile = NULL;
688 InputFileNum = 0;
689 Status = EFI_SUCCESS;
690
691 SetUtilityName (UTILITY_NAME);
692
693 if (argc == 1) {
694 Usage ();
695 return STATUS_ERROR;
696 }
697
698 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
699 (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
700 Usage();
701 return STATUS_ERROR;
702 }
703
704 if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
705 Version();
706 return STATUS_ERROR;
707 }
708
709 //
710 // Parse command line
711 //
712 Index = 1;
713 while (Index < argc) {
714 if (strcmpi (argv[Index], "-i") == 0) {
715 //
716 // Input File found
717 //
718 Index++;
719 InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *));
720 if (InputFileName == NULL) {
721 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
722 return EFI_OUT_OF_RESOURCES;
723 }
724
725 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
726 InputFileName[InputFileNum] = argv[Index];
727 InputFileNum++;
728 Index++;
729 //
730 // Parse subsequent parameters until another switch is encountered
731 //
732 while ((Index < argc) && (argv[Index][0] != '-')) {
733 if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) {
734 //
735 // InputFileName buffer too small, need to realloc
736 //
737 InputFileName = (char **) realloc (
738 InputFileName,
739 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *)
740 );
741 if (InputFileName == NULL) {
742 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
743 return EFI_OUT_OF_RESOURCES;
744 }
745
746 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
747 }
748
749 InputFileName[InputFileNum] = argv[Index];
750 InputFileNum++;
751 Index++;
752 }
753
754 }
755
756 if (strcmpi (argv[Index], "-o") == 0) {
757 //
758 // Output file found
759 //
760 Index++;
761 OutputFileName = argv[Index];
762 } else if (strcmpi (argv[Index], "-s") == 0) {
763 //
764 // Section Type found
765 //
766 Index++;
767 ParamSectionType = argv[Index];
768 } else if (strcmpi (argv[Index], "-t") == 0) {
769 //
770 // Compression or Authentication type
771 //
772 Index++;
773 ParamSectionSubType = argv[Index];
774 } else if (strcmpi (argv[Index], "-l") == 0) {
775 //
776 // Length
777 //
778 Index++;
779 ParamLength = argv[Index];
780 } else if (strcmpi (argv[Index], "-v") == 0) {
781 //
782 // VersionNumber
783 //
784 Index++;
785 ParamVersion = argv[Index];
786 } else if (strcmpi (argv[Index], "-a") == 0) {
787 //
788 // Aux string
789 //
790 Index++;
791 //
792 // Note, the MSVC C-Start parses out and consolidates quoted strings from the command
793 // line. Quote characters are stripped. If this tool is ported to other environments
794 // this will need to be taken into account
795 //
796 strncpy (AuxString, argv[Index], 499);
797 } else if (strcmpi (argv[Index], "-d") == 0) {
798 //
799 // Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1)
800 //
801 Index++;
802 ParamDigitalSignature = argv[Index];
803 } else if (strcmpi (argv[Index], "-?") == 0) {
804 Usage ();
805 return STATUS_ERROR;
806 } else {
807 Error (NULL, 0, 0, argv[Index], "unknown option");
808 return GetUtilityStatus ();
809 }
810
811 Index++;
812 }
813 //
814 // At this point, all command line parameters are verified as not being totally
815 // bogus. Next verify the command line parameters are complete and make
816 // sense...
817 //
818 if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
819 SectionType = EFI_SECTION_COMPRESSION;
820 SubTypeRequired = TRUE;
821 if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
822 SectionSubType = EFI_NOT_COMPRESSED;
823 } else if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
824 SectionSubType = EFI_STANDARD_COMPRESSION;
825 } else {
826 Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type");
827 Usage ();
828 return GetUtilityStatus ();
829 }
830 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
831 SectionType = EFI_SECTION_GUID_DEFINED;
832 SubTypeRequired = TRUE;
833 if (stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) {
834 SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED;
835 } else {
836 Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType);
837 Usage ();
838 return GetUtilityStatus ();
839 }
840 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) {
841 SectionType = EFI_SECTION_PE32;
842 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) {
843 SectionType = EFI_SECTION_PIC;
844 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) {
845 SectionType = EFI_SECTION_TE;
846 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
847 SectionType = EFI_SECTION_DXE_DEPEX;
848 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) {
849 SectionType = EFI_SECTION_VERSION;
850 InputFileRequired = FALSE;
851 Index = sscanf (ParamVersion, "%d", &VersionNumber);
852 if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) {
853 Error (NULL, 0, 0, ParamVersion, "illegal version number");
854 Usage ();
855 return GetUtilityStatus ();
856 }
857
858 if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
859 AuxString[0] = 0;
860 }
861 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
862 SectionType = EFI_SECTION_USER_INTERFACE;
863 InputFileRequired = FALSE;
864 if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
865 Error (NULL, 0, 0, "user interface string not specified", NULL);
866 Usage ();
867 return GetUtilityStatus ();
868 }
869 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
870 SectionType = EFI_SECTION_COMPATIBILITY16;
871 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
872 SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
873 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
874 SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
875 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) {
876 SectionType = EFI_SECTION_RAW;
877 } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
878 SectionType = EFI_SECTION_PEI_DEPEX;
879 } else {
880 Error (NULL, 0, 0, ParamSectionType, "unknown section type");
881 Usage ();
882 return GetUtilityStatus ();
883 }
884 //
885 // Open output file
886 //
887 OutFile = fopen (OutputFileName, "wb");
888 if (OutFile == NULL) {
889 Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
890 if (InFile != NULL) {
891 fclose (InFile);
892 }
893
894 return GetUtilityStatus ();
895 }
896 //
897 // At this point, we've fully validated the command line, and opened appropriate
898 // files, so let's go and do what we've been asked to do...
899 //
900 //
901 // Within this switch, build and write out the section header including any
902 // section type specific pieces. If there's an input file, it's tacked on later
903 //
904 switch (SectionType) {
905 case EFI_SECTION_COMPRESSION:
906 Status = GenSectionCompressionSection (
907 InputFileName,
908 InputFileNum,
909 SectionType,
910 SectionSubType,
911 OutFile
912 );
913 break;
914
915 case EFI_SECTION_GUID_DEFINED:
916 Status = GenSectionGuidDefinedSection (
917 InputFileName,
918 InputFileNum,
919 SectionType,
920 SectionSubType,
921 OutFile
922 );
923 break;
924
925 case EFI_SECTION_VERSION:
926 CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
927
928 Index = sizeof (CommonSect);
929 //
930 // 2 characters for the build number
931 //
932 Index += 2;
933 //
934 // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
935 //
936 Index += (strlen (AuxString) * 2) + 2;
937 memcpy (&CommonSect.Size, &Index, 3);
938 fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
939 fwrite (&VersionNumber, 2, 1, OutFile);
940 Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
941 break;
942
943 case EFI_SECTION_USER_INTERFACE:
944 CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
945 Index = sizeof (CommonSect);
946 //
947 // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
948 //
949 Index += (strlen (AuxString) * 2) + 2;
950 memcpy (&CommonSect.Size, &Index, 3);
951 fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
952 Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
953 break;
954
955 default:
956 //
957 // All other section types are caught by default (they're all the same)
958 //
959 Status = GenSectionCommonLeafSection (
960 InputFileName,
961 InputFileNum,
962 SectionType,
963 OutFile
964 );
965 break;
966 }
967
968 if (InputFileName != NULL) {
969 free (InputFileName);
970 }
971
972 fclose (OutFile);
973 //
974 // If we had errors, then delete the output file
975 //
976 if (GetUtilityStatus () == STATUS_ERROR) {
977 remove (OutputFileName);
978 }
979
980 return GetUtilityStatus ();
981 }