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