]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/UefiHiiPack/HiiPack.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / UefiHiiPack / HiiPack.c
CommitLineData
3e99020d
LG
1/*++\r
2\r
3Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 HiiPack.c\r
15\r
16Abstract:\r
17\r
18 Process HII package files to generate HII package list binary file or PE/COFF\r
19 resource script file (i.e. .rc file).\r
20\r
21--*/\r
22\r
23#include <stdio.h>\r
24#include <string.h>\r
25\r
26#include "Tiano.h"\r
27#include "EfiHii.h"\r
28\r
29#include "EfiUtilityMsgs.h"\r
30#include "ParseInf.h"\r
31\r
32#define UTILITY_VERSION "v1.0"\r
33#define UTILITY_NAME "HiiPack"\r
34#define MAX_PATH 260\r
35\r
36//\r
37// Define HII resource section type and name\r
38//\r
39#define HII_RESOURCE_TYPE "HII"\r
40#define HII_RESOURCE_NAME 1\r
41\r
42//\r
43// We'll store lists of file names from the command line in\r
44// a linked list of these\r
45//\r
46typedef struct _FILE_NAME_LIST {\r
47 struct _FILE_NAME_LIST *Next;\r
48 UINT8 FileName[MAX_PATH];\r
49 UINT32 PackageType;\r
50 UINT32 Length;\r
51 UINT8 *Data;\r
52} FILE_NAME_LIST;\r
53\r
54//\r
55// Create some defines for the different operation modes supported by this utility\r
56//\r
57#define MODE_CREATE_HII_RESOURCE_FILE 0x0001\r
58#define MODE_CREATE_HII_PACKAGE_LIST 0x0002\r
59\r
60//\r
61// Here's all our globals.\r
62//\r
63static struct {\r
64 FILE_NAME_LIST *PackageFile; // all include paths to search\r
65 FILE_NAME_LIST *LastPackageFile;\r
66 UINT8 PackageListFileName[MAX_PATH]; // Output package list file name\r
67 UINT8 ResourceFileName[MAX_PATH]; // Output HII resource file name\r
68 EFI_GUID Guid; // Guid specified on command line\r
69 BOOLEAN GuidSpecified;\r
70 BOOLEAN Verbose;\r
71 UINT32 Mode; // Mode this utility is operating in\r
72} mGlobals;\r
73\r
74static\r
75void\r
76Usage (\r
77 VOID\r
78 );\r
79\r
80static\r
81STATUS\r
82ProcessArgs (\r
83 int Argc,\r
84 char *Argv[]\r
85 );\r
86\r
87static\r
88void\r
89FreeGlobals (\r
90 VOID\r
91 );\r
92\r
93static\r
94void\r
95DumpRawBytes (\r
96 FILE *OutFptr,\r
97 UINT8 *Buffer,\r
98 int Count,\r
99 int Indent\r
100 );\r
101\r
102static\r
103STATUS\r
104CreateResourceScript (\r
105 char *OutputFileName,\r
106 EFI_GUID *PackageListGuid,\r
107 FILE_NAME_LIST *PackageFiles\r
108 );\r
109\r
110static\r
111STATUS\r
112CreatePackageList (\r
113 char *OutputFileName,\r
114 EFI_GUID *PackageListGuid,\r
115 FILE_NAME_LIST *PackageFiles\r
116 );\r
117\r
118int\r
119main (\r
120 int Argc,\r
121 char *Argv[]\r
122 )\r
123/*++\r
124\r
125Routine Description:\r
126\r
127 Call the routine to parse the command-line options, then process the file.\r
128\r
129Arguments:\r
130\r
131 Standard C main() argc and argv.\r
132\r
133Returns:\r
134\r
135 0 if successful\r
136 nonzero otherwise\r
137\r
138--*/\r
139{\r
140 STATUS Status;\r
141\r
142 //\r
143 // Set the utility name for error reporting purposes\r
144 //\r
145 SetUtilityName (UTILITY_NAME);\r
146\r
147 //\r
148 // Process the command-line arguments\r
149 //\r
150 Status = ProcessArgs (Argc, Argv);\r
151 if (Status != STATUS_SUCCESS) {\r
152 return Status;\r
153 }\r
154\r
155 //\r
156 // Switch based on args\r
157 //\r
158 if (mGlobals.Mode & MODE_CREATE_HII_RESOURCE_FILE) {\r
159 CreateResourceScript (mGlobals.ResourceFileName, &mGlobals.Guid, mGlobals.PackageFile);\r
160 }\r
161\r
162 if (mGlobals.Mode & MODE_CREATE_HII_PACKAGE_LIST) {\r
163 CreatePackageList (mGlobals.PackageListFileName, &mGlobals.Guid, mGlobals.PackageFile);\r
164 }\r
165\r
166 FreeGlobals ();\r
167\r
168 return GetUtilityStatus ();\r
169}\r
170\r
171/******************************************************************************/\r
172static const char *gRcFileHeader[] = {\r
173 "//",\r
174 "// DO NOT EDIT -- auto-generated file",\r
175 "//",\r
176 "// This file is generated by the hiipack utility",\r
177 "//",\r
178 NULL\r
179};\r
180\r
181static\r
182STATUS\r
183CreateResourceScript (\r
184 char *OutputFileName,\r
185 EFI_GUID *PackageListGuid,\r
186 FILE_NAME_LIST *PackageFiles\r
187 )\r
188/*++\r
189\r
190Routine Description:\r
191\r
192 Given a linked list of HII package files, walk the list to\r
193 process them and create a single HII resource script file.\r
194\r
195Arguments:\r
196\r
197 OutputFileName - name of output HII resource script file to create\r
198 PackageListGuid - the specified package list GUID\r
199 PackageFiles - linked list of HII package files to process\r
200\r
201Returns:\r
202\r
203 STATUS_SUCCESS - if successful\r
204 STATUS_ERROR - otherwise\r
205\r
206--*/\r
207{\r
208 STATUS Status;\r
209 UINT8 *PackageList;\r
210 UINT8 *Buffer;\r
211 UINT32 PackageListLen;\r
212 FILE *OutFptr;\r
213 UINTN Index;\r
214 FILE_NAME_LIST *Package;\r
215\r
216 //\r
217 // If no input HII pack files, then why are we here? Should have been caught when\r
218 // args were processed though.\r
219 //\r
220 if (PackageFiles == NULL) {\r
221 Error (NULL, 0, 0, "no input package file(s) specified", NULL);\r
222 return STATUS_ERROR;\r
223 }\r
224\r
225 OutFptr = NULL;\r
226 Status = STATUS_ERROR;\r
227\r
228 //\r
229 // Open the output file for writing\r
230 //\r
231 if ((OutFptr = fopen (OutputFileName, "w")) == NULL) {\r
232 Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");\r
233 goto Done;\r
234 }\r
235\r
236 //\r
237 // Write file header\r
238 //\r
239 for (Index = 0; gRcFileHeader[Index] != NULL; Index++) {\r
240 fprintf (OutFptr, "%s\n", gRcFileHeader[Index]);\r
241 }\r
242\r
243 //\r
244 // Write nameID and typeID\r
245 //\r
246 fprintf (OutFptr, "\n");\r
247 fprintf (OutFptr, "%d %s\n", HII_RESOURCE_NAME, HII_RESOURCE_TYPE);\r
248 fprintf (OutFptr, "{\n");\r
249\r
250 //\r
251 // Prepare package list\r
252 //\r
253 PackageListLen = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
254 Package = PackageFiles;\r
255 while (Package != NULL) {\r
256 PackageListLen += Package->Length;\r
257 Package = Package->Next;\r
258 }\r
259 //\r
260 // Inlucde the length of EFI_HII_PACKAGE_END\r
261 //\r
262 PackageListLen += sizeof (EFI_HII_PACKAGE_HEADER);\r
263\r
264 Buffer = (UINT8 *) malloc (PackageListLen);\r
265 if (Buffer == NULL) {\r
266 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
267 goto Done;\r
268 }\r
269 PackageList = Buffer;\r
270\r
271 memcpy (Buffer, PackageListGuid, sizeof (EFI_GUID));\r
272 Buffer += sizeof (EFI_GUID);\r
273 memcpy (Buffer, &PackageListLen, sizeof (UINT32));\r
274 Buffer += sizeof (UINT32);\r
275\r
276 Package = PackageFiles;\r
277 while (Package != NULL) {\r
278 memcpy (Buffer, Package->Data, Package->Length);\r
279 Buffer += Package->Length;\r
280 Package = Package->Next;\r
281 }\r
282 //\r
283 // Append EFI_HII_PACKAGE_END\r
284 //\r
285 ((EFI_HII_PACKAGE_HEADER *) Buffer)->Type = EFI_HII_PACKAGE_END;\r
286 ((EFI_HII_PACKAGE_HEADER *) Buffer)->Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
287\r
288 //\r
289 // Dump package list\r
290 //\r
291 DumpRawBytes (OutFptr, PackageList, PackageListLen, 2);\r
292\r
293 //\r
294 // Write file tail\r
295 //\r
296 fprintf (OutFptr, "}\n");\r
297\r
298 Status = STATUS_SUCCESS;\r
299\r
300Done:\r
301 if (OutFptr != NULL) {\r
302 fclose (OutFptr);\r
303 }\r
304\r
305 return Status;\r
306}\r
307\r
308static\r
309STATUS\r
310CreatePackageList (\r
311 char *OutputFileName,\r
312 EFI_GUID *PackageListGuid,\r
313 FILE_NAME_LIST *PackageFiles\r
314 )\r
315/*++\r
316\r
317Routine Description:\r
318\r
319 Given a linked list of HII package files, walk the list to\r
320 process them and create a binary HII package list file.\r
321\r
322Arguments:\r
323\r
324 OutputFileName - name of output HII package list file to create\r
325 PackageListGuid - the specified package list GUID\r
326 PackageFiles - linked list of HII package files to process\r
327\r
328Returns:\r
329\r
330 STATUS_SUCCESS - if successful\r
331 STATUS_ERROR - otherwise\r
332\r
333--*/\r
334{\r
335 FILE *OutFptr;\r
336 UINT32 PackageListLen;\r
337 FILE_NAME_LIST *Package;\r
338\r
339 if (OutputFileName == NULL || PackageListGuid == NULL || PackageFiles == NULL) {\r
340 return STATUS_ERROR;\r
341 }\r
342\r
343 //\r
344 // Open the output file for writing\r
345 //\r
346 if ((OutFptr = fopen (OutputFileName, "wb")) == NULL) {\r
347 Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");\r
348 goto Done;\r
349 }\r
350\r
351 //\r
352 // Write package list header\r
353 //\r
354 PackageListLen = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
355 Package = PackageFiles;\r
356 while (Package != NULL) {\r
357 PackageListLen += Package->Length;\r
358 Package = Package->Next;\r
359 }\r
360 fwrite (PackageListGuid, sizeof (UINT8), sizeof (EFI_GUID), OutFptr);\r
361 fwrite (&PackageListLen, sizeof (UINT8), sizeof (UINT32), OutFptr);\r
362\r
363 //\r
364 // Write packages\r
365 //\r
366 Package = PackageFiles;\r
367 while (Package != NULL) {\r
368 fwrite (Package->Data, sizeof (UINT8), Package->Length, OutFptr);\r
369 Package = Package->Next;\r
370 }\r
371\r
372Done:\r
373 if (OutFptr != NULL) {\r
374 fclose (OutFptr);\r
375 }\r
376\r
377 return STATUS_SUCCESS;\r
378}\r
379\r
380static\r
381void\r
382FreeGlobals (\r
383 VOID\r
384 )\r
385/*++\r
386\r
387Routine Description:\r
388\r
389 Free up an memory we allocated so we can exit cleanly\r
390\r
391Arguments:\r
392\r
393Returns: NA\r
394\r
395--*/\r
396{\r
397 FILE_NAME_LIST *Next;\r
398\r
399 //\r
400 // Free up input package file names\r
401 //\r
402 while (mGlobals.PackageFile != NULL) {\r
403 Next = mGlobals.PackageFile->Next;\r
404 if (mGlobals.PackageFile->Data != NULL) {\r
405 free (mGlobals.PackageFile->Data);\r
406 }\r
407 free (mGlobals.PackageFile);\r
408 mGlobals.PackageFile = Next;\r
409 }\r
410}\r
411\r
412static\r
413void\r
414DumpRawBytes (\r
415 FILE *OutFptr,\r
416 UINT8 *Buffer,\r
417 int Count,\r
418 int Indent\r
419 )\r
420/*++\r
421\r
422Routine Description:\r
423\r
424 Dump buffer data into output file.\r
425\r
426Arguments:\r
427\r
428 OutFptr - FILE pointer to output file.\r
429 Buffer - the buffer to dump\r
430 Count - number of bytes to dump\r
431 Indent - indent at each line start\r
432\r
433Returns:\r
434\r
435 Nothing.\r
436\r
437--*/\r
438{\r
439 int Counter;\r
440 int Count2;\r
441 UINT16 *Ptr16;\r
442\r
443 Ptr16 = (UINT16 *) Buffer;\r
444 Count2 = Count - (Count & 0x1);\r
445\r
446 for (Counter = 0; Counter < Count2; Counter += 2) {\r
447 if ((Counter & 0xF) == 0) {\r
448 if (Counter == 0) {\r
449 fprintf (OutFptr, "%*c", Indent, ' ');\r
450 } else {\r
451 fprintf (OutFptr, "\n%*c", Indent, ' ');\r
452 }\r
453 }\r
454\r
455 fprintf (OutFptr, "0x%04X, ", (unsigned int) *Ptr16);\r
456 Ptr16++;\r
457 }\r
458\r
459 //\r
460 // Handle the last byte\r
461 //\r
462 if ((Count & 0x1) != 0) {\r
463 if ((Counter & 0xF) == 0) {\r
464 if (Counter == 0) {\r
465 fprintf (OutFptr, "%*c", Indent, ' ');\r
466 } else {\r
467 fprintf (OutFptr, "\n%*c", Indent, ' ');\r
468 }\r
469 }\r
470\r
471 fprintf (OutFptr, "0x%04X, ", (unsigned int) (*Ptr16 & 0xff));\r
472 }\r
473\r
474 fprintf (OutFptr, "\n");\r
475}\r
476\r
477static\r
478STATUS\r
479LoadPackage (\r
480 FILE_NAME_LIST *NameList\r
481 )\r
482/*++\r
483\r
484Routine Description:\r
485\r
486 Process the command line arguments\r
487\r
488Arguments:\r
489\r
490 NameList - the FILE_NAME_LIST linked list node\r
491\r
492Returns:\r
493\r
494 STATUS_SUCCESS - if successful\r
495 STATUS_ERROR - otherwise\r
496\r
497--*/\r
498{\r
499 STATUS Status;\r
500 FILE *InFptr;\r
501 UINT32 BufferSize;\r
502 UINT8 *Buffer;\r
503 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
504 EFI_IFR_FORM_SET *FormSet;\r
505\r
506 Status = STATUS_SUCCESS;\r
507 if (NameList == NULL) {\r
508 return STATUS_ERROR;\r
509 }\r
510\r
511 //\r
512 // Try to open the package file\r
513 //\r
514 if ((InFptr = fopen (NameList->FileName, "rb")) == NULL) {\r
515 Error (NULL, 0, 0, NameList->FileName, "failed to open input file for read");\r
516 return STATUS_ERROR;\r
517 }\r
518\r
519 //\r
520 // Get the file size, then allocate a buffer and read in the file contents.\r
521 //\r
522 fseek (InFptr, 0, SEEK_END);\r
523 BufferSize = (UINT32) ftell (InFptr);\r
524 fseek (InFptr, 0, SEEK_SET);\r
525 Buffer = (UINT8 *) malloc (BufferSize);\r
526 if (Buffer == NULL) {\r
527 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
528 goto Done;\r
529 }\r
530\r
531 if (fread (Buffer, sizeof (UINT8), BufferSize, InFptr) != BufferSize) {\r
532 Error (NULL, 0, 0, NameList->FileName, "error reading file contents");\r
533 Status = STATUS_ERROR;\r
534 goto Done;\r
535 }\r
536\r
537 NameList->Length = BufferSize;\r
538 NameList->Data = Buffer;\r
539\r
540 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
541 NameList->PackageType = PackageHeader->Type;\r
542\r
543 if (!mGlobals.GuidSpecified && NameList->PackageType == EFI_HII_PACKAGE_FORMS) {\r
544 FormSet = (EFI_IFR_FORM_SET *) (Buffer + sizeof (EFI_HII_PACKAGE_HEADER));\r
545 memcpy (&mGlobals.Guid, &FormSet->Guid, sizeof (EFI_GUID));\r
546 mGlobals.GuidSpecified = TRUE;\r
547 }\r
548\r
549Done:\r
550 fclose (InFptr);\r
551\r
552 return Status;\r
553}\r
554\r
555\r
556static\r
557STATUS\r
558ProcessArgs (\r
559 int Argc,\r
560 char *Argv[]\r
561 )\r
562/*++\r
563\r
564Routine Description:\r
565\r
566 Process the command line arguments\r
567\r
568Arguments:\r
569\r
570 As per standard C main()\r
571\r
572Returns:\r
573\r
574 STATUS_SUCCESS - if successful\r
575 STATUS_ERROR - otherwise\r
576\r
577--*/\r
578{\r
579 FILE_NAME_LIST *NewList;\r
580 STATUS Status;\r
581\r
582 Status = STATUS_SUCCESS;\r
583 memset ((void *) &mGlobals, 0, sizeof (mGlobals));\r
584\r
585 //\r
586 // Skip program name\r
587 //\r
588 Argc--;\r
589 Argv++;\r
590\r
591 if (Argc == 0) {\r
592 Usage ();\r
593 return STATUS_ERROR;\r
594 }\r
595\r
596 if (_stricmp (Argv[0], "-h") == 0 || _stricmp (Argv[0], "-?") == 0) {\r
597 Usage ();\r
598 return STATUS_ERROR;\r
599 }\r
600\r
601 //\r
602 // Process until no more args.\r
603 //\r
604 while (Argc > 0) {\r
605 if (_stricmp (Argv[0], "-rc") == 0) {\r
606 Argc--;\r
607 Argv++;\r
608\r
609 if (Argc == 0) {\r
610 Error (UTILITY_NAME, 0, 0, "mising HII resource file name", NULL);\r
611 Status = STATUS_ERROR;\r
612 goto Done;\r
613 }\r
614\r
615 strcpy (mGlobals.ResourceFileName, Argv[0]);\r
616 mGlobals.Mode |= MODE_CREATE_HII_RESOURCE_FILE;\r
617\r
618 } else if (_stricmp (Argv[0], "-hii") == 0) {\r
619 Argc--;\r
620 Argv++;\r
621\r
622 if (Argc == 0) {\r
623 Error (UTILITY_NAME, 0, 0, "mising HII package list file name", NULL);\r
624 Status = STATUS_ERROR;\r
625 goto Done;\r
626 }\r
627\r
628 strcpy (mGlobals.PackageListFileName, Argv[0]);\r
629 mGlobals.Mode |= MODE_CREATE_HII_PACKAGE_LIST;\r
630\r
631 } else if (_stricmp (Argv[0], "-g") == 0) {\r
632 Argc--;\r
633 Argv++;\r
634\r
635 if (Argc == 0) {\r
636 Error (UTILITY_NAME, 0, 0, "mising package list GUID", NULL);\r
637 Status = STATUS_ERROR;\r
638 goto Done;\r
639 }\r
640\r
641 Status = StringToGuid (Argv[0], &mGlobals.Guid);\r
642 if (Status != STATUS_SUCCESS) {\r
643 goto Done;\r
644 }\r
645 mGlobals.GuidSpecified = TRUE;\r
646\r
647 } else {\r
648 //\r
649 // This is a package file\r
650 //\r
651 NewList = malloc (sizeof (FILE_NAME_LIST));\r
652 if (NewList == NULL) {\r
653 Error (UTILITY_NAME, 0, 0, "memory allocation failure", NULL);\r
654 Status = STATUS_ERROR;\r
655 goto Done;\r
656 }\r
657\r
658 memset (NewList, 0, sizeof (FILE_NAME_LIST));\r
659 strcpy (NewList->FileName, Argv[0]);\r
660\r
661 if (mGlobals.PackageFile == NULL) {\r
662 mGlobals.PackageFile = NewList;\r
663 } else {\r
664 mGlobals.LastPackageFile->Next = NewList;\r
665 }\r
666 mGlobals.LastPackageFile = NewList;\r
667\r
668 Status = LoadPackage (NewList);\r
669 if (Status != STATUS_SUCCESS) {\r
670 goto Done;\r
671 }\r
672 }\r
673\r
674 Argc--;\r
675 Argv++;\r
676 }\r
677\r
678 if (!mGlobals.GuidSpecified) {\r
679 Error (UTILITY_NAME, 0, 0, "please specify HII pakcage list GUID", NULL);\r
680 Status = STATUS_ERROR;\r
681 }\r
682\r
683Done:\r
684 if (Status != STATUS_SUCCESS) {\r
685 FreeGlobals ();\r
686 }\r
687\r
688 return Status;\r
689}\r
690\r
691static\r
692void\r
693Usage (\r
694 VOID\r
695 )\r
696/*++\r
697\r
698Routine Description:\r
699\r
700 Print usage information for this utility.\r
701\r
702Arguments:\r
703\r
704 None.\r
705\r
706Returns:\r
707\r
708 Nothing.\r
709\r
710--*/\r
711{\r
712 int i;\r
713 const char *Str[] = {\r
714 UTILITY_NAME" "UTILITY_VERSION" - UEFI HII Package List Utility",\r
715 " Copyright (C), 2008 Intel Corporation",\r
716 \r
717#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )\r
718 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,\r
719#endif\r
720 "",\r
721 "Usage:",\r
722 " "UTILITY_NAME" [OPTION] PACKAGE [PACKAGE [...]]",\r
723 "Description:",\r
724 " Merge HII package files into a single HII Package List.",\r
725 "Options:",\r
726 " -rc FileName write output to PE/COFF Resource Script file",\r
727 " -hii FileName write output to binary Package List file",\r
728 " -g GUID use GUID for the HII Package List Guid",\r
729 "",\r
730 "PACKAGE is the raw binary HII package file generated by StrGather or",\r
731 "VfrCompiler which named as *.hpk. For example, merge a Form package and",\r
732 "a String package into one HII package list:",\r
733 " \""UTILITY_NAME" -rc Sample.rc -hii Sample.hii \\",\r
734 " -g 12345678-1234-1234-1234-123456789abc Vfr.hpk Strings.hpk\"",\r
735 NULL\r
736 };\r
737 for (i = 0; Str[i] != NULL; i++) {\r
738 fprintf (stdout, "%s\n", Str[i]);\r
739 }\r
740}\r