]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/GenFdImage/GenFdImageLib.c
Clean up some data type mismatches.
[mirror_edk2.git] / Tools / Source / TianoTools / GenFdImage / GenFdImageLib.c
1 /*++
2
3 Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
10 Intel Corporation.
11
12
13 Module Name:
14
15 GenFdImageLib.C
16
17 Abstract:
18
19 This file contains the functions required to generate
20 the Firmware Device
21
22 --*/
23
24 //
25 // Coded to EFI 2.0 Coding Standards
26 //
27 //
28 // Include file in build
29 //
30 #include "GenFdImage.h"
31
32 //
33 // Global declarations
34 //
35 UINTN ValidLineNum = 0;
36 UINTN NumFvFiles = 0;
37
38 static UINT64 LastAddress = 0;
39
40 CHAR8 **TokenStr;
41 CHAR8 **OrgStrTokPtr;
42
43 FDINFO *FdInfo;
44 FDINFO *OrgFdInfoPtr;
45
46 FVINFO **FvInfo;
47 FVINFO **OrgFvInfoPtr;
48
49 //
50 // Internal Functions
51 //
52 INTN
53 CompareItems (
54 IN const VOID *Arg1,
55 IN const VOID *Arg2
56 )
57 /*++
58
59 Routine Description:
60
61 This function is used by qsort to sort the Fv list based on FvBaseAddress
62
63 Arguments:
64
65 Arg1
66 Arg2
67
68 Returns:
69
70 None
71
72 --*/
73 // GC_TODO: Arg1 - add argument and description to function comment
74 // GC_TODO: Arg2 - add argument and description to function comment
75 {
76 if ((*(FVINFO **) Arg1)->FvBaseAddress > (*(FVINFO **) Arg2)->FvBaseAddress) {
77 return 1;
78 } else if ((*(FVINFO **) Arg1)->FvBaseAddress < (*(FVINFO **) Arg2)->FvBaseAddress) {
79 return -1;
80 } else {
81 return 0;
82 }
83 }
84
85 VOID
86 BuildTokenList (
87 IN CHAR8 *Token
88 )
89 /*++
90
91 Routine Description:
92
93 This function builds the token list in an array which will be parsed later
94
95 Arguments:
96
97 Token String,
98
99 Returns:
100
101 None
102
103 --*/
104 {
105 strcpy (*TokenStr, Token);
106 TokenStr++;
107 }
108
109 VOID
110 TrimLine (
111 IN CHAR8 *Line
112 )
113 /*++
114
115 Routine Description:
116
117 This function cleans up the line by removing all whitespace and
118 comments.
119
120 Arguments:
121
122 Line String,
123
124 Returns:
125
126 None
127
128 --*/
129 {
130 CHAR8 TmpLine[FILE_NAME_SIZE];
131 CHAR8 c;
132 CHAR8 *Ptr0;
133
134 UINTN i;
135 UINTN j;
136
137 //
138 // Change '#' to '//' for Comment style
139 //
140 // if((Ptr0=strchr(Line, '#')) != NULL) {
141 //
142 if ((Ptr0 = strstr (Line, "//")) != NULL) {
143 Line[Ptr0 - Line] = 0;
144 }
145
146 i = 0;
147 j = 0;
148 while ((c = Line[i]) != 0) {
149 if ((c != ' ') && (c != '\t') && (c != '\n')) {
150 TmpLine[j++] = c;
151 }
152
153 i++;
154 }
155
156 TmpLine[j] = 0;
157 strcpy (Line, TmpLine);
158 }
159
160 VOID
161 ValidLineCount (
162 IN FILE *Fp
163 )
164 /*++
165
166 Routine Description:
167
168 This function calculates number of valid lines in a input file.
169
170 Arguments:
171
172 Fp Pointer to a file handle which has been opened.
173
174 Returns:
175
176 None
177
178 --*/
179 {
180 CHAR8 Buff[FILE_NAME_SIZE];
181
182 while (fgets (Buff, sizeof (Buff), Fp)) {
183 TrimLine (Buff);
184 if (Buff[0] == 0) {
185 continue;
186 }
187
188 ValidLineNum++;
189 }
190 }
191
192 VOID
193 ParseInputFile (
194 IN FILE *Fp
195 )
196 /*++
197
198 Routine Description:
199
200 This function parses the input file and tokenizes the string
201
202 Arguments:
203
204 Fp Pointer to a file handle which has been opened.
205
206 Returns:
207
208 None
209
210 --*/
211 {
212 CHAR8 *Token;
213 CHAR8 Buff[FILE_NAME_SIZE];
214 CHAR8 OrgLine[FILE_NAME_SIZE];
215 CHAR8 Str[FILE_NAME_SIZE];
216 CHAR8 Delimit[] = "=";
217
218 while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
219 strcpy (OrgLine, Buff);
220 TrimLine (Buff);
221
222 if (Buff[0] == 0) {
223 continue;
224 }
225
226 Token = strtok (Buff, Delimit);
227
228 while (Token != NULL) {
229 strcpy (Str, Token);
230 BuildTokenList (Str);
231 Token = strtok (NULL, Delimit);
232 }
233 }
234 }
235
236 EFI_STATUS
237 InitializeComps (
238 VOID
239 )
240 /*++
241
242 Routine Description:
243
244 This function intializes the relevant global variable
245 used to store the information retrieved from the INF file.
246
247 Arguments:
248
249 None
250
251 Returns:
252
253 EFI_STATUS
254
255 --*/
256 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
257 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
258 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
259 // GC_TODO: EFI_SUCCESS - add return value to function comment
260 {
261 UINTN Index;
262
263 FdInfo = malloc (sizeof (FDINFO));
264
265 if (FdInfo == NULL) {
266 printf ("ERROR: allocating memory (struct FDINFO) in"" function InitializeComps.\n");
267 return EFI_OUT_OF_RESOURCES;
268 }
269
270 OrgFdInfoPtr = FdInfo;
271
272 FvInfo = malloc (sizeof (INTN) * NumFvFiles);
273
274 if (FvInfo == NULL) {
275 printf ("ERROR: allocating memory (INTN * NumFvFiles) in"" function InitializeComps.\n");
276 return EFI_OUT_OF_RESOURCES;
277 }
278
279 OrgFvInfoPtr = FvInfo;
280
281 for (Index = 0; Index < NumFvFiles; Index++) {
282 *FvInfo = malloc (sizeof (FVINFO));
283
284 if (*FvInfo == NULL) {
285 printf ("ERROR: allocating memory (FVINFO) in"" function InitializeComps.\n");
286 return EFI_OUT_OF_RESOURCES;
287 }
288
289 memset (*FvInfo, 0, sizeof (FVINFO));
290 FvInfo++;
291 }
292
293 FvInfo = OrgFvInfoPtr;
294
295 return EFI_SUCCESS;
296 }
297
298 VOID
299 InitializeInFileInfo (
300 VOID
301 )
302 /*++
303
304 Routine Description:
305
306 This function intializes the relevant global variable
307 used to store the information retrieved from the INF file.
308
309 Arguments:
310
311 None
312
313 Returns:
314
315 None
316
317 --*/
318 {
319 UINTN OptionFlag;
320
321 UINT64 StringValue;
322
323 OptionFlag = 0;
324 TokenStr = OrgStrTokPtr;
325
326 while (*TokenStr != NULL) {
327 if (stricmp (*TokenStr, "[options]") == 0) {
328 OptionFlag = 1;
329 }
330
331 if (OptionFlag) {
332 if (stricmp (*TokenStr, "EFI_FV_BASE_ADDRESS") == 0) {
333 *TokenStr++;
334 if (AsciiStringToUint64 (
335 *TokenStr,
336 FALSE,
337 &StringValue
338 ) != EFI_SUCCESS) {
339 printf ("\nERROR: Cannot determine the FV base address.");
340 return ;
341 }
342 (*FvInfo)->FvBaseAddress = StringValue;
343 } else if (stricmp (*TokenStr, "EFI_FV_FILE_NAME") == 0) {
344 *TokenStr++;
345 strcpy ((*FvInfo)->FvFile, *TokenStr);
346 }
347 }
348
349 TokenStr++;
350 }
351 }
352
353 EFI_STATUS
354 GetFvRelatedInfoFromInfFile (
355 IN CHAR8 *FileName
356 )
357 /*++
358
359 Routine Description:
360
361 This function reads the input file, parses it and create a list of tokens
362 which are parsed and used, to intialize the data related to the Firmware
363 Volume.
364
365 Arguments:
366
367 FileName FileName which needed to be read to parse data
368
369 Returns:
370
371 EFI_STATUS
372
373 --*/
374 // GC_TODO: EFI_ABORTED - add return value to function comment
375 // GC_TODO: EFI_ABORTED - add return value to function comment
376 // GC_TODO: EFI_SUCCESS - add return value to function comment
377 {
378 FILE *Fp;
379
380 UINTN Index;
381
382 Fp = fopen (FileName, "r");
383
384 if (Fp == NULL) {
385 printf ("Error in opening %s file\n", FileName);
386 return EFI_ABORTED;
387 }
388
389 ValidLineCount (Fp);
390
391 if (ValidLineNum == 0) {
392 printf ("\nFile doesn't contain any valid informations");
393 return EFI_ABORTED;
394 }
395
396 TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum));
397 memset (TokenStr, 0, sizeof (UINTN) * (2 * ValidLineNum));
398 OrgStrTokPtr = TokenStr;
399
400 for (Index = 0; Index < (2 * ValidLineNum); Index++) {
401 *TokenStr = (CHAR8 *) malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
402 memset (*TokenStr, 0, FILE_NAME_SIZE);
403 TokenStr++;
404 }
405
406 *TokenStr = NULL;
407 TokenStr = OrgStrTokPtr;
408 fseek (Fp, 0L, SEEK_SET);
409
410 ParseInputFile (Fp);
411 InitializeInFileInfo ();
412
413 if (Fp) {
414 fclose (Fp);
415 }
416
417 return EFI_SUCCESS;
418 }
419
420 EFI_STATUS
421 WriteFwBinary (
422 IN CHAR8 *FileName,
423 IN UINT64 StartAddress,
424 IN UINT64 Size,
425 IN UINT8 *Buffer
426 )
427 /*++
428
429 Routine Description:
430
431 This function reads the input file, parses it and creates a list of tokens
432 which are parsed and used to intialize the data related to the Firmware
433 Volume.
434
435 Arguments:
436
437 FileName FileName which needed to be read to parse data
438 StartAddress This will set the file position.
439 Size Size in bytes needed to be written
440 Buffer Buffer needed to e written
441
442 Returns:
443
444 EFI_STATUS
445
446 --*/
447 // GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
448 // GC_TODO: EFI_ABORTED - add return value to function comment
449 // GC_TODO: EFI_SUCCESS - add return value to function comment
450 {
451 FILE *Fp;
452
453 UINTN NumByte;
454
455 Fp = fopen (FileName, "a+b");
456
457 if (Fp == NULL) {
458 printf ("\nERROR:Error in opening file %s ", FileName);
459 return EFI_INVALID_PARAMETER;
460 }
461
462 fseek (Fp, (UINTN) StartAddress, SEEK_SET);
463 NumByte = fwrite ((VOID *) Buffer, sizeof (UINT8), (UINTN) Size, Fp);
464
465 //
466 // Check to ensure that buffer has been copied successfully
467 //
468 if (NumByte != Size) {
469 printf ("\nERROR: Error in copying the buffer into file");
470 return EFI_ABORTED;
471 }
472
473 if (Fp) {
474 fclose (Fp);
475 }
476
477 return EFI_SUCCESS;
478 }
479
480 EFI_STATUS
481 BuildFirmwareDeviceBinaryFromFwVolumes (
482 IN UINT64 FvBaseAddress,
483 IN CHAR8 *FvFileName,
484 IN CHAR8 *FdFileName
485 )
486 /*++
487
488 Routine Description:
489
490 This function reads the input file, parses it and creates a list of tokens
491 which are parsed and used to intialize the data related to the Firmware
492 Volume.
493
494 Arguments:
495
496 FvBaseAddress Base Address. This info is retrieved from INF file
497 FvFileName InputFileName
498 FdFileName Output File Name
499
500 Returns:
501
502 EFI_STATUS
503
504 --*/
505 // GC_TODO: EFI_ABORTED - add return value to function comment
506 // GC_TODO: EFI_ABORTED - add return value to function comment
507 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
508 // GC_TODO: EFI_ABORTED - add return value to function comment
509 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
510 // GC_TODO: EFI_SUCCESS - add return value to function comment
511 {
512 FILE *Fp;
513
514 UINT64 FileSize;
515 UINT64 NumByteRead;
516 UINT64 PadByteSize;
517 UINT64 BaseAddress;
518
519 UINTN Index;
520
521 UINT8 *Buffer;
522
523 EFI_STATUS Status;
524
525 static UINT64 StartAddress = 0;
526
527 Fp = fopen (FvFileName, "r+b");
528
529 if (Fp == NULL) {
530 printf ("\nERROR:Error in opening file %s", FvFileName);
531 return EFI_ABORTED;
532 }
533
534 BaseAddress = FdInfo->FdBaseAddress;
535
536 //
537 // Check if Base Address of Firmware Volume falls below the Base Address
538 // Firmware Device, if yes, then abort this process.
539 //
540 if (FvBaseAddress < BaseAddress) {
541 printf ("\nERROR: Firmware Volume Base Address falls below Firmware ""Device Address.\n");
542 return EFI_ABORTED;
543 }
544 //
545 // Check if there are any holes between two Firmware Volumes. If any holes
546 // exist, fill the hole with PadByted data.
547 //
548 if (FvBaseAddress > LastAddress) {
549 PadByteSize = (FvBaseAddress - LastAddress);
550 Buffer = malloc ((UINTN) PadByteSize);
551 if (Buffer == NULL) {
552 printf ("ERROR: allocating (Buffer) memory in"" function BuildFirmwareDeviceBinaryFromFwVolumes.\n");
553 return EFI_OUT_OF_RESOURCES;
554 }
555
556 for (Index = 0; Index < PadByteSize; Index++) {
557 *Buffer = FdInfo->PadValue;
558 Buffer++;
559 }
560
561 Buffer -= PadByteSize;
562 Status = WriteFwBinary (
563 FdFileName,
564 StartAddress,
565 (UINT64) PadByteSize,
566 Buffer
567 );
568
569 if (Buffer) {
570 free (Buffer);
571 }
572
573 if (Status != EFI_SUCCESS) {
574 printf ("\nERROR: Error in writing the binary image to file");
575 return Status;
576 }
577
578 StartAddress += PadByteSize;
579 LastAddress += PadByteSize;
580 }
581 //
582 // Proceed with next Firmware Volume updates
583 //
584 FileSize = _filelength (fileno (Fp));
585
586 if ((FvBaseAddress + FileSize) > (FdInfo->FdBaseAddress + FdInfo->FdSize)) {
587 printf (
588 "\nERROR:Unable to update Firmware Device. File %s is larger than \
589 available space.",
590 FvFileName
591 );
592 if (Fp) {
593 fclose (Fp);
594 }
595
596 return EFI_ABORTED;
597 }
598
599 Buffer = malloc ((UINTN) FileSize);
600
601 if (Buffer == NULL) {
602 printf ("Error in allocating buffer to read specific file\n");
603 return EFI_OUT_OF_RESOURCES;
604 }
605
606 NumByteRead = fread ((VOID *) Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
607
608 Status = WriteFwBinary (FdFileName, StartAddress, FileSize, Buffer);
609
610 if (Buffer) {
611 free ((VOID *) Buffer);
612 }
613
614 if (Fp) {
615 fclose (Fp);
616 }
617
618 if (Status != EFI_SUCCESS) {
619 printf ("\nERROR: Error in writing the binary image to file");
620 return Status;
621 }
622
623 StartAddress += NumByteRead;
624 LastAddress += FileSize;
625
626 return EFI_SUCCESS;
627 }
628
629 VOID
630 CleanUpMemory (
631 VOID
632 )
633 /*++
634
635 Routine Description:
636
637 This function cleans up any allocated buffer
638
639 Arguments:
640
641 None
642
643 Returns:
644
645 None
646
647 --*/
648 {
649 UINTN Index;
650
651 if (FdInfo) {
652 free (FdInfo);
653 }
654
655 FvInfo = OrgFvInfoPtr;
656
657 if (FvInfo) {
658 for (Index = 0; Index < NumFvFiles; Index++) {
659 if (*FvInfo) {
660 free (*FvInfo);
661 }
662
663 FvInfo++;
664 }
665
666 FvInfo = OrgFvInfoPtr;
667 free (FvInfo);
668 }
669 }
670
671 EFI_STATUS
672 GenerateFdImage (
673 IN UINT64 BaseAddress,
674 IN UINT64 Size,
675 IN UINT8 PadByte,
676 IN CHAR8 *OutFile,
677 IN CHAR8 **FileList
678 )
679 /*++
680
681 Routine Description:
682
683 This function reads the input file, parses it and creates a list of tokens
684 which are parsed and used to intialize the data related to the Firmware
685 Volume.
686
687 Arguments:
688
689 BaseAddress Base Address for this Firmware Device
690 Size, Total Size of the Firmware Device
691 PadByte Pad byte data
692 OutFile Output File Name
693 FileList File List pointer to INF file names.
694
695 Returns:
696
697 EFI_STATUS
698
699 --*/
700 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
701 // GC_TODO: EFI_ABORTED - add return value to function comment
702 // GC_TODO: EFI_ABORTED - add return value to function comment
703 // GC_TODO: EFI_SUCCESS - add return value to function comment
704 {
705 EFI_STATUS Status;
706
707 UINTN Index;
708 UINTN PadSize;
709 UINTN FileSize;
710 UINTN NumByte;
711
712 CHAR8 **InFile;
713
714 FILE *Fp;
715
716 UINT8 *Buffer;
717
718 //
719 // If any previous Firmware Device existed,
720 // make it to 0 bytes
721 //
722 if ((Fp = fopen (OutFile, "w")) != NULL) {
723 fclose (Fp);
724 }
725
726 InFile = FileList;
727
728 while (*InFile != NULL) {
729 NumFvFiles++;
730 InFile++;
731 }
732
733 InitializeComps ();
734
735 //
736 // Restore the orginal pointers
737 //
738 FvInfo = OrgFvInfoPtr;
739 InFile = FileList;
740
741 while (*InFile != NULL) {
742 strcpy ((*FvInfo)->FvInfoFile, *InFile);
743 Status = GetFvRelatedInfoFromInfFile (*InFile);
744
745 if (Status != EFI_SUCCESS) {
746 printf ("\nERROR: Error occurred in processsing INF file");
747 CleanUpMemory ();
748 return Status;
749 }
750
751 InFile++;
752 FvInfo++;
753 }
754
755 FdInfo->FdSize = Size;
756 FdInfo->FdBaseAddress = BaseAddress;
757 FdInfo->PadValue = PadByte;
758 FvInfo = OrgFvInfoPtr;
759 strcpy (FdInfo->OutFileName, OutFile);
760
761 for (Index = 0; Index < NumFvFiles; Index++) {
762 Status = GenerateFvImage ((*FvInfo)->FvInfoFile);
763
764 if (Status != EFI_SUCCESS) {
765 CleanUpMemory ();
766 return Status;
767 }
768
769 FvInfo++;
770 }
771
772 FvInfo = OrgFvInfoPtr;
773
774 //
775 // Sort the Firmware Volume information. Firmware Volume with lower
776 // base addresses will be processed first and higher base address one
777 // will be processed later.
778 //
779 qsort ((VOID *) FvInfo, NumFvFiles, sizeof (FVINFO *), CompareItems);
780
781 LastAddress = (*FvInfo)->FvBaseAddress;
782
783 for (Index = 0; Index < NumFvFiles; Index++) {
784 Status = BuildFirmwareDeviceBinaryFromFwVolumes (
785 (*FvInfo)->FvBaseAddress,
786 (*FvInfo)->FvFile,
787 FdInfo->OutFileName
788 );
789 if (Status != EFI_SUCCESS) {
790 CleanUpMemory ();
791 return Status;
792 }
793
794 FvInfo++;
795 }
796 //
797 // Check if any space left after copying data from all Firmware Volumes
798 // If yes, then fill those location with PadValue.
799 //
800 if ((FdInfo->FdBaseAddress + Size) > LastAddress) {
801
802 PadSize = (UINTN) ((FdInfo->FdBaseAddress + FdInfo->FdSize) - LastAddress);
803 Buffer = malloc (PadSize);
804
805 if (Buffer == NULL) {
806 printf ("\nERROR: allocating PadSize memory in function GenerateFdImage.\n");
807 CleanUpMemory ();
808 return EFI_OUT_OF_RESOURCES;
809 }
810
811 for (Index = 0; Index < PadSize; Index++) {
812 *Buffer = FdInfo->PadValue;
813 Buffer++;
814 }
815
816 Buffer -= PadSize;
817
818 Fp = fopen (OutFile, "a+b");
819
820 if (Fp == NULL) {
821 printf ("\nERROR:Opening file %s", OutFile);
822 CleanUpMemory ();
823 return EFI_ABORTED;
824 }
825
826 FileSize = _filelength (fileno (Fp));
827 fseek (Fp, FileSize, SEEK_SET);
828 NumByte = fwrite (Buffer, sizeof (UINT8), PadSize, Fp);
829
830 if (Buffer) {
831 free (Buffer);
832 }
833
834 fclose (Fp);
835
836 if (NumByte != (sizeof (UINT8) * PadSize)) {
837 printf ("\nERROR: Copying data from buffer to File %s ", OutFile);
838 CleanUpMemory ();
839 return EFI_ABORTED;
840 }
841 }
842 //
843 // Clean up all the memory which has been allocated so far.
844 //
845 CleanUpMemory ();
846
847 return EFI_SUCCESS;
848 }