OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
Open.c
Go to the documentation of this file.
1
9#include "NTFS.h"
10#include "Helper.h"
11
12extern INT64 mIndexCounter;
13
14EFI_STATUS
15EFIAPI
17 IN EFI_FILE_PROTOCOL *This,
18 OUT EFI_FILE_PROTOCOL **NewHandle,
19 IN CHAR16 *FileName,
20 IN UINT64 OpenMode,
21 IN UINT64 Attributes
22 )
23{
24 EFI_STATUS Status;
25 EFI_NTFS_FILE *File;
26 EFI_FS *FileSystem;
27 EFI_NTFS_FILE *NewFile;
28 CHAR16 Path[MAX_PATH];
29 CHAR16 CleanPath[MAX_PATH];
30 CHAR16 *DirName;
31 UINTN Index;
32 UINTN Length;
33 BOOLEAN AbsolutePath;
34
35 ASSERT (This != NULL);
36 ASSERT (NewHandle != NULL);
37 ASSERT (FileName != NULL);
38
39 File = (EFI_NTFS_FILE *)This;
40 FileSystem = File->FileSystem;
41 AbsolutePath = (*FileName == L'\\');
42
43 ZeroMem (Path, sizeof (Path));
44
45 if (OpenMode != EFI_FILE_MODE_READ) {
46 DEBUG ((DEBUG_INFO, "NTFS: File '%s' can only be opened in read-only mode\n", FileName));
47 return EFI_WRITE_PROTECTED;
48 }
49
50 if ((*FileName == 0) || (CompareMem (FileName, L".", sizeof (L".")) == 0)) {
51 ++File->RefCount;
52 *NewHandle = This;
53 return EFI_SUCCESS;
54 }
55
56 if (AbsolutePath) {
57 Length = 0;
58 } else {
59 Length = StrnLenS (File->Path, MAX_PATH);
60 if (Length == MAX_PATH) {
61 DEBUG ((DEBUG_INFO, "NTFS: Path is too long.\n"));
62 return EFI_OUT_OF_RESOURCES;
63 }
64
65 Status = StrCpyS (Path, MAX_PATH, File->Path);
66 if (EFI_ERROR (Status)) {
67 DEBUG ((DEBUG_INFO, "NTFS: Could not copy string.\n"));
68 return Status;
69 }
70
71 if ((Length == 0) || (Path[Length - 1U] != '/')) {
72 Path[Length++] = L'/';
73 }
74 }
75
76 Status = StrCpyS (&Path[Length], MAX_PATH - Length, FileName);
77 if (EFI_ERROR (Status)) {
78 DEBUG ((DEBUG_INFO, "NTFS: Could not copy FileName `%s`.\n", FileName));
79 return Status;
80 }
81
82 Index = StrnLenS (Path, MAX_PATH);
83 while (Index > Length) {
84 --Index;
85 if (Path[Index] == L'\\') {
86 Path[Index] = L'/';
87 }
88 }
89
90 ZeroMem (CleanPath, sizeof (CleanPath));
91 Status = RelativeToAbsolute (CleanPath, Path);
92 if (EFI_ERROR (Status)) {
93 return Status;
94 }
95
96 NewFile = AllocateZeroPool (sizeof (EFI_NTFS_FILE));
97 if (NewFile == NULL) {
98 return EFI_OUT_OF_RESOURCES;
99 }
100
101 NewFile->FileSystem = FileSystem;
102 CopyMem (&NewFile->EfiFile, &FileSystem->EfiFile, sizeof (EFI_FILE_PROTOCOL));
103
104 NewFile->Path = AllocateZeroPool (StrnSizeS (CleanPath, MAX_PATH));
105 if (NewFile->Path == NULL) {
106 DEBUG ((DEBUG_INFO, "NTFS: Could not instantiate path\n"));
107 FreePool (NewFile);
108 return EFI_OUT_OF_RESOURCES;
109 }
110
111 CopyMem (NewFile->Path, CleanPath, StrnSizeS (CleanPath, MAX_PATH));
112
113 Length = StrnLenS (CleanPath, MAX_PATH);
114 if (Length == MAX_PATH) {
115 DEBUG ((DEBUG_INFO, "NTFS: CleanPath is too long.\n"));
116 return EFI_OUT_OF_RESOURCES;
117 }
118
119 Index = Length;
120 while (Index > 0) {
121 --Index;
122 if (CleanPath[Index] == L'/') {
123 CleanPath[Index] = 0;
124 break;
125 }
126 }
127
128 DirName = (Index == 0) ? L"/" : CleanPath;
129 NewFile->BaseName = (Index == Length) ? L"\0" : &NewFile->Path[Index + 1U];
130
131 Status = NtfsDir (FileSystem, DirName, NewFile, INFO_HOOK);
132 if (EFI_ERROR (Status)) {
133 FreePool (NewFile->Path);
134 FreePool (NewFile);
135 return Status;
136 }
137
138 if (!NewFile->IsDir) {
139 Status = NtfsOpen (NewFile);
140 if (EFI_ERROR (Status)) {
141 FreePool (NewFile->Path);
142 FreePool (NewFile);
143 return Status;
144 }
145 }
146
147 NewFile->RefCount++;
148 *NewHandle = &NewFile->EfiFile;
149
150 return EFI_SUCCESS;
151}
152
153STATIC
154EFI_STATUS
156 IN EFI_NTFS_FILE *File,
157 OUT VOID *Data,
158 IN OUT UINTN *Size
159 )
160{
161 EFI_STATUS Status;
162 EFI_FILE_INFO *Info;
163 CHAR16 Path[MAX_PATH];
164 EFI_NTFS_FILE *TmpFile = NULL;
165 UINTN Length;
166
167 ASSERT (File != NULL);
168 ASSERT (Size != NULL);
169 ASSERT ((Data != NULL) || ((Data == NULL) && (*Size == 0)));
170
171 Info = (EFI_FILE_INFO *)Data;
172
173 if (*Size < MINIMUM_INFO_LENGTH) {
175 return EFI_BUFFER_TOO_SMALL;
176 }
177
178 ZeroMem (Path, sizeof (Path));
179 ZeroMem (Data, *Size);
180 Info->Size = *Size;
181
182 Status = StrCpyS (Path, MAX_PATH, File->Path);
183 if (EFI_ERROR (Status)) {
184 DEBUG ((DEBUG_INFO, "NTFS: Could not copy string.\n"));
185 return Status;
186 }
187
188 Length = StrnLenS (Path, MAX_PATH);
189 if (Length == MAX_PATH) {
190 DEBUG ((DEBUG_INFO, "NTFS: Path is too long.\n"));
191 return EFI_OUT_OF_RESOURCES;
192 }
193
194 if ((Length == 0) || (Path[Length - 1U] != L'/')) {
195 Path[Length] = L'/';
196 Length++;
197 }
198
199 mIndexCounter = (INT64)File->DirIndex;
200 if (Length == 0) {
201 Status = NtfsDir (File->FileSystem, L"/", Data, DIR_HOOK);
202 } else {
203 Status = NtfsDir (File->FileSystem, File->Path, Data, DIR_HOOK);
204 }
205
206 if (mIndexCounter >= 0) {
207 //
208 // No entries left
209 //
210 *Size = 0;
211 return EFI_SUCCESS;
212 }
213
214 if (EFI_ERROR (Status)) {
215 DEBUG ((DEBUG_INFO, "NTFS: Directory listing failed.\n"));
216 return Status;
217 }
218
219 Info->FileSize = 0;
220 Info->PhysicalSize = 0;
221
222 if ((Info->Attribute & EFI_FILE_DIRECTORY) == 0) {
223 TmpFile = AllocateZeroPool (sizeof (EFI_NTFS_FILE));
224 if (TmpFile == NULL) {
225 return EFI_OUT_OF_RESOURCES;
226 }
227
228 TmpFile->FileSystem = File->FileSystem;
229 CopyMem (&TmpFile->EfiFile, &File->FileSystem->EfiFile, sizeof (EFI_FILE_PROTOCOL));
230
231 if ((MAX_PATH - Length) < StrSize (Info->FileName)) {
232 DEBUG ((DEBUG_INFO, "NTFS: FileName is too long.\n"));
233 FreePool (TmpFile);
234 return EFI_OUT_OF_RESOURCES;
235 }
236
237 CopyMem (&Path[Length], Info->FileName, StrSize (Info->FileName));
238 TmpFile->Path = Path;
239
240 Status = NtfsOpen (TmpFile);
241 if (EFI_ERROR (Status)) {
242 // DEBUG ((DEBUG_INFO, "NTFS: Unable to obtain the size of '%s'\n", Info->FileName));
243 } else {
244 Info->FileSize = TmpFile->RootFile.DataAttributeSize;
245 Info->PhysicalSize = TmpFile->RootFile.DataAttributeSize;
246 }
247
248 FreePool (TmpFile);
249 }
250
251 *Size = (UINTN)Info->Size;
252 ++File->DirIndex;
253
254 // DEBUG ((DEBUG_INFO, "NTFS: Entry[%d]: '%s' %s\n", File->DirIndex - 1U, Info->FileName,
255 // (Info->Attribute & EFI_FILE_DIRECTORY) ? L"<DIR>" : L""));
256
257 return EFI_SUCCESS;
258}
259
260STATIC
261EFI_STATUS
263 IN EFI_NTFS_FILE *File,
264 OUT VOID *Data,
265 IN UINTN *Size
266 )
267{
268 EFI_STATUS Status;
269 UINT64 Remaining;
270 NTFS_FILE *BaseMftRecord;
271
272 ASSERT (File != NULL);
273 ASSERT (Size != NULL);
274 ASSERT ((Data != NULL) || ((Data == NULL) && (*Size == 0)));
275
276 Remaining = (File->RootFile.DataAttributeSize > File->Offset) ?
277 File->RootFile.DataAttributeSize - File->Offset : 0;
278
279 if (*Size > Remaining) {
280 *Size = (UINTN)Remaining;
281 }
282
283 BaseMftRecord = &File->RootFile;
284
285 Status = ReadAttr (&BaseMftRecord->Attr, Data, File->Offset, *Size);
286 if (EFI_ERROR (Status)) {
287 *Size = 0;
288 FreeAttr (&BaseMftRecord->Attr);
289 return Status;
290 }
291
292 File->Offset += *Size;
293
294 return EFI_SUCCESS;
295}
296
297EFI_STATUS
298EFIAPI
300 IN EFI_FILE_PROTOCOL *This,
301 IN OUT UINTN *BufferSize,
302 OUT VOID *Buffer
303 )
304{
305 EFI_NTFS_FILE *File;
306
307 ASSERT (This != NULL);
308 ASSERT (BufferSize != NULL);
309 ASSERT ((Buffer != NULL) || ((Buffer == NULL) && (*BufferSize == 0)));
310
311 File = (EFI_NTFS_FILE *)This;
312
313 if (File->IsDir) {
314 return FileReadDir (File, Buffer, BufferSize);
315 }
316
317 return Read (File, Buffer, BufferSize);
318}
319
320EFI_STATUS
321EFIAPI
323 IN EFI_FILE_PROTOCOL *This,
324 IN OUT UINTN *BufferSize,
325 IN VOID *Buffer
326 )
327{
328 return EFI_WRITE_PROTECTED;
329}
330
331EFI_STATUS
332EFIAPI
334 IN EFI_FILE_PROTOCOL *This
335 )
336{
337 FileClose (This);
338
339 return EFI_WARN_DELETE_FAILURE;
340}
341
342EFI_STATUS
343EFIAPI
345 IN EFI_FILE_PROTOCOL *This
346 )
347{
348 return EFI_ACCESS_DENIED;
349}
350
351EFI_STATUS
352EFIAPI
354 IN EFI_FILE_PROTOCOL *This
355 )
356{
357 EFI_NTFS_FILE *File;
358
359 ASSERT (This != NULL);
360
361 File = (EFI_NTFS_FILE *)This;
362
363 if (&File->RootFile == File->FileSystem->RootIndex) {
364 return EFI_SUCCESS;
365 }
366
367 if (--File->RefCount == 0) {
368 FreeFile (&File->RootFile);
369 FreeFile (&File->MftFile);
370
371 if (File->Path != NULL) {
372 FreePool (File->Path);
373 }
374
375 FreePool (File);
376 }
377
378 return EFI_SUCCESS;
379}
UINT64 Length
EFI_STATUS EFIAPI ReadAttr(IN NTFS_ATTR *Attr, OUT UINT8 *Dest, IN UINT64 Offset, IN UINTN Length)
Definition Data.c:184
VOID FreeFile(IN NTFS_FILE *File)
Definition Disc.c:810
EFI_STATUS NtfsDir(IN EFI_FS *FileSystem, IN CONST CHAR16 *Path, OUT EFI_NTFS_FILE *File, IN FUNCTION_TYPE FunctionType)
Definition Disc.c:13
VOID FreeAttr(IN NTFS_ATTR *Attr)
Definition Disc.c:792
EFI_STATUS NtfsOpen(IN EFI_NTFS_FILE *File)
Definition Disc.c:53
#define MAX_PATH
Definition Driver.h:16
#define MINIMUM_INFO_LENGTH
Definition Driver.h:17
EFI_STATUS RelativeToAbsolute(OUT CHAR16 *Dest, IN CHAR16 *Source)
Definition Index.c:826
@ INFO_HOOK
Definition Helper.h:55
@ DIR_HOOK
Definition Helper.h:56
DMG_SIZE_DEVICE_PATH Size
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
EFI_STATUS EFIAPI FileClose(IN EFI_FILE_PROTOCOL *This)
Definition Open.c:353
EFI_STATUS EFIAPI FileFlush(IN EFI_FILE_PROTOCOL *This)
Definition Open.c:344
EFI_STATUS EFIAPI FileDelete(IN EFI_FILE_PROTOCOL *This)
Definition Open.c:333
INT64 mIndexCounter
Definition Index.c:14
STATIC EFI_STATUS FileReadDir(IN EFI_NTFS_FILE *File, OUT VOID *Data, IN OUT UINTN *Size)
Definition Open.c:155
EFI_STATUS EFIAPI FileOpen(IN EFI_FILE_PROTOCOL *This, OUT EFI_FILE_PROTOCOL **NewHandle, IN CHAR16 *FileName, IN UINT64 OpenMode, IN UINT64 Attributes)
Definition Open.c:16
EFI_STATUS EFIAPI FileWrite(IN EFI_FILE_PROTOCOL *This, IN OUT UINTN *BufferSize, IN VOID *Buffer)
Definition Open.c:322
STATIC EFI_STATUS Read(IN EFI_NTFS_FILE *File, OUT VOID *Data, IN UINTN *Size)
Definition Open.c:262
EFI_STATUS EFIAPI FileRead(IN EFI_FILE_PROTOCOL *This, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
Definition Open.c:299
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55
EFI_FILE_PROTOCOL EfiFile
Definition Driver.h:641
NTFS_FILE * RootIndex
Definition Driver.h:646
NTFS_FILE RootFile
Definition Driver.h:634
UINT32 RefCount
Definition Driver.h:633
BOOLEAN IsDir
Definition Driver.h:628
CHAR16 * Path
Definition Driver.h:630
CHAR16 * BaseName
Definition Driver.h:631
EFI_FS * FileSystem
Definition Driver.h:636
EFI_FILE_PROTOCOL EfiFile
Definition Driver.h:627
NTFS_FILE MftFile
Definition Driver.h:635
NTFS_ATTR Attr
Definition Driver.h:622
UINT64 DataAttributeSize
Definition Driver.h:616