1 /** @file
2 This contains some useful functions for accessing files.
3 
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <assert.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include "CommonLib.h"
14 #include "MemoryFile.h"
15 
16 
17 //
18 // Local (static) function prototypes
19 //
20 STATIC
21 VOID
22 CheckMemoryFileState (
23   IN EFI_HANDLE InputMemoryFile
24   );
25 
26 //
27 // Function implementations
28 //
29 
30 EFI_STATUS
GetMemoryFile(IN CHAR8 * InputFileName,OUT EFI_HANDLE * OutputMemoryFile)31 GetMemoryFile (
32   IN CHAR8       *InputFileName,
33   OUT EFI_HANDLE *OutputMemoryFile
34   )
35 /*++
36 
37 Routine Description:
38 
39   This opens a file, reads it into memory and returns a memory file
40   object.
41 
42 Arguments:
43 
44   InputFile          Memory file image.
45   OutputMemoryFile   Handle to memory file
46 
47 Returns:
48 
49   EFI_STATUS
50   OutputMemoryFile is valid if !EFI_ERROR
51 
52 --*/
53 {
54   EFI_STATUS  Status;
55   CHAR8       *InputFileImage;
56   UINT32      BytesRead;
57   MEMORY_FILE *NewMemoryFile;
58 
59   Status = GetFileImage (InputFileName, &InputFileImage, &BytesRead);
60   if (EFI_ERROR (Status)) {
61     return Status;
62   }
63 
64   NewMemoryFile = malloc (sizeof (*NewMemoryFile));
65   if (NewMemoryFile == NULL) {
66     free (InputFileImage);
67     return EFI_OUT_OF_RESOURCES;
68   }
69 
70   NewMemoryFile->FileImage           = InputFileImage;
71   NewMemoryFile->CurrentFilePointer  = InputFileImage;
72   NewMemoryFile->Eof                 = InputFileImage + BytesRead;
73 
74   *OutputMemoryFile = (EFI_HANDLE)NewMemoryFile;
75 
76   CheckMemoryFileState (*OutputMemoryFile);
77 
78   return EFI_SUCCESS;
79 }
80 
81 
82 EFI_STATUS
FreeMemoryFile(IN EFI_HANDLE InputMemoryFile)83 FreeMemoryFile (
84   IN EFI_HANDLE InputMemoryFile
85   )
86 /*++
87 
88 Routine Description:
89 
90   Frees all memory associated with the input memory file.
91 
92 Arguments:
93 
94   InputMemoryFile   Handle to memory file
95 
96 Returns:
97 
98   EFI_STATUS
99 
100 --*/
101 {
102   MEMORY_FILE *MemoryFile;
103 
104   CheckMemoryFileState (InputMemoryFile);
105 
106   MemoryFile = (MEMORY_FILE*)InputMemoryFile;
107 
108   free (MemoryFile->FileImage);
109 
110   //
111   // Invalidate state of MEMORY_FILE structure to catch invalid usage.
112   //
113   memset (MemoryFile, 0xcc, sizeof (*MemoryFile));
114   MemoryFile->Eof -= 1;
115 
116   free (MemoryFile);
117 
118   return EFI_SUCCESS;
119 }
120 
121 
122 CHAR8 *
ReadMemoryFileLine(IN EFI_HANDLE InputMemoryFile)123 ReadMemoryFileLine (
124   IN EFI_HANDLE     InputMemoryFile
125   )
126 /*++
127 
128 Routine Description:
129 
130   This function reads a line from the memory file.  The newline characters
131   are stripped and a null terminated string is returned.
132 
133   If the string pointer returned is non-NULL, then the caller must free the
134   memory associated with this string.
135 
136 Arguments:
137 
138   InputMemoryFile   Handle to memory file
139 
140 Returns:
141 
142   NULL if error or EOF
143   NULL character termincated string otherwise (MUST BE FREED BY CALLER)
144 
145 --*/
146 {
147   CHAR8       *EndOfLine;
148   UINTN       CharsToCopy;
149   MEMORY_FILE *InputFile;
150   UINTN       BytesToEof;
151   CHAR8       *OutputString;
152 
153   //
154   // Verify input parameters are not null
155   //
156   CheckMemoryFileState (InputMemoryFile);
157 
158   InputFile = (MEMORY_FILE*)InputMemoryFile;
159 
160   //
161   // Check for end of file condition
162   //
163   if (InputFile->CurrentFilePointer >= InputFile->Eof) {
164     return NULL;
165   }
166 
167   //
168   // Determine the number of bytes remaining until the EOF
169   //
170   BytesToEof = InputFile->Eof - InputFile->CurrentFilePointer;
171 
172   //
173   // Find the next newline char
174   //
175   EndOfLine = memchr (InputFile->CurrentFilePointer, '\n', BytesToEof);
176 
177   //
178   // Determine the number of characters to copy.
179   //
180   if (EndOfLine == 0) {
181     //
182     // If no newline found, copy to the end of the file.
183     //
184     CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
185   } else {
186     //
187     // Newline found in the file.
188     //
189     CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;
190   }
191 
192   OutputString = malloc (CharsToCopy + 1);
193   if (OutputString == NULL) {
194     return NULL;
195   }
196 
197   //
198   // Copy the line.
199   //
200   memcpy (OutputString, InputFile->CurrentFilePointer, CharsToCopy);
201 
202   //
203   // Add the null termination over the 0x0D
204   //
205   if (OutputString[CharsToCopy - 1] == '\r') {
206 
207     OutputString[CharsToCopy - 1] = '\0';
208 
209   } else {
210 
211     OutputString[CharsToCopy] = '\0';
212 
213   }
214 
215   //
216   // Increment the current file pointer (include the 0x0A)
217   //
218   InputFile->CurrentFilePointer += CharsToCopy + 1;
219   if (InputFile->CurrentFilePointer > InputFile->Eof) {
220     InputFile->CurrentFilePointer = InputFile->Eof;
221   }
222   CheckMemoryFileState (InputMemoryFile);
223 
224   //
225   // Return the string
226   //
227   return OutputString;
228 }
229 
230 
231 STATIC
232 VOID
CheckMemoryFileState(IN EFI_HANDLE InputMemoryFile)233 CheckMemoryFileState (
234   IN EFI_HANDLE InputMemoryFile
235   )
236 {
237   MEMORY_FILE *MemoryFile;
238 
239   assert (InputMemoryFile != NULL);
240 
241   MemoryFile = (MEMORY_FILE*)InputMemoryFile;
242 
243   assert (MemoryFile->FileImage != NULL);
244   assert (MemoryFile->CurrentFilePointer != NULL);
245   assert (MemoryFile->Eof != NULL);
246   assert (MemoryFile->Eof >= MemoryFile->FileImage);
247   assert (MemoryFile->CurrentFilePointer >= MemoryFile->FileImage);
248   assert (MemoryFile->CurrentFilePointer <= MemoryFile->Eof);
249 }
250 
251 
252