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