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