]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/C/GenSec/GenSec.c
BaseTools: Update Trim to generate VfrBinOffset Binary
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
... / ...
CommitLineData
1/** @file\r
2Creates output file that is a properly formed section per the PI spec.\r
3\r
4Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13**/\r
14\r
15#include <stdio.h>\r
16#include <stdlib.h>\r
17#include <string.h>\r
18#include <ctype.h>\r
19\r
20#include <Common/UefiBaseTypes.h>\r
21#include <Common/PiFirmwareFile.h>\r
22#include <Protocol/GuidedSectionExtraction.h>\r
23#include <IndustryStandard/PeImage.h>\r
24\r
25#include "CommonLib.h"\r
26#include "Compress.h"\r
27#include "Crc32.h"\r
28#include "EfiUtilityMsgs.h"\r
29#include "ParseInf.h"\r
30\r
31//\r
32// GenSec Tool Information\r
33//\r
34#define UTILITY_NAME "GenSec"\r
35#define UTILITY_MAJOR_VERSION 0\r
36#define UTILITY_MINOR_VERSION 1\r
37\r
38STATIC CHAR8 *mSectionTypeName[] = {\r
39 NULL, // 0x00 - reserved\r
40 "EFI_SECTION_COMPRESSION", // 0x01\r
41 "EFI_SECTION_GUID_DEFINED", // 0x02\r
42 NULL, // 0x03 - reserved\r
43 NULL, // 0x04 - reserved\r
44 NULL, // 0x05 - reserved\r
45 NULL, // 0x06 - reserved\r
46 NULL, // 0x07 - reserved\r
47 NULL, // 0x08 - reserved\r
48 NULL, // 0x09 - reserved\r
49 NULL, // 0x0A - reserved\r
50 NULL, // 0x0B - reserved\r
51 NULL, // 0x0C - reserved\r
52 NULL, // 0x0D - reserved\r
53 NULL, // 0x0E - reserved\r
54 NULL, // 0x0F - reserved\r
55 "EFI_SECTION_PE32", // 0x10\r
56 "EFI_SECTION_PIC", // 0x11\r
57 "EFI_SECTION_TE", // 0x12\r
58 "EFI_SECTION_DXE_DEPEX", // 0x13\r
59 "EFI_SECTION_VERSION", // 0x14\r
60 "EFI_SECTION_USER_INTERFACE", // 0x15\r
61 "EFI_SECTION_COMPATIBILITY16", // 0x16\r
62 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17\r
63 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18\r
64 "EFI_SECTION_RAW", // 0x19\r
65 NULL, // 0x1A\r
66 "EFI_SECTION_PEI_DEPEX", // 0x1B\r
67 "EFI_SECTION_SMM_DEPEX" // 0x1C\r
68};\r
69\r
70STATIC CHAR8 *mCompressionTypeName[] = { "PI_NONE", "PI_STD" };\r
71\r
72#define EFI_GUIDED_SECTION_NONE 0x80\r
73STATIC CHAR8 *mGUIDedSectionAttribue[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};\r
74\r
75STATIC CHAR8 *mAlignName[] = {\r
76 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",\r
77 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",\r
78 "512K", "1M", "2M", "4M", "8M", "16M"\r
79};\r
80\r
81//\r
82// Crc32 GUID section related definitions.\r
83//\r
84typedef struct {\r
85 EFI_GUID_DEFINED_SECTION GuidSectionHeader;\r
86 UINT32 CRC32Checksum;\r
87} CRC32_SECTION_HEADER;\r
88\r
89typedef struct {\r
90 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;\r
91 UINT32 CRC32Checksum;\r
92} CRC32_SECTION_HEADER2;\r
93\r
94STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
95STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
96\r
97STATIC\r
98VOID \r
99Version (\r
100 VOID\r
101 )\r
102/*++\r
103\r
104Routine Description:\r
105\r
106 Print out version information for this utility.\r
107\r
108Arguments:\r
109\r
110 None\r
111 \r
112Returns:\r
113\r
114 None\r
115 \r
116--*/ \r
117{\r
118 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
119}\r
120\r
121STATIC\r
122VOID\r
123Usage (\r
124 VOID\r
125 )\r
126/*++\r
127\r
128Routine Description:\r
129\r
130 Print Help message.\r
131\r
132Arguments:\r
133\r
134 VOID\r
135\r
136Returns:\r
137\r
138 None\r
139\r
140--*/\r
141{\r
142 //\r
143 // Summary usage\r
144 //\r
145 fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);\r
146 \r
147 //\r
148 // Copyright declaration\r
149 // \r
150 fprintf (stdout, "Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.\n\n");\r
151\r
152 //\r
153 // Details Option\r
154 //\r
155 fprintf (stdout, "Options:\n");\r
156 fprintf (stdout, " -o FileName, --outputfile FileName\n\\r
157 File is the SectionFile to be created.\n");\r
158 fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\\r
159 SectionType defined in PI spec is one type of\n\\r
160 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\\r
161 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\\r
162 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\\r
163 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\\r
164 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\\r
165 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\\r
166 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\\r
167 if -s option is not given, \n\\r
168 EFI_SECTION_ALL is default section type.\n");\r
169 fprintf (stdout, " -c [Type], --compress [Type]\n\\r
170 Compress method type can be PI_NONE or PI_STD.\n\\r
171 if -c option is not given, PI_STD is default type.\n"); \r
172 fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\\r
173 GuidValue is one specific vendor guid value.\n\\r
174 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");\r
175 fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\\r
176 GuidHeaderLength is the size of header of guided data\n");\r
177 fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\\r
178 GuidAttr is guid section atttributes, which may be\n\\r
179 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\\r
180 if -r option is not given, default PROCESSING_REQUIRED\n");\r
181 fprintf (stdout, " -n String, --name String\n\\r
182 String is a NULL terminated string used in Ui section.\n");\r
183 fprintf (stdout, " -j Number, --buildnumber Number\n\\r
184 Number is an integer value between 0 and 65535\n\\r
185 used in Ver section.\n");\r
186 fprintf (stdout, " --sectionalign SectionAlign\n\\r
187 SectionAlign points to section alignment, which support\n\\r
188 the alignment scope 1~16M. It is specified in same\n\\r
189 order that the section file is input.\n");\r
190 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");\r
191 fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");\r
192 fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");\r
193 fprintf (stdout, " --version Show program's version number and exit.\n");\r
194 fprintf (stdout, " -h, --help Show this help message and exit.\n");\r
195}\r
196\r
197VOID\r
198Ascii2UnicodeString (\r
199 CHAR8 *String,\r
200 CHAR16 *UniString\r
201 )\r
202/*++\r
203\r
204Routine Description:\r
205\r
206 Write ascii string as unicode string format to FILE \r
207\r
208Arguments:\r
209\r
210 String - Pointer to string that is written to FILE.\r
211 UniString - Pointer to unicode string\r
212\r
213Returns:\r
214\r
215 NULL\r
216\r
217--*/\r
218{\r
219 while (*String != '\0') {\r
220 *(UniString++) = (CHAR16) *(String++);\r
221 }\r
222 //\r
223 // End the UniString with a NULL.\r
224 //\r
225 *UniString = '\0';\r
226} \r
227\r
228STATUS\r
229GenSectionCommonLeafSection (\r
230 CHAR8 **InputFileName,\r
231 UINT32 InputFileNum,\r
232 UINT8 SectionType,\r
233 UINT8 **OutFileBuffer\r
234 )\r
235/*++\r
236 \r
237Routine Description:\r
238 \r
239 Generate a leaf section of type other than EFI_SECTION_VERSION\r
240 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.\r
241 The function won't validate the input file's contents. For\r
242 common leaf sections, the input file may be a binary file.\r
243 The utility will add section header to the file.\r
244 \r
245Arguments:\r
246 \r
247 InputFileName - Name of the input file.\r
248 \r
249 InputFileNum - Number of input files. Should be 1 for leaf section.\r
250\r
251 SectionType - A valid section type string\r
252\r
253 OutFileBuffer - Buffer pointer to Output file contents\r
254\r
255Returns:\r
256 \r
257 STATUS_ERROR - can't continue\r
258 STATUS_SUCCESS - successful return\r
259\r
260--*/\r
261{\r
262 UINT32 InputFileLength;\r
263 FILE *InFile;\r
264 UINT8 *Buffer;\r
265 UINT32 TotalLength;\r
266 UINT32 HeaderLength;\r
267 EFI_COMMON_SECTION_HEADER *CommonSect;\r
268 STATUS Status;\r
269\r
270 if (InputFileNum > 1) {\r
271 Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");\r
272 return STATUS_ERROR;\r
273 } else if (InputFileNum < 1) {\r
274 Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");\r
275 return STATUS_ERROR;\r
276 }\r
277 //\r
278 // Open the input file\r
279 //\r
280 InFile = fopen (LongFilePath (InputFileName[0]), "rb");\r
281 if (InFile == NULL) {\r
282 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
283 return STATUS_ERROR;\r
284 }\r
285\r
286 Status = STATUS_ERROR;\r
287 Buffer = NULL;\r
288 //\r
289 // Seek to the end of the input file so we can determine its size\r
290 //\r
291 fseek (InFile, 0, SEEK_END);\r
292 InputFileLength = ftell (InFile);\r
293 fseek (InFile, 0, SEEK_SET);\r
294 DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength);\r
295 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;\r
296 //\r
297 // Size must fit in 3 bytes\r
298 //\r
299 //if (TotalLength >= MAX_SECTION_SIZE) {\r
300 // Error (NULL, 0, 2000, "Invalid parameter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);\r
301 // goto Done;\r
302 //}\r
303 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);\r
304 if (TotalLength >= MAX_SECTION_SIZE) {\r
305 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;\r
306 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);\r
307 }\r
308 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
309 //\r
310 // Fill in the fields in the local section header structure\r
311 //\r
312 Buffer = (UINT8 *) malloc ((size_t) TotalLength);\r
313 if (Buffer == NULL) {\r
314 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); \r
315 goto Done;\r
316 }\r
317 CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;\r
318 CommonSect->Type = SectionType;\r
319 if (TotalLength < MAX_SECTION_SIZE) {\r
320 CommonSect->Size[0] = (UINT8) (TotalLength & 0xff);\r
321 CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
322 CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
323 } else {\r
324 memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3);\r
325 ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength;\r
326 }\r
327 \r
328 //\r
329 // read data from the input file.\r
330 //\r
331 if (InputFileLength != 0) {\r
332 if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {\r
333 Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);\r
334 goto Done;\r
335 }\r
336 }\r
337\r
338 //\r
339 // Set OutFileBuffer \r
340 //\r
341 *OutFileBuffer = Buffer;\r
342 Status = STATUS_SUCCESS;\r
343\r
344Done:\r
345 fclose (InFile);\r
346\r
347 return Status;\r
348}\r
349\r
350STATIC\r
351EFI_STATUS\r
352StringtoAlignment (\r
353 IN CHAR8 *AlignBuffer,\r
354 OUT UINT32 *AlignNumber\r
355 )\r
356/*++\r
357\r
358Routine Description:\r
359\r
360 Converts Align String to align value (1~16M).\r
361\r
362Arguments:\r
363\r
364 AlignBuffer - Pointer to Align string.\r
365 AlignNumber - Pointer to Align value.\r
366\r
367Returns:\r
368\r
369 EFI_SUCCESS Successfully convert align string to align value.\r
370 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.\r
371\r
372--*/\r
373{\r
374 UINT32 Index = 0;\r
375 //\r
376 // Check AlignBuffer\r
377 //\r
378 if (AlignBuffer == NULL) {\r
379 return EFI_INVALID_PARAMETER;\r
380 }\r
381 for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {\r
382 if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {\r
383 *AlignNumber = 1 << Index;\r
384 return EFI_SUCCESS;\r
385 }\r
386 }\r
387 return EFI_INVALID_PARAMETER;\r
388}\r
389\r
390EFI_STATUS\r
391GetSectionContents (\r
392 CHAR8 **InputFileName,\r
393 UINT32 *InputFileAlign,\r
394 UINT32 InputFileNum,\r
395 UINT8 *FileBuffer,\r
396 UINT32 *BufferLength\r
397 )\r
398/*++\r
399 \r
400Routine Description:\r
401 \r
402 Get the contents of all section files specified in InputFileName\r
403 into FileBuffer.\r
404 \r
405Arguments:\r
406 \r
407 InputFileName - Name of the input file.\r
408\r
409 InputFileAlign - Alignment required by the input file data.\r
410\r
411 InputFileNum - Number of input files. Should be at least 1.\r
412\r
413 FileBuffer - Output buffer to contain data\r
414\r
415 BufferLength - On input, this is size of the FileBuffer. \r
416 On output, this is the actual length of the data.\r
417\r
418Returns:\r
419 \r
420 EFI_SUCCESS on successful return\r
421 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.\r
422 EFI_ABORTED if unable to open input file.\r
423 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.\r
424--*/\r
425{\r
426 UINT32 Size;\r
427 UINT32 Offset;\r
428 UINT32 FileSize;\r
429 UINT32 Index;\r
430 FILE *InFile;\r
431 EFI_COMMON_SECTION_HEADER *SectHeader;\r
432 EFI_COMMON_SECTION_HEADER2 TempSectHeader;\r
433 EFI_TE_IMAGE_HEADER TeHeader;\r
434 UINT32 TeOffset;\r
435 EFI_GUID_DEFINED_SECTION GuidSectHeader;\r
436 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2;\r
437 UINT32 HeaderSize;\r
438\r
439 if (InputFileNum < 1) {\r
440 Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file");\r
441 return EFI_INVALID_PARAMETER;\r
442 }\r
443\r
444 if (BufferLength == NULL) {\r
445 Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");\r
446 return EFI_INVALID_PARAMETER;\r
447 }\r
448\r
449 Size = 0;\r
450 Offset = 0;\r
451 TeOffset = 0;\r
452 //\r
453 // Go through our array of file names and copy their contents\r
454 // to the output buffer.\r
455 //\r
456 for (Index = 0; Index < InputFileNum; Index++) {\r
457 //\r
458 // make sure section ends on a DWORD boundary\r
459 //\r
460 while ((Size & 0x03) != 0) {\r
461 if (FileBuffer != NULL && Size < *BufferLength) {\r
462 FileBuffer[Size] = 0;\r
463 }\r
464 Size++;\r
465 }\r
466 \r
467 // \r
468 // Open file and read contents\r
469 //\r
470 InFile = fopen (LongFilePath (InputFileName[Index]), "rb");\r
471 if (InFile == NULL) {\r
472 Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);\r
473 return EFI_ABORTED;\r
474 }\r
475\r
476 fseek (InFile, 0, SEEK_END);\r
477 FileSize = ftell (InFile);\r
478 fseek (InFile, 0, SEEK_SET);\r
479 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize); \r
480 //\r
481 // Adjust section buffer when section alignment is required.\r
482 //\r
483 if (InputFileAlign != NULL) {\r
484 //\r
485 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.\r
486 //\r
487 TeOffset = 0;\r
488 //\r
489 // The section might be EFI_COMMON_SECTION_HEADER2\r
490 // But only Type needs to be checked\r
491 //\r
492 if (FileSize >= MAX_SECTION_SIZE) {\r
493 HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);\r
494 } else {\r
495 HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
496 }\r
497 fread (&TempSectHeader, 1, HeaderSize, InFile);\r
498 if (TempSectHeader.Type == EFI_SECTION_TE) {\r
499 fread (&TeHeader, 1, sizeof (TeHeader), InFile);\r
500 if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
501 TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);\r
502 }\r
503 } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {\r
504 fseek (InFile, 0, SEEK_SET);\r
505 if (FileSize >= MAX_SECTION_SIZE) {\r
506 fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile);\r
507 if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
508 HeaderSize = GuidSectHeader2.DataOffset;\r
509 }\r
510 } else {\r
511 fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);\r
512 if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
513 HeaderSize = GuidSectHeader.DataOffset;\r
514 }\r
515 }\r
516 } \r
517\r
518 fseek (InFile, 0, SEEK_SET);\r
519\r
520 //\r
521 // Revert TeOffset to the converse value relative to Alignment\r
522 // This is to assure the original PeImage Header at Alignment.\r
523 //\r
524 if (TeOffset != 0) {\r
525 TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);\r
526 TeOffset = TeOffset % InputFileAlign [Index];\r
527 }\r
528\r
529 //\r
530 // make sure section data meet its alignment requirement by adding one raw pad section.\r
531 //\r
532 if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {\r
533 Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);\r
534 Offset = Offset - Size - HeaderSize - TeOffset;\r
535 \r
536 if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {\r
537 //\r
538 // The maximal alignment is 64K, the raw section size must be less than 0xffffff\r
539 //\r
540 memset (FileBuffer + Size, 0, Offset);\r
541 SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);\r
542 SectHeader->Type = EFI_SECTION_RAW;\r
543 SectHeader->Size[0] = (UINT8) (Offset & 0xff);\r
544 SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);\r
545 SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);\r
546 }\r
547 DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset);\r
548\r
549 Size = Size + Offset;\r
550 }\r
551 }\r
552\r
553 //\r
554 // Now read the contents of the file into the buffer\r
555 // Buffer must be enough to contain the file content.\r
556 //\r
557 if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {\r
558 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {\r
559 Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);\r
560 fclose (InFile);\r
561 return EFI_ABORTED;\r
562 }\r
563 }\r
564\r
565 fclose (InFile);\r
566 Size += FileSize;\r
567 }\r
568 \r
569 //\r
570 // Set the real required buffer size.\r
571 //\r
572 if (Size > *BufferLength) {\r
573 *BufferLength = Size;\r
574 return EFI_BUFFER_TOO_SMALL;\r
575 } else {\r
576 *BufferLength = Size;\r
577 return EFI_SUCCESS;\r
578 }\r
579}\r
580\r
581EFI_STATUS\r
582GenSectionCompressionSection (\r
583 CHAR8 **InputFileName,\r
584 UINT32 *InputFileAlign,\r
585 UINT32 InputFileNum,\r
586 UINT8 SectCompSubType,\r
587 UINT8 **OutFileBuffer\r
588 )\r
589/*++\r
590 \r
591Routine Description:\r
592 \r
593 Generate an encapsulating section of type EFI_SECTION_COMPRESSION\r
594 Input file must be already sectioned. The function won't validate\r
595 the input files' contents. Caller should hand in files already \r
596 with section header.\r
597 \r
598Arguments:\r
599 \r
600 InputFileName - Name of the input file.\r
601\r
602 InputFileAlign - Alignment required by the input file data.\r
603\r
604 InputFileNum - Number of input files. Should be at least 1.\r
605\r
606 SectCompSubType - Specify the compression algorithm requested. \r
607 \r
608 OutFileBuffer - Buffer pointer to Output file contents\r
609\r
610Returns:\r
611 \r
612 EFI_SUCCESS on successful return\r
613 EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
614 EFI_ABORTED if unable to open input file.\r
615 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
616--*/\r
617{\r
618 UINT32 TotalLength;\r
619 UINT32 InputLength;\r
620 UINT32 CompressedLength;\r
621 UINT32 HeaderLength;\r
622 UINT8 *FileBuffer;\r
623 UINT8 *OutputBuffer;\r
624 EFI_STATUS Status;\r
625 EFI_COMPRESSION_SECTION *CompressionSect;\r
626 EFI_COMPRESSION_SECTION2 *CompressionSect2;\r
627 COMPRESS_FUNCTION CompressFunction;\r
628\r
629 InputLength = 0;\r
630 FileBuffer = NULL;\r
631 OutputBuffer = NULL;\r
632 CompressedLength = 0;\r
633 TotalLength = 0;\r
634 //\r
635 // read all input file contents into a buffer\r
636 // first get the size of all file contents\r
637 //\r
638 Status = GetSectionContents (\r
639 InputFileName,\r
640 InputFileAlign,\r
641 InputFileNum,\r
642 FileBuffer,\r
643 &InputLength\r
644 );\r
645\r
646 if (Status == EFI_BUFFER_TOO_SMALL) {\r
647 FileBuffer = (UINT8 *) malloc (InputLength);\r
648 if (FileBuffer == NULL) {\r
649 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
650 return EFI_OUT_OF_RESOURCES;\r
651 }\r
652 //\r
653 // read all input file contents into a buffer\r
654 //\r
655 Status = GetSectionContents (\r
656 InputFileName,\r
657 InputFileAlign,\r
658 InputFileNum,\r
659 FileBuffer,\r
660 &InputLength\r
661 );\r
662 }\r
663\r
664 if (EFI_ERROR (Status)) {\r
665 if (FileBuffer != NULL) {\r
666 free (FileBuffer);\r
667 }\r
668 return Status;\r
669 }\r
670\r
671 if (FileBuffer == NULL) {\r
672 return EFI_OUT_OF_RESOURCES;\r
673 }\r
674\r
675 CompressFunction = NULL;\r
676\r
677 //\r
678 // Now data is in FileBuffer, compress the data\r
679 //\r
680 switch (SectCompSubType) {\r
681 case EFI_NOT_COMPRESSED:\r
682 CompressedLength = InputLength;\r
683 HeaderLength = sizeof (EFI_COMPRESSION_SECTION);\r
684 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {\r
685 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);\r
686 }\r
687 TotalLength = CompressedLength + HeaderLength;\r
688 //\r
689 // Copy file buffer to the none compressed data.\r
690 //\r
691 OutputBuffer = malloc (TotalLength);\r
692 if (OutputBuffer == NULL) {\r
693 free (FileBuffer);\r
694 return EFI_OUT_OF_RESOURCES;\r
695 }\r
696 memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);\r
697 free (FileBuffer);\r
698 FileBuffer = OutputBuffer;\r
699 break;\r
700\r
701 case EFI_STANDARD_COMPRESSION:\r
702 CompressFunction = (COMPRESS_FUNCTION) EfiCompress;\r
703 break;\r
704\r
705 default:\r
706 Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");\r
707 free (FileBuffer);\r
708 return EFI_ABORTED;\r
709 }\r
710\r
711 if (CompressFunction != NULL) {\r
712\r
713 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);\r
714 if (Status == EFI_BUFFER_TOO_SMALL) {\r
715 HeaderLength = sizeof (EFI_COMPRESSION_SECTION);\r
716 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {\r
717 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);\r
718 }\r
719 TotalLength = CompressedLength + HeaderLength;\r
720 OutputBuffer = malloc (TotalLength);\r
721 if (!OutputBuffer) {\r
722 free (FileBuffer);\r
723 return EFI_OUT_OF_RESOURCES;\r
724 }\r
725\r
726 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);\r
727 }\r
728\r
729 free (FileBuffer);\r
730 FileBuffer = OutputBuffer;\r
731\r
732 if (EFI_ERROR (Status)) {\r
733 if (FileBuffer != NULL) {\r
734 free (FileBuffer);\r
735 }\r
736\r
737 return Status;\r
738 }\r
739\r
740 if (FileBuffer == NULL) {\r
741 return EFI_OUT_OF_RESOURCES;\r
742 }\r
743 }\r
744\r
745 DebugMsg (NULL, 0, 9, "comprss file size", \r
746 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);\r
747\r
748 //if (TotalLength >= MAX_SECTION_SIZE) {\r
749 // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
750 // if (FileBuffer != NULL) {\r
751 // free (FileBuffer);\r
752 // }\r
753 // if (OutputBuffer != NULL) {\r
754 // free (OutputBuffer);\r
755 // }\r
756 // return STATUS_ERROR;\r
757 //}\r
758 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
759\r
760 //\r
761 // Add the section header for the compressed data\r
762 //\r
763 if (TotalLength >= MAX_SECTION_SIZE) {\r
764 CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;\r
765\r
766 memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);\r
767 CompressionSect2->CommonHeader.Type = EFI_SECTION_COMPRESSION;\r
768 CompressionSect2->CommonHeader.ExtendedSize = TotalLength;\r
769 CompressionSect2->CompressionType = SectCompSubType;\r
770 CompressionSect2->UncompressedLength = InputLength;\r
771 } else {\r
772 CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;\r
773 \r
774 CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION;\r
775 CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);\r
776 CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
777 CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
778 CompressionSect->CompressionType = SectCompSubType;\r
779 CompressionSect->UncompressedLength = InputLength;\r
780 }\r
781\r
782 //\r
783 // Set OutFileBuffer \r
784 //\r
785 *OutFileBuffer = FileBuffer;\r
786\r
787 return EFI_SUCCESS;\r
788}\r
789\r
790EFI_STATUS\r
791GenSectionGuidDefinedSection (\r
792 CHAR8 **InputFileName,\r
793 UINT32 *InputFileAlign,\r
794 UINT32 InputFileNum,\r
795 EFI_GUID *VendorGuid,\r
796 UINT16 DataAttribute,\r
797 UINT32 DataHeaderSize,\r
798 UINT8 **OutFileBuffer\r
799 )\r
800/*++\r
801 \r
802Routine Description:\r
803 \r
804 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED\r
805 Input file must be already sectioned. The function won't validate\r
806 the input files' contents. Caller should hand in files already \r
807 with section header.\r
808 \r
809Arguments:\r
810 \r
811 InputFileName - Name of the input file.\r
812 \r
813 InputFileAlign - Alignment required by the input file data.\r
814\r
815 InputFileNum - Number of input files. Should be at least 1.\r
816\r
817 VendorGuid - Specify vendor guid value.\r
818\r
819 DataAttribute - Specify attribute for the vendor guid data. \r
820 \r
821 DataHeaderSize- Guided Data Header Size\r
822 \r
823 OutFileBuffer - Buffer pointer to Output file contents\r
824\r
825Returns:\r
826 \r
827 EFI_SUCCESS on successful return\r
828 EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
829 EFI_ABORTED if unable to open input file.\r
830 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
831\r
832--*/\r
833{\r
834 UINT32 TotalLength;\r
835 UINT32 InputLength;\r
836 UINT32 Offset;\r
837 UINT8 *FileBuffer;\r
838 UINT32 Crc32Checksum;\r
839 EFI_STATUS Status;\r
840 CRC32_SECTION_HEADER *Crc32GuidSect;\r
841 CRC32_SECTION_HEADER2 *Crc32GuidSect2;\r
842 EFI_GUID_DEFINED_SECTION *VendorGuidSect;\r
843 EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2;\r
844\r
845 InputLength = 0;\r
846 Offset = 0;\r
847 FileBuffer = NULL;\r
848 TotalLength = 0;\r
849\r
850 //\r
851 // read all input file contents into a buffer\r
852 // first get the size of all file contents\r
853 //\r
854 Status = GetSectionContents (\r
855 InputFileName,\r
856 InputFileAlign,\r
857 InputFileNum,\r
858 FileBuffer,\r
859 &InputLength\r
860 );\r
861\r
862 if (Status == EFI_BUFFER_TOO_SMALL) {\r
863 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {\r
864 Offset = sizeof (CRC32_SECTION_HEADER);\r
865 if (InputLength + Offset >= MAX_SECTION_SIZE) {\r
866 Offset = sizeof (CRC32_SECTION_HEADER2);\r
867 }\r
868 } else {\r
869 Offset = sizeof (EFI_GUID_DEFINED_SECTION);\r
870 if (InputLength + Offset >= MAX_SECTION_SIZE) {\r
871 Offset = sizeof (EFI_GUID_DEFINED_SECTION2);\r
872 }\r
873 }\r
874 TotalLength = InputLength + Offset;\r
875\r
876 FileBuffer = (UINT8 *) malloc (InputLength + Offset);\r
877 if (FileBuffer == NULL) {\r
878 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
879 return EFI_OUT_OF_RESOURCES;\r
880 }\r
881 //\r
882 // read all input file contents into a buffer\r
883 //\r
884 Status = GetSectionContents (\r
885 InputFileName,\r
886 InputFileAlign,\r
887 InputFileNum,\r
888 FileBuffer + Offset,\r
889 &InputLength\r
890 );\r
891 }\r
892\r
893 if (EFI_ERROR (Status)) {\r
894 if (FileBuffer != NULL) {\r
895 free (FileBuffer);\r
896 }\r
897 Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);\r
898 return Status;\r
899 }\r
900\r
901 if (InputLength == 0) {\r
902 if (FileBuffer != NULL) {\r
903 free (FileBuffer);\r
904 }\r
905 Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);\r
906 return EFI_NOT_FOUND;\r
907 }\r
908\r
909 //\r
910 // InputLength != 0, but FileBuffer == NULL means out of resources.\r
911 //\r
912 if (FileBuffer == NULL) {\r
913 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
914 return EFI_OUT_OF_RESOURCES;\r
915 }\r
916\r
917 //\r
918 // Now data is in FileBuffer + Offset\r
919 //\r
920 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {\r
921 //\r
922 // Default Guid section is CRC32.\r
923 //\r
924 Crc32Checksum = 0;\r
925 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
926 \r
927 if (TotalLength >= MAX_SECTION_SIZE) {\r
928 Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;\r
929 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;\r
930 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) 0xff;\r
931 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) 0xff;\r
932 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) 0xff;\r
933 Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;\r
934 memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
935 Crc32GuidSect2->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
936 Crc32GuidSect2->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER2);\r
937 Crc32GuidSect2->CRC32Checksum = Crc32Checksum;\r
938 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);\r
939 } else {\r
940 Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;\r
941 Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;\r
942 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);\r
943 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
944 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
945 memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
946 Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
947 Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);\r
948 Crc32GuidSect->CRC32Checksum = Crc32Checksum;\r
949 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);\r
950 }\r
951 } else {\r
952 if (TotalLength >= MAX_SECTION_SIZE) {\r
953 VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;\r
954 VendorGuidSect2->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;\r
955 VendorGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff;\r
956 VendorGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff;\r
957 VendorGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff;\r
958 VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);\r
959 memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
960 VendorGuidSect2->Attributes = DataAttribute;\r
961 VendorGuidSect2->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);\r
962 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);\r
963 } else {\r
964 VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;\r
965 VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;\r
966 VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);\r
967 VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
968 VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
969 memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
970 VendorGuidSect->Attributes = DataAttribute;\r
971 VendorGuidSect->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);\r
972 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);\r
973 }\r
974 }\r
975 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
976 \r
977 //\r
978 // Set OutFileBuffer \r
979 //\r
980 *OutFileBuffer = FileBuffer;\r
981\r
982 return EFI_SUCCESS;\r
983}\r
984\r
985int\r
986main (\r
987 int argc,\r
988 char *argv[]\r
989 )\r
990/*++\r
991\r
992Routine Description:\r
993\r
994 Main\r
995\r
996Arguments:\r
997\r
998 command line parameters\r
999\r
1000Returns:\r
1001\r
1002 EFI_SUCCESS Section header successfully generated and section concatenated.\r
1003 EFI_ABORTED Could not generate the section\r
1004 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
1005\r
1006--*/\r
1007{\r
1008 UINT32 Index;\r
1009 UINT32 InputFileNum;\r
1010 FILE *OutFile;\r
1011 CHAR8 **InputFileName;\r
1012 CHAR8 *OutputFileName;\r
1013 CHAR8 *SectionName;\r
1014 CHAR8 *CompressionName;\r
1015 CHAR8 *StringBuffer;\r
1016 EFI_GUID VendorGuid = mZeroGuid;\r
1017 int VersionNumber;\r
1018 UINT8 SectType;\r
1019 UINT8 SectCompSubType;\r
1020 UINT16 SectGuidAttribute; \r
1021 UINT64 SectGuidHeaderLength;\r
1022 EFI_VERSION_SECTION *VersionSect;\r
1023 EFI_USER_INTERFACE_SECTION *UiSect;\r
1024 UINT32 InputLength;\r
1025 UINT8 *OutFileBuffer;\r
1026 EFI_STATUS Status;\r
1027 UINT64 LogLevel;\r
1028 UINT32 *InputFileAlign;\r
1029 UINT32 InputFileAlignNum;\r
1030 EFI_COMMON_SECTION_HEADER *SectionHeader;\r
1031\r
1032 InputFileAlign = NULL;\r
1033 InputFileAlignNum = 0;\r
1034 InputFileName = NULL;\r
1035 OutputFileName = NULL;\r
1036 SectionName = NULL;\r
1037 CompressionName = NULL;\r
1038 StringBuffer = "";\r
1039 OutFile = NULL;\r
1040 VersionNumber = 0;\r
1041 InputFileNum = 0;\r
1042 SectType = EFI_SECTION_ALL;\r
1043 SectCompSubType = 0;\r
1044 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;\r
1045 OutFileBuffer = NULL;\r
1046 InputLength = 0;\r
1047 Status = STATUS_SUCCESS;\r
1048 LogLevel = 0;\r
1049 SectGuidHeaderLength = 0;\r
1050 VersionSect = NULL;\r
1051 UiSect = NULL;\r
1052 \r
1053 SetUtilityName (UTILITY_NAME);\r
1054 \r
1055 if (argc == 1) {\r
1056 Error (NULL, 0, 1001, "Missing options", "No options input");\r
1057 Usage ();\r
1058 return STATUS_ERROR;\r
1059 }\r
1060\r
1061 //\r
1062 // Parse command line\r
1063 //\r
1064 argc --;\r
1065 argv ++;\r
1066\r
1067 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
1068 Version ();\r
1069 Usage ();\r
1070 return STATUS_SUCCESS; \r
1071 }\r
1072\r
1073 if (stricmp (argv[0], "--version") == 0) {\r
1074 Version ();\r
1075 return STATUS_SUCCESS; \r
1076 }\r
1077\r
1078 while (argc > 0) {\r
1079 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {\r
1080 SectionName = argv[1];\r
1081 if (SectionName == NULL) {\r
1082 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");\r
1083 goto Finish;\r
1084 }\r
1085 argc -= 2;\r
1086 argv += 2;\r
1087 continue; \r
1088 }\r
1089\r
1090 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
1091 OutputFileName = argv[1];\r
1092 if (OutputFileName == NULL) {\r
1093 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");\r
1094 goto Finish;\r
1095 }\r
1096 argc -= 2;\r
1097 argv += 2;\r
1098 continue; \r
1099 }\r
1100\r
1101 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {\r
1102 CompressionName = argv[1];\r
1103 if (CompressionName == NULL) {\r
1104 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");\r
1105 goto Finish;\r
1106 }\r
1107 argc -= 2;\r
1108 argv += 2;\r
1109 continue;\r
1110 }\r
1111\r
1112 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {\r
1113 Status = StringToGuid (argv[1], &VendorGuid);\r
1114 if (EFI_ERROR (Status)) {\r
1115 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1116 goto Finish;\r
1117 }\r
1118 argc -= 2;\r
1119 argv += 2;\r
1120 continue;\r
1121 }\r
1122\r
1123 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
1124 if (argv[1] == NULL) {\r
1125 Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");\r
1126 goto Finish;\r
1127 }\r
1128 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
1129 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
1130 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
1131 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
1132 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {\r
1133 //\r
1134 // NONE attribute\r
1135 //\r
1136 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;\r
1137 } else {\r
1138 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1139 goto Finish;\r
1140 }\r
1141 argc -= 2;\r
1142 argv += 2;\r
1143 continue;\r
1144 }\r
1145\r
1146 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {\r
1147 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);\r
1148 if (EFI_ERROR (Status)) {\r
1149 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);\r
1150 goto Finish;\r
1151 }\r
1152 argc -= 2;\r
1153 argv += 2;\r
1154 continue;\r
1155 }\r
1156\r
1157 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {\r
1158 StringBuffer = argv[1];\r
1159 if (StringBuffer == NULL) {\r
1160 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");\r
1161 goto Finish;\r
1162 }\r
1163 argc -= 2;\r
1164 argv += 2;\r
1165 continue;\r
1166 }\r
1167\r
1168 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {\r
1169 if (argv[1] == NULL) {\r
1170 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");\r
1171 goto Finish;\r
1172 }\r
1173 //\r
1174 // Verify string is a integrator number\r
1175 //\r
1176 for (Index = 0; Index < strlen (argv[1]); Index++) {\r
1177 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {\r
1178 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1179 goto Finish;\r
1180 }\r
1181 }\r
1182\r
1183 sscanf (argv[1], "%d", &VersionNumber);\r
1184 argc -= 2;\r
1185 argv += 2;\r
1186 continue;\r
1187 }\r
1188\r
1189 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1190 SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1191 VerboseMsg ("Verbose output Mode Set!");\r
1192 argc --;\r
1193 argv ++;\r
1194 continue;\r
1195 }\r
1196\r
1197 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1198 SetPrintLevel (KEY_LOG_LEVEL);\r
1199 KeyMsg ("Quiet output Mode Set!");\r
1200 argc --;\r
1201 argv ++;\r
1202 continue;\r
1203 }\r
1204\r
1205 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1206 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1207 if (EFI_ERROR (Status)) {\r
1208 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1209 goto Finish;\r
1210 }\r
1211 if (LogLevel > 9) {\r
1212 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);\r
1213 goto Finish;\r
1214 }\r
1215 SetPrintLevel (LogLevel);\r
1216 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1217 argc -= 2;\r
1218 argv += 2;\r
1219 continue;\r
1220 }\r
1221\r
1222 //\r
1223 // Section File alignment requirement\r
1224 //\r
1225 if (stricmp (argv[0], "--sectionalign") == 0) {\r
1226 if (InputFileAlignNum == 0) {\r
1227 InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1228 if (InputFileAlign == NULL) {\r
1229 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1230 goto Finish;\r
1231 }\r
1232 memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1233 } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1234 InputFileAlign = (UINT32 *) realloc (\r
1235 InputFileAlign,\r
1236 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)\r
1237 );\r
1238\r
1239 if (InputFileAlign == NULL) {\r
1240 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1241 goto Finish;\r
1242 }\r
1243 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
1244 }\r
1245 \r
1246 Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));\r
1247 if (EFI_ERROR (Status)) {\r
1248 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1249 goto Finish;\r
1250 }\r
1251 argc -= 2;\r
1252 argv += 2;\r
1253 InputFileAlignNum ++;\r
1254 continue; \r
1255 }\r
1256\r
1257 //\r
1258 // Get Input file name\r
1259 //\r
1260 if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1261 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1262 if (InputFileName == NULL) {\r
1263 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1264 goto Finish;\r
1265 }\r
1266 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1267 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1268 //\r
1269 // InputFileName buffer too small, need to realloc\r
1270 //\r
1271 InputFileName = (CHAR8 **) realloc (\r
1272 InputFileName,\r
1273 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1274 );\r
1275\r
1276 if (InputFileName == NULL) {\r
1277 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1278 goto Finish;\r
1279 }\r
1280 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1281 }\r
1282\r
1283 InputFileName[InputFileNum++] = argv[0];\r
1284 argc --;\r
1285 argv ++;\r
1286 }\r
1287\r
1288 if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {\r
1289 Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");\r
1290 goto Finish;\r
1291 }\r
1292\r
1293 VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1294\r
1295 //\r
1296 // Parse all command line parameters to get the corresponding section type.\r
1297 //\r
1298 VerboseMsg ("Section type is %s", SectionName);\r
1299 if (SectionName == NULL) {\r
1300 //\r
1301 // No specified Section type, default is SECTION_ALL.\r
1302 //\r
1303 SectType = EFI_SECTION_ALL;\r
1304 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {\r
1305 SectType = EFI_SECTION_COMPRESSION;\r
1306 if (CompressionName == NULL) {\r
1307 //\r
1308 // Default is PI_STD compression algorithm.\r
1309 //\r
1310 SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1311 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {\r
1312 SectCompSubType = EFI_NOT_COMPRESSED;\r
1313 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {\r
1314 SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1315 } else {\r
1316 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);\r
1317 goto Finish;\r
1318 }\r
1319 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);\r
1320 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
1321 SectType = EFI_SECTION_GUID_DEFINED;\r
1322 \r
1323 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
1324 //\r
1325 // NONE attribute, clear attribute value.\r
1326 //\r
1327 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;\r
1328 }\r
1329 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
1330 (unsigned) VendorGuid.Data1,\r
1331 VendorGuid.Data2,\r
1332 VendorGuid.Data3,\r
1333 VendorGuid.Data4[0],\r
1334 VendorGuid.Data4[1],\r
1335 VendorGuid.Data4[2],\r
1336 VendorGuid.Data4[3],\r
1337 VendorGuid.Data4[4],\r
1338 VendorGuid.Data4[5],\r
1339 VendorGuid.Data4[6],\r
1340 VendorGuid.Data4[7]);\r
1341 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {\r
1342 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);\r
1343 }\r
1344 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {\r
1345 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);\r
1346 }\r
1347 if (SectGuidHeaderLength != 0) {\r
1348 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);\r
1349 }\r
1350 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {\r
1351 SectType = EFI_SECTION_PE32;\r
1352 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {\r
1353 SectType = EFI_SECTION_PIC;\r
1354 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {\r
1355 SectType = EFI_SECTION_TE;\r
1356 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {\r
1357 SectType = EFI_SECTION_DXE_DEPEX;\r
1358 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {\r
1359 SectType = EFI_SECTION_SMM_DEPEX;\r
1360 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
1361 SectType = EFI_SECTION_VERSION;\r
1362 if (VersionNumber < 0 || VersionNumber > 65535) {\r
1363 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);\r
1364 goto Finish;\r
1365 }\r
1366 VerboseMsg ("Version section number is %d", VersionNumber);\r
1367 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {\r
1368 SectType = EFI_SECTION_USER_INTERFACE;\r
1369 if (StringBuffer[0] == '\0') {\r
1370 Error (NULL, 0, 1001, "Missing option", "user interface string");\r
1371 goto Finish;\r
1372 }\r
1373 VerboseMsg ("UI section string name is %s", StringBuffer);\r
1374 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {\r
1375 SectType = EFI_SECTION_COMPATIBILITY16;\r
1376 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {\r
1377 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
1378 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {\r
1379 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
1380 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {\r
1381 SectType = EFI_SECTION_RAW;\r
1382 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {\r
1383 SectType = EFI_SECTION_PEI_DEPEX;\r
1384 } else {\r
1385 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);\r
1386 goto Finish;\r
1387 }\r
1388 \r
1389 //\r
1390 // GuidValue is only required by Guided section.\r
1391 //\r
1392 if ((SectType != EFI_SECTION_GUID_DEFINED) &&\r
1393 (SectionName != NULL) &&\r
1394 (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
1395 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);\r
1396 }\r
1397 \r
1398 //\r
1399 // Check whether there is input file\r
1400 // \r
1401 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {\r
1402 //\r
1403 // The input file are required for other section type.\r
1404 //\r
1405 if (InputFileNum == 0) {\r
1406 Error (NULL, 0, 1001, "Missing options", "Input files");\r
1407 goto Finish;\r
1408 }\r
1409 }\r
1410 //\r
1411 // Check whether there is output file\r
1412 //\r
1413 for (Index = 0; Index < InputFileNum; Index ++) {\r
1414 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);\r
1415 }\r
1416 if (OutputFileName == NULL) {\r
1417 Error (NULL, 0, 1001, "Missing options", "Output file");\r
1418 goto Finish;\r
1419 // OutFile = stdout;\r
1420 }\r
1421 VerboseMsg ("Output file name is %s", OutputFileName);\r
1422\r
1423 //\r
1424 // At this point, we've fully validated the command line, and opened appropriate\r
1425 // files, so let's go and do what we've been asked to do...\r
1426 //\r
1427 //\r
1428 // Within this switch, build and write out the section header including any\r
1429 // section type specific pieces. If there's an input file, it's tacked on later\r
1430 //\r
1431 switch (SectType) {\r
1432 case EFI_SECTION_COMPRESSION:\r
1433 if (InputFileAlign != NULL) {\r
1434 free (InputFileAlign);\r
1435 InputFileAlign = NULL;\r
1436 }\r
1437 Status = GenSectionCompressionSection (\r
1438 InputFileName,\r
1439 InputFileAlign,\r
1440 InputFileNum,\r
1441 SectCompSubType,\r
1442 &OutFileBuffer\r
1443 );\r
1444 break;\r
1445\r
1446 case EFI_SECTION_GUID_DEFINED:\r
1447 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
1448 //\r
1449 // Only process alignment for the default known CRC32 guided section.\r
1450 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.\r
1451 //\r
1452 free (InputFileAlign);\r
1453 InputFileAlign = NULL;\r
1454 }\r
1455 Status = GenSectionGuidDefinedSection (\r
1456 InputFileName,\r
1457 InputFileAlign,\r
1458 InputFileNum,\r
1459 &VendorGuid,\r
1460 SectGuidAttribute,\r
1461 (UINT32) SectGuidHeaderLength,\r
1462 &OutFileBuffer\r
1463 );\r
1464 break;\r
1465\r
1466 case EFI_SECTION_VERSION:\r
1467 Index = sizeof (EFI_COMMON_SECTION_HEADER);\r
1468 //\r
1469 // 2 bytes for the build number UINT16\r
1470 //\r
1471 Index += 2;\r
1472 //\r
1473 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1474 //\r
1475 Index += (strlen (StringBuffer) * 2) + 2;\r
1476 OutFileBuffer = (UINT8 *) malloc (Index);\r
1477 if (OutFileBuffer == NULL) {\r
1478 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1479 goto Finish;\r
1480 }\r
1481 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;\r
1482 VersionSect->CommonHeader.Type = SectType;\r
1483 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);\r
1484 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);\r
1485 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);\r
1486 VersionSect->BuildNumber = (UINT16) VersionNumber;\r
1487 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);\r
1488 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
1489 break;\r
1490\r
1491 case EFI_SECTION_USER_INTERFACE:\r
1492 Index = sizeof (EFI_COMMON_SECTION_HEADER);\r
1493 //\r
1494 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1495 //\r
1496 Index += (strlen (StringBuffer) * 2) + 2;\r
1497 OutFileBuffer = (UINT8 *) malloc (Index);\r
1498 if (OutFileBuffer == NULL) {\r
1499 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1500 goto Finish;\r
1501 }\r
1502 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;\r
1503 UiSect->CommonHeader.Type = SectType;\r
1504 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);\r
1505 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);\r
1506 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);\r
1507 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);\r
1508 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
1509 break;\r
1510\r
1511 case EFI_SECTION_ALL:\r
1512 //\r
1513 // read all input file contents into a buffer\r
1514 // first get the size of all file contents\r
1515 //\r
1516 Status = GetSectionContents (\r
1517 InputFileName,\r
1518 InputFileAlign,\r
1519 InputFileNum,\r
1520 OutFileBuffer,\r
1521 &InputLength\r
1522 );\r
1523 \r
1524 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1525 OutFileBuffer = (UINT8 *) malloc (InputLength);\r
1526 if (OutFileBuffer == NULL) {\r
1527 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1528 goto Finish;\r
1529 }\r
1530 //\r
1531 // read all input file contents into a buffer\r
1532 //\r
1533 Status = GetSectionContents (\r
1534 InputFileName,\r
1535 InputFileAlign,\r
1536 InputFileNum,\r
1537 OutFileBuffer,\r
1538 &InputLength\r
1539 );\r
1540 }\r
1541 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);\r
1542 break;\r
1543 default:\r
1544 //\r
1545 // All other section types are caught by default (they're all the same)\r
1546 //\r
1547 Status = GenSectionCommonLeafSection (\r
1548 InputFileName,\r
1549 InputFileNum,\r
1550 SectType,\r
1551 &OutFileBuffer\r
1552 );\r
1553 break;\r
1554 }\r
1555 \r
1556 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {\r
1557 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);\r
1558 goto Finish;\r
1559 }\r
1560\r
1561 //\r
1562 // Get output file length\r
1563 //\r
1564 if (SectType != EFI_SECTION_ALL) {\r
1565 SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;\r
1566 InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;\r
1567 if (InputLength == 0xffffff) {\r
1568 InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;\r
1569 }\r
1570 }\r
1571 \r
1572 //\r
1573 // Write the output file\r
1574 //\r
1575 OutFile = fopen (LongFilePath (OutputFileName), "wb");\r
1576 if (OutFile == NULL) {\r
1577 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);\r
1578 goto Finish;\r
1579 }\r
1580\r
1581 fwrite (OutFileBuffer, InputLength, 1, OutFile);\r
1582\r
1583Finish:\r
1584 if (InputFileName != NULL) {\r
1585 free (InputFileName);\r
1586 }\r
1587\r
1588 if (InputFileAlign != NULL) {\r
1589 free (InputFileAlign);\r
1590 }\r
1591\r
1592 if (OutFileBuffer != NULL) {\r
1593 free (OutFileBuffer);\r
1594 }\r
1595\r
1596 if (OutFile != NULL) {\r
1597 fclose (OutFile);\r
1598 }\r
1599 \r
1600 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1601\r
1602 return GetUtilityStatus ();\r
1603}\r