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