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