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