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