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