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