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