1 /** @file
2   Library functions that perform file IO. Memory buffer, file system, and
3   fimrware volume operations are supproted.
4 
5   Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
6   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
7 
8   SPDX-License-Identifier: BSD-2-Clause-Patent
9 
10   Basic support for opening files on different device types. The device string
11   is in the form of DevType:Path. Current DevType is required as there is no
12   current mounted device concept of current working directory concept implement
13   by this library.
14 
15   Device names are case insensative and only check the leading characters for
16   unique matches. Thus the following are all the same:
17     LoadFile0:
18     l0:
19     L0:
20     Lo0:
21 
22   Supported Device Names:
23   A0x1234:0x12 - A memory buffer starting at address 0x1234 for 0x12 bytes
24   l1:          - EFI LoadFile device one.
25   B0:          - EFI BlockIo zero.
26   fs3:         - EFI Simple File System device 3
27   Fv2:         - EFI Firmware VOlume device 2
28   1.2.3.4:name - TFTP IP and file name
29 
30 **/
31 
32 #ifndef __EFI_FILE_LIB_H__
33 #define __EFI_FILE_LIB_H__
34 
35 #include <PiDxe.h>
36 #include <Protocol/FirmwareVolume2.h>
37 #include <Protocol/FirmwareVolumeBlock.h>
38 #include <Protocol/BlockIo.h>
39 #include <Protocol/LoadFile.h>
40 #include <Protocol/LoadFile.h>
41 #include <Protocol/SimpleFileSystem.h>
42 #include <Guid/FileInfo.h>
43 #include <Guid/FileSystemInfo.h>
44 
45 #define MAX_PATHNAME    0x200
46 
47 /// Type of the file that has been opened
48 typedef enum {
49   EfiOpenLoadFile,
50   EfiOpenMemoryBuffer,
51   EfiOpenFirmwareVolume,
52   EfiOpenFileSystem,
53   EfiOpenBlockIo,
54   EfiOpenTftp,
55   EfiOpenMaxValue
56 } EFI_OPEN_FILE_TYPE;
57 
58 
59 /// Public information about the open file
60 typedef struct {
61   UINTN                         Version;          // Common information
62   EFI_OPEN_FILE_TYPE            Type;
63   EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
64   EFI_STATUS                    LastError;
65   EFI_HANDLE                    EfiHandle;
66   CHAR8                         *DeviceName;
67   CHAR8                         *FileName;
68 
69   UINT64                        CurrentPosition;  // Information for Seek
70   UINT64                        MaxPosition;
71 
72   UINTN                         BaseOffset;       // Base offset for hexdump command
73 
74   UINTN                         Size;             // Valid for all types other than l#:
75   UINT8                         *Buffer;          // Information valid for A#:
76 
77   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;              // Information valid for Fv#:
78   EFI_GUID                      FvNameGuid;
79   EFI_SECTION_TYPE              FvSectionType;
80   EFI_FV_FILETYPE               FvType;
81   EFI_FV_FILE_ATTRIBUTES        FvAttributes;
82 
83   EFI_PHYSICAL_ADDRESS          FvStart;
84   UINTN                         FvSize;
85   UINTN                         FvHeaderSize;
86 
87   EFI_FILE                      *FsFileHandle;    // Information valid for Fs#:
88   EFI_FILE_SYSTEM_INFO          *FsInfo;
89   EFI_FILE_INFO                 *FsFileInfo;
90   EFI_BLOCK_IO_MEDIA            *FsBlockIoMedia;  // Information valid for Fs#: or B#:
91   EFI_BLOCK_IO_PROTOCOL         *FsBlockIo;       // Information valid for Fs#: or B#:
92 
93   UINTN                         DiskOffset;       // Information valid for B#:
94 
95   EFI_LOAD_FILE_PROTOCOL        *LoadFile;        // Information valid for l#:
96 
97   EFI_IP_ADDRESS                ServerIp;         // Information valid for t:
98   BOOLEAN                       IsDirty;
99   BOOLEAN                       IsBufferValid;
100 
101 } EFI_OPEN_FILE;
102 
103 
104 /// Type of Seek to perform
105 typedef enum {
106   EfiSeekStart,
107   EfiSeekCurrent,
108   EfiSeekEnd,
109   EfiSeekMax
110 } EFI_SEEK_TYPE;
111 
112 
113 /**
114   Open a device named by PathName. The PathName includes a device name and
115   path separated by a :. See file header for more details on the PathName
116   syntax. There is no checking to prevent a file from being opened more than
117   one type.
118 
119   SectionType is only used to open an FV. Each file in an FV contains multiple
120   sections and only the SectionType section is opened.
121 
122   For any file that is opened with EfiOpen() must be closed with EfiClose().
123 
124   @param  PathName    Path to parse to open
125   @param  OpenMode    Same as EFI_FILE.Open()
126   @param  SectionType Section in FV to open.
127 
128   @return NULL  Open failed
129   @return Valid EFI_OPEN_FILE handle
130 
131 **/
132 EFI_OPEN_FILE *
133 EfiOpen (
134   IN        CHAR8               *PathName,
135   IN  CONST UINT64              OpenMode,
136   IN  CONST EFI_SECTION_TYPE    SectionType
137   );
138 
139 EFI_STATUS
140 EfiCopyFile (
141   IN        CHAR8               *DestinationFile,
142   IN        CHAR8               *SourceFile
143   );
144 
145 /**
146   Use DeviceType and Index to form a valid PathName and try and open it.
147 
148   @param  DeviceType  Device type to open
149   @param  Index       Device Index to use. Zero relative.
150 
151   @return NULL  Open failed
152   @return Valid EFI_OPEN_FILE handle
153 
154 **/
155 EFI_OPEN_FILE  *
156 EfiDeviceOpenByType (
157   IN  EFI_OPEN_FILE_TYPE    DeviceType,
158   IN  UINTN                 Index
159   );
160 
161 
162 /**
163   Close a file handle opened by EfiOpen() and free all resources allocated by
164   EfiOpen().
165 
166   @param  Stream    Open File Handle
167 
168   @return EFI_INVALID_PARAMETER  Stream is not an Open File
169   @return EFI_SUCCESS            Steam closed
170 
171 **/
172 EFI_STATUS
173 EfiClose (
174   IN  EFI_OPEN_FILE     *Stream
175   );
176 
177 
178 /**
179   Return the size of the file represented by Stream. Also return the current
180   Seek position. Opening a file will enable a valid file size to be returned.
181   LoadFile is an exception as a load file size is set to zero.
182 
183   @param  Stream    Open File Handle
184 
185   @return 0         Stream is not an Open File or a valid LoadFile handle
186 
187 **/
188 UINTN
189 EfiTell (
190   IN  EFI_OPEN_FILE     *Stream,
191   OUT UINT64            *CurrentPosition   OPTIONAL
192   );
193 
194 
195 /**
196   Seek to the Offset location in the file. LoadFile and FV device types do
197   not support EfiSeek(). It is not possible to grow the file size using
198   EfiSeek().
199 
200   SeekType defines how use Offset to calculate the new file position:
201   EfiSeekStart  : Position = Offset
202   EfiSeekCurrent: Position is Offset bytes from the current position
203   EfiSeekEnd    : Only supported if Offset is zero to seek to end of file.
204 
205   @param  Stream    Open File Handle
206   @param  Offset    Offset to seek too.
207   @param  SeekType  Type of seek to perform
208 
209 
210   @return EFI_INVALID_PARAMETER  Stream is not an Open File
211   @return EFI_UNSUPPORTED        LoadFile and FV does not support Seek
212   @return EFI_NOT_FOUND          Seek past the end of the file.
213   @return EFI_SUCCESS            Steam closed
214 
215 **/
216 EFI_STATUS
217 EfiSeek (
218   IN  EFI_OPEN_FILE     *Stream,
219   IN  EFI_LBA           Offset,
220   IN  EFI_SEEK_TYPE     SeekType
221   );
222 
223 
224 /**
225   Read BufferSize bytes from the current location in the file. For load file
226   and FV case you must read the entire file.
227 
228   @param  Stream      Open File Handle
229   @param  Buffer      Caller allocated buffer.
230   @param  BufferSize  Size of buffer in bytes.
231 
232 
233   @return EFI_SUCCESS           Stream is not an Open File
234   @return EFI_END_OF_FILE Tried to read past the end of the file
235   @return EFI_INVALID_PARAMETER Stream is not an open file handle
236   @return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read
237   @return "other"               Error returned from device read
238 
239 **/
240 EFI_STATUS
241 EfiRead (
242   IN  EFI_OPEN_FILE     *Stream,
243   OUT VOID              *Buffer,
244   OUT UINTN             *BufferSize
245   );
246 
247 
248 /**
249   Read the entire file into a buffer. This routine allocates the buffer and
250   returns it to the user full of the read data.
251 
252   This is very useful for load file where it's hard to know how big the buffer
253   must be.
254 
255   @param  Stream      Open File Handle
256   @param  Buffer      Pointer to buffer to return.
257   @param  BufferSize  Pointer to Size of buffer return..
258 
259 
260   @return EFI_SUCCESS           Stream is not an Open File
261   @return EFI_END_OF_FILE       Tried to read past the end of the file
262   @return EFI_INVALID_PARAMETER Stream is not an open file handle
263   @return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read
264   @return "other"               Error returned from device read
265 
266 **/
267 EFI_STATUS
268 EfiReadAllocatePool (
269   IN  EFI_OPEN_FILE     *Stream,
270   OUT VOID              **Buffer,
271   OUT UINTN             *BufferSize
272   );
273 
274 
275 /**
276   Write data back to the file.
277 
278   @param  Stream      Open File Handle
279   @param  Buffer      Pointer to buffer to return.
280   @param  BufferSize  Pointer to Size of buffer return..
281 
282 
283   @return EFI_SUCCESS           Stream is not an Open File
284   @return EFI_END_OF_FILE       Tried to read past the end of the file
285   @return EFI_INVALID_PARAMETER Stream is not an open file handle
286   @return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read
287   @return "other"               Error returned from device write
288 
289 **/
290 EFI_STATUS
291 EfiWrite (
292   IN  EFI_OPEN_FILE   *Stream,
293   OUT VOID            *Buffer,
294   OUT UINTN           *BufferSize
295   );
296 
297 
298 /**
299   Return the number of devices of the current type active in the system
300 
301   @param  Type      Device type to check
302 
303   @return 0         Invalid type
304 
305 **/
306 UINTN
307 EfiGetDeviceCounts (
308   IN  EFI_OPEN_FILE_TYPE     Type
309   );
310 
311 
312 /**
313   Set the Current Working Directory (CWD). If a call is made to EfiOpen () and
314   the path does not contain a device name, The CWD is prepended to the path.
315 
316   @param  Cwd     Current Working Directory to set
317 
318 
319   @return EFI_SUCCESS           CWD is set
320   @return EFI_INVALID_PARAMETER Cwd is not a valid device:path
321 
322 **/
323 EFI_STATUS
324 EfiSetCwd (
325   IN  CHAR8   *Cwd
326   );
327 
328 /**
329   Set the Current Working Directory (CWD). If a call is made to EfiOpen () and
330   the path does not contain a device name, The CWD is prepended to the path.
331 
332   @param  Cwd     Current Working Directory
333 
334 
335   @return NULL    No CWD set
336   @return 'other' malloc'ed buffer contains CWD.
337 
338 **/
339 CHAR8 *
340 EfiGetCwd (
341   VOID
342   );
343 
344 #endif
345