TianoCore EDK2 master
Loading...
Searching...
No Matches
ReadWrite.c
Go to the documentation of this file.
1
10#include "Fat.h"
11
26EFIAPI
28 IN EFI_FILE_PROTOCOL *FHand,
29 OUT UINT64 *Position
30 )
31{
32 FAT_IFILE *IFile;
33 FAT_OFILE *OFile;
34
35 IFile = IFILE_FROM_FHAND (FHand);
36 OFile = IFile->OFile;
37
38 if (OFile->Error == EFI_NOT_FOUND) {
39 return EFI_DEVICE_ERROR;
40 }
41
42 if (OFile->ODir != NULL) {
43 return EFI_UNSUPPORTED;
44 }
45
46 *Position = IFile->Position;
47 return EFI_SUCCESS;
48}
49
63EFIAPI
65 IN EFI_FILE_PROTOCOL *FHand,
66 IN UINT64 Position
67 )
68{
69 FAT_IFILE *IFile;
70 FAT_OFILE *OFile;
71
72 IFile = IFILE_FROM_FHAND (FHand);
73 OFile = IFile->OFile;
74
75 if (OFile->Error == EFI_NOT_FOUND) {
76 return EFI_DEVICE_ERROR;
77 }
78
80
81 //
82 // If this is a directory, we can only set back to position 0
83 //
84 if (OFile->ODir != NULL) {
85 if (Position != 0) {
86 //
87 // Reset current directory cursor;
88 //
89 return EFI_UNSUPPORTED;
90 }
91
92 FatResetODirCursor (OFile);
93 }
94
95 //
96 // Set the position
97 //
98 if (Position == (UINT64)-1) {
99 Position = OFile->FileSize;
100 }
101
102 //
103 // Set the position
104 //
105 IFile->Position = Position;
106 return EFI_SUCCESS;
107}
108
123 IN FAT_IFILE *IFile,
124 IN OUT UINTN *BufferSize,
125 OUT VOID *Buffer
126 )
127{
128 EFI_STATUS Status;
129 FAT_OFILE *OFile;
130 FAT_ODIR *ODir;
131 FAT_DIRENT *DirEnt;
132 UINT32 CurrentPos;
133
134 OFile = IFile->OFile;
135 ODir = OFile->ODir;
136 CurrentPos = ((UINT32)IFile->Position) / sizeof (FAT_DIRECTORY_ENTRY);
137
138 //
139 // We need to relocate the directory
140 //
141 if (CurrentPos < ODir->CurrentPos) {
142 //
143 // The directory cursor has been modified by another IFile, we reset the cursor
144 //
145 FatResetODirCursor (OFile);
146 }
147
148 //
149 // We seek the next directory entry's position
150 //
151 do {
152 Status = FatGetNextDirEnt (OFile, &DirEnt);
153 if (EFI_ERROR (Status) || (DirEnt == NULL)) {
154 //
155 // Something error occurred or reach the end of directory,
156 // return 0 buffersize
157 //
158 *BufferSize = 0;
159 goto Done;
160 }
161 } while (ODir->CurrentPos <= CurrentPos);
162
163 Status = FatGetDirEntInfo (OFile->Volume, DirEnt, BufferSize, Buffer);
164
165Done:
166 //
167 // Update IFile's Position
168 //
169 if (!EFI_ERROR (Status)) {
170 //
171 // Update IFile->Position, if everything is all right
172 //
173 CurrentPos = ODir->CurrentPos;
174 IFile->Position = CurrentPos * sizeof (FAT_DIRECTORY_ENTRY);
175 }
176
177 return Status;
178}
179
200 IN EFI_FILE_PROTOCOL *FHand,
201 IN IO_MODE IoMode,
202 IN OUT UINTN *BufferSize,
203 IN OUT VOID *Buffer,
204 IN EFI_FILE_IO_TOKEN *Token
205 )
206{
207 EFI_STATUS Status;
208 FAT_IFILE *IFile;
209 FAT_OFILE *OFile;
210 FAT_VOLUME *Volume;
211 UINT64 EndPosition;
212 FAT_TASK *Task;
213
214 IFile = IFILE_FROM_FHAND (FHand);
215 OFile = IFile->OFile;
216 Volume = OFile->Volume;
217 Task = NULL;
218
219 //
220 // Write to a directory is unsupported
221 //
222 if ((OFile->ODir != NULL) && (IoMode == WriteData)) {
223 return EFI_UNSUPPORTED;
224 }
225
226 if (OFile->Error == EFI_NOT_FOUND) {
227 return EFI_DEVICE_ERROR;
228 }
229
230 if (IoMode == ReadData) {
231 //
232 // If position is at EOF, then return device error
233 //
234 if (IFile->Position > OFile->FileSize) {
235 return EFI_DEVICE_ERROR;
236 }
237 } else {
238 //
239 // Check if the we can write data
240 //
241 if (Volume->ReadOnly) {
242 return EFI_WRITE_PROTECTED;
243 }
244
245 if (IFile->ReadOnly) {
246 return EFI_ACCESS_DENIED;
247 }
248 }
249
250 if (Token == NULL) {
252 } else {
253 //
254 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
255 // But if it calls, the below check can avoid crash.
256 //
257 if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {
258 return EFI_UNSUPPORTED;
259 }
260
261 Task = FatCreateTask (IFile, Token);
262 if (Task == NULL) {
263 return EFI_OUT_OF_RESOURCES;
264 }
265 }
266
268
269 Status = OFile->Error;
270 if (!EFI_ERROR (Status)) {
271 if (OFile->ODir != NULL) {
272 //
273 // Read a directory is supported
274 //
275 ASSERT (IoMode == ReadData);
276 Status = FatIFileReadDir (IFile, BufferSize, Buffer);
277 OFile = NULL;
278 } else {
279 //
280 // Access a file
281 //
282 EndPosition = IFile->Position + *BufferSize;
283 if (EndPosition > OFile->FileSize) {
284 //
285 // The position goes beyond the end of file
286 //
287 if (IoMode == ReadData) {
288 //
289 // Adjust the actual size read
290 //
291 *BufferSize -= (UINTN)EndPosition - OFile->FileSize;
292 } else {
293 //
294 // We expand the file size of OFile
295 //
296 Status = FatGrowEof (OFile, EndPosition);
297 if (EFI_ERROR (Status)) {
298 //
299 // Must update the file's info into the file's Directory Entry
300 // and then flush the dirty cache info into disk.
301 //
302 *BufferSize = 0;
303 FatOFileFlush (OFile);
304 OFile = NULL;
305 goto Done;
306 }
307
309 }
310 }
311
312 Status = FatAccessOFile (OFile, IoMode, (UINTN)IFile->Position, BufferSize, Buffer, Task);
313 IFile->Position += *BufferSize;
314 }
315 }
316
317 if (Token != NULL) {
318 if (!EFI_ERROR (Status)) {
319 Status = FatQueueTask (IFile, Task);
320 } else {
321 FatDestroyTask (Task);
322 }
323 }
324
325Done:
326 //
327 // On EFI_SUCCESS case, not calling FatCleanupVolume():
328 // 1) The Cache flush operation is avoided to enhance
329 // performance. Caller is responsible to call Flush() when necessary.
330 // 2) The volume dirty bit is probably set already, and is expected to be
331 // cleaned in subsequent Flush() or other operations.
332 // 3) Write operation doesn't affect OFile/IFile structure, so
333 // Reference checking is not necessary.
334 //
335 if (EFI_ERROR (Status)) {
336 Status = FatCleanupVolume (Volume, OFile, Status, NULL);
337 }
338
340 return Status;
341}
342
359EFIAPI
361 IN EFI_FILE_PROTOCOL *FHand,
362 IN OUT UINTN *BufferSize,
363 OUT VOID *Buffer
364 )
365{
366 return FatIFileAccess (FHand, ReadData, BufferSize, Buffer, NULL);
367}
368
383EFIAPI
385 IN EFI_FILE_PROTOCOL *FHand,
387 )
388{
389 return FatIFileAccess (FHand, ReadData, &Token->BufferSize, Token->Buffer, Token);
390}
391
410EFIAPI
412 IN EFI_FILE_PROTOCOL *FHand,
413 IN OUT UINTN *BufferSize,
414 IN VOID *Buffer
415 )
416{
417 return FatIFileAccess (FHand, WriteData, BufferSize, Buffer, NULL);
418}
419
434EFIAPI
436 IN EFI_FILE_PROTOCOL *FHand,
438 )
439{
440 return FatIFileAccess (FHand, WriteData, &Token->BufferSize, Token->Buffer, Token);
441}
442
461 IN FAT_OFILE *OFile,
462 IN IO_MODE IoMode,
463 IN UINTN Position,
464 IN OUT UINTN *DataBufferSize,
465 IN OUT UINT8 *UserBuffer,
466 IN FAT_TASK *Task
467 )
468{
469 FAT_VOLUME *Volume;
470 UINTN Len;
471 EFI_STATUS Status;
472 UINTN BufferSize;
473
474 BufferSize = *DataBufferSize;
475 Volume = OFile->Volume;
476 ASSERT_VOLUME_LOCKED (Volume);
477
478 Status = EFI_SUCCESS;
479 while (BufferSize > 0) {
480 //
481 // Seek the OFile to the file position
482 //
483 Status = FatOFilePosition (OFile, Position, BufferSize);
484 if (EFI_ERROR (Status)) {
485 break;
486 }
487
488 //
489 // Clip length to block run
490 //
491 Len = BufferSize > OFile->PosRem ? OFile->PosRem : BufferSize;
492
493 //
494 // Write the data
495 //
496 Status = FatDiskIo (Volume, IoMode, OFile->PosDisk, Len, UserBuffer, Task);
497 if (EFI_ERROR (Status)) {
498 break;
499 }
500
501 //
502 // Data was successfully accessed
503 //
504 Position += Len;
505 UserBuffer += Len;
506 BufferSize -= Len;
507 if (IoMode == WriteData) {
508 OFile->Dirty = TRUE;
509 OFile->Archive = TRUE;
510 }
511
512 //
513 // Make sure no outbound occurred
514 //
515 ASSERT (Position <= OFile->FileSize);
516 }
517
518 //
519 // Update the number of bytes accessed
520 //
521 *DataBufferSize -= BufferSize;
522 return Status;
523}
524
538 IN FAT_OFILE *OFile,
539 IN UINT64 ExpandedSize
540 )
541{
542 EFI_STATUS Status;
543 UINTN WritePos;
544
545 WritePos = OFile->FileSize;
546 Status = FatGrowEof (OFile, ExpandedSize);
547 if (!EFI_ERROR (Status)) {
548 Status = FatWriteZeroPool (OFile, WritePos);
549 }
550
551 return Status;
552}
553
568 IN FAT_OFILE *OFile,
569 IN UINTN WritePos
570 )
571{
572 EFI_STATUS Status;
573 VOID *ZeroBuffer;
574 UINTN AppendedSize;
575 UINTN BufferSize;
576 UINTN WriteSize;
577
578 AppendedSize = OFile->FileSize - WritePos;
579 BufferSize = AppendedSize;
580 if (AppendedSize > FAT_MAX_ALLOCATE_SIZE) {
581 //
582 // If the appended size is larger, maybe we can not allocate the whole
583 // memory once. So if the growed size is larger than 10M, we just
584 // allocate 10M memory (one healthy system should have 10M available
585 // memory), and then write the zerobuffer to the file several times.
586 //
587 BufferSize = FAT_MAX_ALLOCATE_SIZE;
588 }
589
590 ZeroBuffer = AllocateZeroPool (BufferSize);
591 if (ZeroBuffer == NULL) {
592 return EFI_OUT_OF_RESOURCES;
593 }
594
595 do {
596 WriteSize = AppendedSize > BufferSize ? BufferSize : (UINTN)AppendedSize;
597 AppendedSize -= WriteSize;
598 Status = FatAccessOFile (OFile, WriteData, WritePos, &WriteSize, ZeroBuffer, NULL);
599 if (EFI_ERROR (Status)) {
600 break;
601 }
602
603 WritePos += WriteSize;
604 } while (AppendedSize > 0);
605
606 FreePool (ZeroBuffer);
607 return Status;
608}
609
623 IN FAT_OFILE *OFile,
624 IN UINTN TruncatedSize
625 )
626{
627 OFile->FileSize = TruncatedSize;
628 return FatShrinkEof (OFile);
629}
UINT64 UINTN
EFI_STATUS FatGetDirEntInfo(IN FAT_VOLUME *Volume, IN FAT_DIRENT *DirEnt, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
EFI_STATUS FatGetNextDirEnt(IN FAT_OFILE *OFile, OUT FAT_DIRENT **PtrDirEnt)
VOID FatUpdateDirEntClusterSizeInfo(IN FAT_OFILE *OFile)
VOID FatResetODirCursor(IN FAT_OFILE *OFile)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID FatDestroyTask(FAT_TASK *Task)
Definition: Misc.c:51
FAT_TASK * FatCreateTask(FAT_IFILE *IFile, EFI_FILE_IO_TOKEN *Token)
Definition: Misc.c:24
EFI_STATUS FatQueueTask(IN FAT_IFILE *IFile, IN FAT_TASK *Task)
Definition: Misc.c:124
EFI_STATUS FatOFileFlush(IN FAT_OFILE *OFile)
Definition: Flush.c:218
EFI_STATUS FatGrowEof(IN FAT_OFILE *OFile, IN UINT64 NewSizeInBytes)
Definition: FileSpace.c:429
EFI_STATUS FatOFilePosition(IN FAT_OFILE *OFile, IN UINTN Position, IN UINTN PosLimit)
Definition: FileSpace.c:562
VOID FatWaitNonblockingTask(FAT_IFILE *IFile)
Definition: Misc.c:75
EFI_STATUS FatShrinkEof(IN FAT_OFILE *OFile)
Definition: FileSpace.c:355
EFI_STATUS FatDiskIo(IN FAT_VOLUME *Volume, IN IO_MODE IoMode, IN UINT64 Offset, IN UINTN BufferSize, IN OUT VOID *Buffer, IN FAT_TASK *Task)
Definition: Misc.c:315
VOID FatAcquireLock(VOID)
Definition: Misc.c:395
VOID FatReleaseLock(VOID)
Definition: Misc.c:426
EFI_STATUS FatCleanupVolume(IN FAT_VOLUME *Volume, IN FAT_OFILE *OFile, IN EFI_STATUS EfiStatus, IN FAT_TASK *Task)
Definition: Flush.c:382
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS EFIAPI FatReadEx(IN EFI_FILE_PROTOCOL *FHand, IN OUT EFI_FILE_IO_TOKEN *Token)
Definition: ReadWrite.c:384
EFI_STATUS EFIAPI FatRead(IN EFI_FILE_PROTOCOL *FHand, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
Definition: ReadWrite.c:360
EFI_STATUS FatWriteZeroPool(IN FAT_OFILE *OFile, IN UINTN WritePos)
Definition: ReadWrite.c:567
EFI_STATUS EFIAPI FatWrite(IN EFI_FILE_PROTOCOL *FHand, IN OUT UINTN *BufferSize, IN VOID *Buffer)
Definition: ReadWrite.c:411
EFI_STATUS FatExpandOFile(IN FAT_OFILE *OFile, IN UINT64 ExpandedSize)
Definition: ReadWrite.c:537
EFI_STATUS EFIAPI FatGetPosition(IN EFI_FILE_PROTOCOL *FHand, OUT UINT64 *Position)
Definition: ReadWrite.c:27
EFI_STATUS FatIFileAccess(IN EFI_FILE_PROTOCOL *FHand, IN IO_MODE IoMode, IN OUT UINTN *BufferSize, IN OUT VOID *Buffer, IN EFI_FILE_IO_TOKEN *Token)
Definition: ReadWrite.c:199
EFI_STATUS FatIFileReadDir(IN FAT_IFILE *IFile, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
Definition: ReadWrite.c:122
EFI_STATUS EFIAPI FatSetPosition(IN EFI_FILE_PROTOCOL *FHand, IN UINT64 Position)
Definition: ReadWrite.c:64
EFI_STATUS FatTruncateOFile(IN FAT_OFILE *OFile, IN UINTN TruncatedSize)
Definition: ReadWrite.c:622
EFI_STATUS EFIAPI FatWriteEx(IN EFI_FILE_PROTOCOL *FHand, IN OUT EFI_FILE_IO_TOKEN *Token)
Definition: ReadWrite.c:435
EFI_STATUS FatAccessOFile(IN FAT_OFILE *OFile, IN IO_MODE IoMode, IN UINTN Position, IN OUT UINTN *DataBufferSize, IN OUT UINT8 *UserBuffer, IN FAT_TASK *Task)
Definition: ReadWrite.c:460
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
Definition: Fat.h:204
Definition: Fat.h:217
Definition: Fat.h:227