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