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