]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.c
1d1c307e87526091235f4f1ab9cb939c158b6ed0
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GenSection / GenSection.c
1 /*++
2
3 Copyright (c) 2004 - 2007, 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
39 #define PARAMETER_NOT_SPECIFIED "Parameter not specified"
40 #define MAXIMUM_INPUT_FILE_NUM 10
41 #define MAX_SECTION_SIZE 0x1000000
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 >= MAX_SECTION_SIZE) {
223 Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit(%dM).", TotalLength, MAX_SECTION_SIZE>>20);
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 - On input, this is size of the FileBuffer.
286 On output, this is the actual length of the data.
287
288 Returns:
289
290 EFI_SUCCESS on successful return
291 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
292 EFI_ABORTED if unable to open input file.
293 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
294 --*/
295 {
296 UINTN Size;
297 fpos_t FileSize;
298 INTN Index;
299 FILE *InFile;
300
301 if (InputFileNum < 1) {
302 Error (NULL, 0, 0, "must specify at least one input file", NULL);
303 return EFI_INVALID_PARAMETER;
304 }
305
306 if (BufferLength == NULL) {
307 Error (NULL, 0, 0, "BufferLength can't be NULL", NULL);
308 return EFI_INVALID_PARAMETER;
309 }
310
311 Size = 0;
312 //
313 // Go through our array of file names and copy their contents
314 // to the output buffer.
315 //
316 for (Index = 0; Index < InputFileNum; Index++) {
317 InFile = fopen (InputFileName[Index], "rb");
318 if (InFile == NULL) {
319 Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");
320 return EFI_ABORTED;
321 }
322
323 fseek (InFile, 0, SEEK_END);
324 fgetpos (InFile, &FileSize);
325 fseek (InFile, 0, SEEK_SET);
326 //
327 // Now read the contents of the file into the buffer
328 // Buffer must be enough to contain the file content.
329 //
330 if (FileSize > 0 && FileBuffer != NULL && (Size + (UINTN) FileSize) <= *BufferLength) {
331 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
332 Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");
333 fclose (InFile);
334 return EFI_ABORTED;
335 }
336 }
337
338 fclose (InFile);
339 Size += (UINTN) FileSize;
340 //
341 // make sure section ends on a DWORD boundary
342 //
343 while ((Size & 0x03) != 0) {
344 if (FileBuffer != NULL && Size < *BufferLength) {
345 FileBuffer[Size] = 0;
346 }
347 Size++;
348 }
349 }
350
351 if (Size > *BufferLength) {
352 *BufferLength = Size;
353 return EFI_BUFFER_TOO_SMALL;
354 } else {
355 *BufferLength = Size;
356 return EFI_SUCCESS;
357 }
358 }
359
360 EFI_STATUS
361 GenSectionCompressionSection (
362 char **InputFileName,
363 int InputFileNum,
364 UINTN SectionType,
365 UINTN SectionSubType,
366 FILE *OutFile
367 )
368 /*++
369
370 Routine Description:
371
372 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
373 Input file must be already sectioned. The function won't validate
374 the input files' contents. Caller should hand in files already
375 with section header.
376
377 Arguments:
378
379 InputFileName - Name of the input file.
380
381 InputFileNum - Number of input files. Should be at least 1.
382
383 SectionType - Section type to generate. Should be
384 EFI_SECTION_COMPRESSION
385
386 SectionSubType - Specify the compression algorithm requested.
387
388 OutFile - Output file handle
389
390 Returns:
391
392 EFI_SUCCESS on successful return
393 EFI_INVALID_PARAMETER if InputFileNum is less than 1
394 EFI_ABORTED if unable to open input file.
395 EFI_OUT_OF_RESOURCES No resource to complete the operation.
396 --*/
397 {
398 UINTN TotalLength;
399 UINTN InputLength;
400 UINTN CompressedLength;
401 UINT8 *FileBuffer;
402 UINT8 *OutputBuffer;
403 EFI_STATUS Status;
404 EFI_COMPRESSION_SECTION CompressionSect;
405 COMPRESS_FUNCTION CompressFunction;
406
407 if (SectionType != EFI_SECTION_COMPRESSION) {
408 Error (NULL, 0, 0, "parameter must be EFI_SECTION_COMPRESSION", NULL);
409 return EFI_INVALID_PARAMETER;
410 }
411
412 InputLength = 0;
413 FileBuffer = NULL;
414 OutputBuffer = NULL;
415 CompressedLength = 0;
416 //
417 // read all input file contents into a buffer
418 // first get the size of all file contents
419 //
420 Status = GetSectionContents (
421 InputFileName,
422 InputFileNum,
423 FileBuffer,
424 &InputLength
425 );
426
427 if (Status == EFI_BUFFER_TOO_SMALL) {
428 FileBuffer = (UINT8 *) malloc (InputLength);
429 if (FileBuffer == NULL) {
430 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
431 return EFI_OUT_OF_RESOURCES;
432 }
433 //
434 // read all input file contents into a buffer
435 //
436 Status = GetSectionContents (
437 InputFileName,
438 InputFileNum,
439 FileBuffer,
440 &InputLength
441 );
442 }
443
444 if (EFI_ERROR (Status)) {
445 if (FileBuffer != NULL) {
446 free (FileBuffer);
447 }
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) TianoCompress;
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 if (TotalLength >= MAX_SECTION_SIZE) {
502 Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
503 if (FileBuffer != NULL) {
504 free (FileBuffer);
505 }
506 if (OutputBuffer != NULL) {
507 free (OutputBuffer);
508 }
509 return STATUS_ERROR;
510 }
511 //
512 // Add the section header for the compressed data
513 //
514 CompressionSect.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType;
515 CompressionSect.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
516 CompressionSect.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
517 CompressionSect.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
518 CompressionSect.CompressionType = (UINT8) SectionSubType;
519 CompressionSect.UncompressedLength = InputLength;
520
521 fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);
522 fwrite (FileBuffer, CompressedLength, 1, OutFile);
523 free (FileBuffer);
524 return EFI_SUCCESS;
525 }
526
527 EFI_STATUS
528 GenSectionGuidDefinedSection (
529 char **InputFileName,
530 int InputFileNum,
531 UINTN SectionType,
532 UINTN SectionSubType,
533 FILE *OutFile
534 )
535 /*++
536
537 Routine Description:
538
539 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
540 Input file must be already sectioned. The function won't validate
541 the input files' contents. Caller should hand in files already
542 with section header.
543
544 Arguments:
545
546 InputFileName - Name of the input file.
547
548 InputFileNum - Number of input files. Should be at least 1.
549
550 SectionType - Section type to generate. Should be
551 EFI_SECTION_GUID_DEFINED
552
553 SectionSubType - Specify the authentication algorithm requested.
554
555 OutFile - Output file handle
556
557 Returns:
558
559 EFI_SUCCESS on successful return
560 EFI_INVALID_PARAMETER if InputFileNum is less than 1
561 EFI_ABORTED if unable to open input file.
562 EFI_OUT_OF_RESOURCES No resource to complete the operation.
563
564 --*/
565 {
566 INTN TotalLength;
567 INTN InputLength;
568 UINT8 *FileBuffer;
569 UINT32 Crc32Checksum;
570 EFI_STATUS Status;
571 CRC32_SECTION_HEADER Crc32GuidSect;
572
573 if (SectionType != EFI_SECTION_GUID_DEFINED) {
574 Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL);
575 return EFI_INVALID_PARAMETER;
576 }
577
578 InputLength = 0;
579 FileBuffer = NULL;
580 //
581 // read all input file contents into a buffer
582 // first get the size of all file contents
583 //
584 Status = GetSectionContents (
585 InputFileName,
586 InputFileNum,
587 FileBuffer,
588 &InputLength
589 );
590
591 if (Status == EFI_BUFFER_TOO_SMALL) {
592 FileBuffer = (UINT8 *) malloc (InputLength);
593 if (FileBuffer == NULL) {
594 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
595 return EFI_OUT_OF_RESOURCES;
596 }
597 //
598 // read all input file contents into a buffer
599 //
600 Status = GetSectionContents (
601 InputFileName,
602 InputFileNum,
603 FileBuffer,
604 &InputLength
605 );
606 }
607
608 if (EFI_ERROR (Status)) {
609 if (FileBuffer != NULL) {
610 free (FileBuffer);
611 }
612 return Status;
613 }
614 //
615 // Now data is in FileBuffer
616 //
617 switch (SectionSubType) {
618 case EFI_SECTION_CRC32_GUID_DEFINED:
619 Crc32Checksum = 0;
620 CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);
621 if (EFI_ERROR (Status)) {
622 free (FileBuffer);
623 return Status;
624 }
625
626 TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE;
627 if (TotalLength >= MAX_SECTION_SIZE) {
628 Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);
629 free (FileBuffer);
630 return STATUS_ERROR;
631 }
632
633 Crc32GuidSect.GuidSectionHeader.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType;
634 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
635 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
636 Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
637 memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
638 Crc32GuidSect.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
639 Crc32GuidSect.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE;
640 Crc32GuidSect.CRC32Checksum = Crc32Checksum;
641
642 break;
643
644 default:
645 Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type");
646 free (FileBuffer);
647 return EFI_ABORTED;
648 }
649
650 fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);
651 fwrite (FileBuffer, InputLength, 1, OutFile);
652
653 free (FileBuffer);
654
655 return EFI_SUCCESS;
656 }
657
658 int
659 main (
660 int argc,
661 char *argv[]
662 )
663 /*++
664
665 Routine Description:
666
667 Main
668
669 Arguments:
670
671 command line parameters
672
673 Returns:
674
675 EFI_SUCCESS Section header successfully generated and section concatenated.
676 EFI_ABORTED Could not generate the section
677 EFI_OUT_OF_RESOURCES No resource to complete the operation.
678
679 --*/
680 {
681 INTN Index;
682 INTN VersionNumber;
683 UINTN SectionType;
684 UINTN SectionSubType;
685 BOOLEAN InputFileRequired;
686 BOOLEAN SubTypeRequired;
687 FILE *InFile;
688 FILE *OutFile;
689 INTN InputFileNum;
690
691 char **InputFileName;
692 char *OutputFileName;
693 char AuxString[500] = { 0 };
694
695 char *ParamSectionType;
696 char *ParamSectionSubType;
697 char *ParamLength;
698 char *ParamVersion;
699 char *ParamDigitalSignature;
700
701 EFI_STATUS Status;
702 EFI_COMMON_SECTION_HEADER CommonSect;
703
704 InputFileName = NULL;
705 OutputFileName = PARAMETER_NOT_SPECIFIED;
706 ParamSectionType = PARAMETER_NOT_SPECIFIED;
707 ParamSectionSubType = PARAMETER_NOT_SPECIFIED;
708 ParamLength = PARAMETER_NOT_SPECIFIED;
709 ParamVersion = PARAMETER_NOT_SPECIFIED;
710 ParamDigitalSignature = PARAMETER_NOT_SPECIFIED;
711 Status = EFI_SUCCESS;
712
713 VersionNumber = 0;
714 SectionType = 0;
715 SectionSubType = 0;
716 InputFileRequired = TRUE;
717 SubTypeRequired = FALSE;
718 InFile = NULL;
719 OutFile = NULL;
720 InputFileNum = 0;
721 Status = EFI_SUCCESS;
722
723 SetUtilityName (UTILITY_NAME);
724 if (argc == 1) {
725 PrintUsageMessage ();
726 return STATUS_ERROR;
727 }
728 //
729 // Parse command line
730 //
731 Index = 1;
732 while (Index < argc) {
733 if (_strcmpi (argv[Index], "-i") == 0) {
734 //
735 // Input File found
736 //
737 Index++;
738 InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *));
739 if (InputFileName == NULL) {
740 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
741 return EFI_OUT_OF_RESOURCES;
742 }
743
744 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
745 InputFileName[InputFileNum] = argv[Index];
746 InputFileNum++;
747 Index++;
748 //
749 // Parse subsequent parameters until another switch is encountered
750 //
751 while ((Index < argc) && (argv[Index][0] != '-')) {
752 if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) {
753 //
754 // InputFileName buffer too small, need to realloc
755 //
756 InputFileName = (char **) realloc (
757 InputFileName,
758 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *)
759 );
760 if (InputFileName == NULL) {
761 Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
762 return EFI_OUT_OF_RESOURCES;
763 }
764
765 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
766 }
767
768 InputFileName[InputFileNum] = argv[Index];
769 InputFileNum++;
770 Index++;
771 }
772
773 }
774
775 if (_strcmpi (argv[Index], "-o") == 0) {
776 //
777 // Output file found
778 //
779 Index++;
780 OutputFileName = argv[Index];
781 } else if (_strcmpi (argv[Index], "-s") == 0) {
782 //
783 // Section Type found
784 //
785 Index++;
786 ParamSectionType = argv[Index];
787 } else if (_strcmpi (argv[Index], "-t") == 0) {
788 //
789 // Compression or Authentication type
790 //
791 Index++;
792 ParamSectionSubType = argv[Index];
793 } else if (_strcmpi (argv[Index], "-l") == 0) {
794 //
795 // Length
796 //
797 Index++;
798 ParamLength = argv[Index];
799 } else if (_strcmpi (argv[Index], "-v") == 0) {
800 //
801 // VersionNumber
802 //
803 Index++;
804 ParamVersion = argv[Index];
805 } else if (_strcmpi (argv[Index], "-a") == 0) {
806 //
807 // Aux string
808 //
809 Index++;
810 //
811 // Note, the MSVC C-Start parses out and consolidates quoted strings from the command
812 // line. Quote characters are stripped. If this tool is ported to other environments
813 // this will need to be taken into account
814 //
815 strncpy (AuxString, argv[Index], 499);
816 } else if (_strcmpi (argv[Index], "-d") == 0) {
817 //
818 // Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1)
819 //
820 Index++;
821 ParamDigitalSignature = argv[Index];
822 } else if (_strcmpi (argv[Index], "-?") == 0) {
823 PrintUsageMessage ();
824 return STATUS_ERROR;
825 } else {
826 Error (NULL, 0, 0, argv[Index], "unknown option");
827 return GetUtilityStatus ();
828 }
829
830 Index++;
831 }
832 //
833 // At this point, all command line parameters are verified as not being totally
834 // bogus. Next verify the command line parameters are complete and make
835 // sense...
836 //
837 if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
838 SectionType = EFI_SECTION_COMPRESSION;
839 SubTypeRequired = TRUE;
840 if (_stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
841 SectionSubType = EFI_NOT_COMPRESSED;
842 } else if (_stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
843 SectionSubType = EFI_STANDARD_COMPRESSION;
844 } else {
845 Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type");
846 PrintUsageMessage ();
847 return GetUtilityStatus ();
848 }
849 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
850 SectionType = EFI_SECTION_GUID_DEFINED;
851 SubTypeRequired = TRUE;
852 if (_stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) {
853 SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED;
854 } else {
855 Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType);
856 PrintUsageMessage ();
857 return GetUtilityStatus ();
858 }
859 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) {
860 SectionType = EFI_SECTION_PE32;
861 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) {
862 SectionType = EFI_SECTION_PIC;
863 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) {
864 SectionType = EFI_SECTION_TE;
865 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
866 SectionType = EFI_SECTION_DXE_DEPEX;
867 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) {
868 SectionType = EFI_SECTION_VERSION;
869 InputFileRequired = FALSE;
870 Index = sscanf (ParamVersion, "%d", &VersionNumber);
871 if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) {
872 Error (NULL, 0, 0, ParamVersion, "illegal version number");
873 PrintUsageMessage ();
874 return GetUtilityStatus ();
875 }
876
877 if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
878 AuxString[0] = 0;
879 }
880 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
881 SectionType = EFI_SECTION_USER_INTERFACE;
882 InputFileRequired = FALSE;
883 if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
884 Error (NULL, 0, 0, "user interface string not specified", NULL);
885 PrintUsageMessage ();
886 return GetUtilityStatus ();
887 }
888 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
889 SectionType = EFI_SECTION_COMPATIBILITY16;
890 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
891 SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
892 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
893 SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
894 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) {
895 SectionType = EFI_SECTION_RAW;
896 } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
897 SectionType = EFI_SECTION_PEI_DEPEX;
898 } else {
899 Error (NULL, 0, 0, ParamSectionType, "unknown section type");
900 PrintUsageMessage ();
901 return GetUtilityStatus ();
902 }
903 //
904 // Open output file
905 //
906 OutFile = fopen (OutputFileName, "wb");
907 if (OutFile == NULL) {
908 Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
909 if (InFile != NULL) {
910 fclose (InFile);
911 }
912
913 return GetUtilityStatus ();
914 }
915 //
916 // At this point, we've fully validated the command line, and opened appropriate
917 // files, so let's go and do what we've been asked to do...
918 //
919 //
920 // Within this switch, build and write out the section header including any
921 // section type specific pieces. If there's an input file, it's tacked on later
922 //
923 switch (SectionType) {
924 case EFI_SECTION_COMPRESSION:
925 Status = GenSectionCompressionSection (
926 InputFileName,
927 InputFileNum,
928 SectionType,
929 SectionSubType,
930 OutFile
931 );
932 break;
933
934 case EFI_SECTION_GUID_DEFINED:
935 Status = GenSectionGuidDefinedSection (
936 InputFileName,
937 InputFileNum,
938 SectionType,
939 SectionSubType,
940 OutFile
941 );
942 break;
943
944 case EFI_SECTION_VERSION:
945 CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
946
947 Index = sizeof (CommonSect);
948 //
949 // 2 characters for the build number
950 //
951 Index += 2;
952 //
953 // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
954 //
955 Index += (strlen (AuxString) * 2) + 2;
956 memcpy (&CommonSect.Size, &Index, 3);
957 fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
958 fwrite (&VersionNumber, 2, 1, OutFile);
959 Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
960 break;
961
962 case EFI_SECTION_USER_INTERFACE:
963 CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
964 Index = sizeof (CommonSect);
965 //
966 // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
967 //
968 Index += (strlen (AuxString) * 2) + 2;
969 memcpy (&CommonSect.Size, &Index, 3);
970 fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
971 Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
972 break;
973
974 default:
975 //
976 // All other section types are caught by default (they're all the same)
977 //
978 Status = GenSectionCommonLeafSection (
979 InputFileName,
980 InputFileNum,
981 SectionType,
982 OutFile
983 );
984 break;
985 }
986
987 if (InputFileName != NULL) {
988 free (InputFileName);
989 }
990
991 fclose (OutFile);
992 //
993 // If we had errors, then delete the output file
994 //
995 if (GetUtilityStatus () == STATUS_ERROR) {
996 remove (OutputFileName);
997 }
998
999 return GetUtilityStatus ();
1000 }