3 Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Functions that perform file read/write
30 IN EFI_FILE_PROTOCOL
*FHand
,
37 Get the file's position of the file.
41 FHand - The handle of file.
42 Position - The file's position of the file.
46 EFI_SUCCESS - Get the info successfully.
47 EFI_DEVICE_ERROR - Can not find the OFile for the file.
48 EFI_UNSUPPORTED - The open file is not a file.
55 IFile
= IFILE_FROM_FHAND (FHand
);
58 if (OFile
->Error
== EFI_NOT_FOUND
) {
59 return EFI_DEVICE_ERROR
;
62 if (OFile
->ODir
!= NULL
) {
63 return EFI_UNSUPPORTED
;
66 *Position
= IFile
->Position
;
73 IN EFI_FILE_PROTOCOL
*FHand
,
80 Set the file's position of the file.
84 FHand - The handle of file.
85 Position - The file's position of the file.
89 EFI_SUCCESS - Set the info successfully.
90 EFI_DEVICE_ERROR - Can not find the OFile for the file.
91 EFI_UNSUPPORTED - Set a directory with a not-zero position.
98 IFile
= IFILE_FROM_FHAND (FHand
);
101 if (OFile
->Error
== EFI_NOT_FOUND
) {
102 return EFI_DEVICE_ERROR
;
105 FatWaitNonblockingTask (IFile
);
108 // If this is a directory, we can only set back to position 0
110 if (OFile
->ODir
!= NULL
) {
113 // Reset current directory cursor;
115 return EFI_UNSUPPORTED
;
118 FatResetODirCursor (OFile
);
123 if (Position
== (UINT64
)-1) {
124 Position
= OFile
->FileSize
;
129 IFile
->Position
= Position
;
136 IN OUT UINTN
*BufferSize
,
143 Get the file info from the open file of the IFile into Buffer.
147 IFile - The instance of the open file.
148 BufferSize - Size of Buffer.
149 Buffer - Buffer containing read data.
153 EFI_SUCCESS - Get the file info successfully.
154 other - An error occurred when operation the disk.
164 OFile
= IFile
->OFile
;
166 CurrentPos
= ((UINT32
) IFile
->Position
) / sizeof (FAT_DIRECTORY_ENTRY
);
169 // We need to relocate the directory
171 if (CurrentPos
< ODir
->CurrentPos
) {
173 // The directory cursor has been modified by another IFile, we reset the cursor
175 FatResetODirCursor (OFile
);
178 // We seek the next directory entry's position
181 Status
= FatGetNextDirEnt (OFile
, &DirEnt
);
182 if (EFI_ERROR (Status
) || DirEnt
== NULL
) {
184 // Something error occurred or reach the end of directory,
185 // return 0 buffersize
190 } while (ODir
->CurrentPos
<= CurrentPos
);
191 Status
= FatGetDirEntInfo (OFile
->Volume
, DirEnt
, BufferSize
, Buffer
);
195 // Update IFile's Position
197 if (!EFI_ERROR (Status
)) {
199 // Update IFile->Position, if everything is all right
201 CurrentPos
= ODir
->CurrentPos
;
202 IFile
->Position
= (UINT64
) (CurrentPos
* sizeof (FAT_DIRECTORY_ENTRY
));
210 IN EFI_FILE_PROTOCOL
*FHand
,
212 IN OUT UINTN
*BufferSize
,
214 IN EFI_FILE_IO_TOKEN
*Token
220 Get the file info from the open file of the IFile into Buffer.
224 FHand - The file handle to access.
225 IoMode - Indicate whether the access mode is reading or writing.
226 BufferSize - Size of Buffer.
227 Buffer - Buffer containing read data.
228 Token - A pointer to the token associated with the transaction.
232 EFI_SUCCESS - Get the file info successfully.
233 EFI_DEVICE_ERROR - Can not find the OFile for the file.
234 EFI_VOLUME_CORRUPTED - The file type of open file is error.
235 EFI_WRITE_PROTECTED - The disk is write protect.
236 EFI_ACCESS_DENIED - The file is read-only.
237 other - An error occurred when operating on the disk.
248 IFile
= IFILE_FROM_FHAND (FHand
);
249 OFile
= IFile
->OFile
;
250 Volume
= OFile
->Volume
;
254 // Write to a directory is unsupported
256 if ((OFile
->ODir
!= NULL
) && (IoMode
== WRITE_DATA
)) {
257 return EFI_UNSUPPORTED
;
260 if (OFile
->Error
== EFI_NOT_FOUND
) {
261 return EFI_DEVICE_ERROR
;
264 if (IoMode
== READ_DATA
) {
266 // If position is at EOF, then return device error
268 if (IFile
->Position
> OFile
->FileSize
) {
269 return EFI_DEVICE_ERROR
;
273 // Check if the we can write data
275 if (Volume
->ReadOnly
) {
276 return EFI_WRITE_PROTECTED
;
279 if (IFile
->ReadOnly
) {
280 return EFI_ACCESS_DENIED
;
285 FatWaitNonblockingTask (IFile
);
288 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
289 // But if it calls, the below check can avoid crash.
291 if (FHand
->Revision
< EFI_FILE_PROTOCOL_REVISION2
) {
292 return EFI_UNSUPPORTED
;
294 Task
= FatCreateTask (IFile
, Token
);
296 return EFI_OUT_OF_RESOURCES
;
302 Status
= OFile
->Error
;
303 if (!EFI_ERROR (Status
)) {
304 if (OFile
->ODir
!= NULL
) {
306 // Read a directory is supported
308 ASSERT (IoMode
== READ_DATA
);
309 Status
= FatIFileReadDir (IFile
, BufferSize
, Buffer
);
315 EndPosition
= IFile
->Position
+ *BufferSize
;
316 if (EndPosition
> OFile
->FileSize
) {
318 // The position goes beyond the end of file
320 if (IoMode
== READ_DATA
) {
322 // Adjust the actual size read
324 *BufferSize
-= (UINTN
) EndPosition
- OFile
->FileSize
;
327 // We expand the file size of OFile
329 Status
= FatGrowEof (OFile
, EndPosition
);
330 if (EFI_ERROR (Status
)) {
332 // Must update the file's info into the file's Directory Entry
333 // and then flush the dirty cache info into disk.
336 FatOFileFlush (OFile
);
341 FatUpdateDirEntClusterSizeInfo (OFile
);
345 Status
= FatAccessOFile (OFile
, IoMode
, (UINTN
) IFile
->Position
, BufferSize
, Buffer
, Task
);
346 IFile
->Position
+= *BufferSize
;
351 if (!EFI_ERROR (Status
)) {
352 Status
= FatQueueTask (IFile
, Task
);
354 FatDestroyTask (Task
);
360 // On EFI_SUCCESS case, not calling FatCleanupVolume():
361 // 1) The Cache flush operation is avoided to enhance
362 // performance. Caller is responsible to call Flush() when necessary.
363 // 2) The volume dirty bit is probably set already, and is expected to be
364 // cleaned in subsequent Flush() or other operations.
365 // 3) Write operation doesn't affect OFile/IFile structure, so
366 // Reference checking is not necessary.
368 if (EFI_ERROR (Status
)) {
369 Status
= FatCleanupVolume (Volume
, OFile
, Status
, NULL
);
379 IN EFI_FILE_PROTOCOL
*FHand
,
380 IN OUT UINTN
*BufferSize
,
391 FHand - The handle of the file.
392 BufferSize - Size of Buffer.
393 Buffer - Buffer containing read data.
397 EFI_SUCCESS - Get the file info successfully.
398 EFI_DEVICE_ERROR - Can not find the OFile for the file.
399 EFI_VOLUME_CORRUPTED - The file type of open file is error.
400 other - An error occurred when operation the disk.
404 return FatIFileAccess (FHand
, READ_DATA
, BufferSize
, Buffer
, NULL
);
410 IN EFI_FILE_PROTOCOL
*FHand
,
411 IN OUT EFI_FILE_IO_TOKEN
*Token
421 FHand - The handle of the file.
422 Token - A pointer to the token associated with the transaction.
426 EFI_SUCCESS - Get the file info successfully.
427 EFI_DEVICE_ERROR - Can not find the OFile for the file.
428 EFI_VOLUME_CORRUPTED - The file type of open file is error.
429 other - An error occurred when operation the disk.
433 return FatIFileAccess (FHand
, READ_DATA
, &Token
->BufferSize
, Token
->Buffer
, Token
);
439 IN EFI_FILE_PROTOCOL
*FHand
,
440 IN OUT UINTN
*BufferSize
,
447 Write the content of buffer into files.
451 FHand - The handle of the file.
452 BufferSize - Size of Buffer.
453 Buffer - Buffer containing write data.
457 EFI_SUCCESS - Set the file info successfully.
458 EFI_WRITE_PROTECTED - The disk is write protect.
459 EFI_ACCESS_DENIED - The file is read-only.
460 EFI_DEVICE_ERROR - The OFile is not valid.
461 EFI_UNSUPPORTED - The open file is not a file.
462 - The writing file size is larger than 4GB.
463 other - An error occurred when operation the disk.
467 return FatIFileAccess (FHand
, WRITE_DATA
, BufferSize
, Buffer
, NULL
);
473 IN EFI_FILE_PROTOCOL
*FHand
,
474 IN OUT EFI_FILE_IO_TOKEN
*Token
484 FHand - The handle of the file.
485 Token - A pointer to the token associated with the transaction.
489 EFI_SUCCESS - Get the file info successfully.
490 EFI_DEVICE_ERROR - Can not find the OFile for the file.
491 EFI_VOLUME_CORRUPTED - The file type of open file is error.
492 other - An error occurred when operation the disk.
496 return FatIFileAccess (FHand
, WRITE_DATA
, &Token
->BufferSize
, Token
->Buffer
, Token
);
504 IN OUT UINTN
*DataBufferSize
,
505 IN OUT UINT8
*UserBuffer
,
512 This function reads data from a file or writes data to a file.
513 It uses OFile->PosRem to determine how much data can be accessed in one time.
517 OFile - The open file.
518 IoMode - Indicate whether the access mode is reading or writing.
519 Position - The position where data will be accessed.
520 DataBufferSize - Size of Buffer.
521 UserBuffer - Buffer containing data.
525 EFI_SUCCESS - Access the data successfully.
526 other - An error occurred when operating on the disk.
535 BufferSize
= *DataBufferSize
;
536 Volume
= OFile
->Volume
;
537 ASSERT_VOLUME_LOCKED (Volume
);
539 Status
= EFI_SUCCESS
;
540 while (BufferSize
> 0) {
542 // Seek the OFile to the file position
544 Status
= FatOFilePosition (OFile
, Position
, BufferSize
);
545 if (EFI_ERROR (Status
)) {
549 // Clip length to block run
551 Len
= BufferSize
> OFile
->PosRem
? OFile
->PosRem
: BufferSize
;
556 Status
= FatDiskIo (Volume
, IoMode
, OFile
->PosDisk
, Len
, UserBuffer
, Task
);
557 if (EFI_ERROR (Status
)) {
561 // Data was successfully accessed
566 if (IoMode
== WRITE_DATA
) {
568 OFile
->Archive
= TRUE
;
571 // Make sure no outbound occurred
573 ASSERT (Position
<= OFile
->FileSize
);
576 // Update the number of bytes accessed
578 *DataBufferSize
-= BufferSize
;
585 IN UINT64 ExpandedSize
591 Expand OFile by appending zero bytes at the end of OFile.
595 OFile - The open file.
596 ExpandedSize - The number of zero bytes appended at the end of the file.
600 EFI_SUCCESS - The file is expanded successfully.
601 other - An error occurred when expanding file.
608 WritePos
= OFile
->FileSize
;
609 Status
= FatGrowEof (OFile
, ExpandedSize
);
610 if (!EFI_ERROR (Status
)) {
611 Status
= FatWriteZeroPool (OFile
, WritePos
);
626 Write zero pool from the WritePos to the end of OFile.
630 OFile - The open file to write zero pool.
631 WritePos - The number of zero bytes written.
635 EFI_SUCCESS - Write the zero pool successfully.
636 EFI_OUT_OF_RESOURCES - Not enough memory to perform the operation.
637 other - An error occurred when writing disk.
647 AppendedSize
= OFile
->FileSize
- WritePos
;
648 BufferSize
= AppendedSize
;
649 if (AppendedSize
> FAT_MAX_ALLOCATE_SIZE
) {
651 // If the appended size is larger, maybe we can not allocate the whole
652 // memory once. So if the growed size is larger than 10M, we just
653 // allocate 10M memory (one healthy system should have 10M available
654 // memory), and then write the zerobuffer to the file several times.
656 BufferSize
= FAT_MAX_ALLOCATE_SIZE
;
659 ZeroBuffer
= AllocateZeroPool (BufferSize
);
660 if (ZeroBuffer
== NULL
) {
661 return EFI_OUT_OF_RESOURCES
;
665 WriteSize
= AppendedSize
> BufferSize
? BufferSize
: (UINTN
) AppendedSize
;
666 AppendedSize
-= WriteSize
;
667 Status
= FatAccessOFile (OFile
, WRITE_DATA
, WritePos
, &WriteSize
, ZeroBuffer
, NULL
);
668 if (EFI_ERROR (Status
)) {
672 WritePos
+= WriteSize
;
673 } while (AppendedSize
> 0);
675 FreePool (ZeroBuffer
);
682 IN UINTN TruncatedSize
688 Truncate the OFile to smaller file size.
692 OFile - The open file.
693 TruncatedSize - The new file size.
697 EFI_SUCCESS - The file is truncated successfully.
698 other - An error occurred when truncating file.
702 OFile
->FileSize
= TruncatedSize
;
703 return FatShrinkEof (OFile
);