3 Copyright (c) 2005 - 2013, 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
;
253 if (OFile
->Error
== EFI_NOT_FOUND
) {
254 return EFI_DEVICE_ERROR
;
257 if (IoMode
== READ_DATA
) {
259 // If position is at EOF, then return device error
261 if (IFile
->Position
> OFile
->FileSize
) {
262 return EFI_DEVICE_ERROR
;
266 // Check if the we can write data
268 if (Volume
->ReadOnly
) {
269 return EFI_WRITE_PROTECTED
;
272 if (IFile
->ReadOnly
) {
273 return EFI_ACCESS_DENIED
;
278 FatWaitNonblockingTask (IFile
);
281 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
282 // But if it calls, the below check can avoid crash.
284 if (FHand
->Revision
< EFI_FILE_PROTOCOL_REVISION2
) {
285 return EFI_UNSUPPORTED
;
287 Task
= FatCreateTask (IFile
, Token
);
289 return EFI_OUT_OF_RESOURCES
;
295 Status
= OFile
->Error
;
296 if (!EFI_ERROR (Status
)) {
297 if (OFile
->ODir
!= NULL
) {
299 // Access a directory
301 Status
= EFI_UNSUPPORTED
;
302 if (IoMode
== READ_DATA
) {
304 // Read a directory is supported
306 Status
= FatIFileReadDir (IFile
, BufferSize
, Buffer
);
314 EndPosition
= IFile
->Position
+ *BufferSize
;
315 if (EndPosition
> OFile
->FileSize
) {
317 // The position goes beyond the end of file
319 if (IoMode
== READ_DATA
) {
321 // Adjust the actual size read
323 *BufferSize
-= (UINTN
) EndPosition
- OFile
->FileSize
;
326 // We expand the file size of OFile
328 Status
= FatGrowEof (OFile
, EndPosition
);
329 if (EFI_ERROR (Status
)) {
331 // Must update the file's info into the file's Directory Entry
332 // and then flush the dirty cache info into disk.
335 FatOFileFlush (OFile
);
340 FatUpdateDirEntClusterSizeInfo (OFile
);
344 Status
= FatAccessOFile (OFile
, IoMode
, (UINTN
) IFile
->Position
, BufferSize
, Buffer
, Task
);
345 IFile
->Position
+= *BufferSize
;
350 if (!EFI_ERROR (Status
)) {
351 Status
= FatQueueTask (IFile
, Task
);
353 FatDestroyTask (Task
);
359 // On EFI_SUCCESS case, not calling FatCleanupVolume():
360 // 1) The Cache flush operation is avoided to enhance
361 // performance. Caller is responsible to call Flush() when necessary.
362 // 2) The volume dirty bit is probably set already, and is expected to be
363 // cleaned in subsequent Flush() or other operations.
364 // 3) Write operation doesn't affect OFile/IFile structure, so
365 // Reference checking is not necessary.
367 if (EFI_ERROR (Status
)) {
368 Status
= FatCleanupVolume (Volume
, OFile
, Status
, NULL
);
378 IN EFI_FILE_PROTOCOL
*FHand
,
379 IN OUT UINTN
*BufferSize
,
390 FHand - The handle of the file.
391 BufferSize - Size of Buffer.
392 Buffer - Buffer containing read data.
396 EFI_SUCCESS - Get the file info successfully.
397 EFI_DEVICE_ERROR - Can not find the OFile for the file.
398 EFI_VOLUME_CORRUPTED - The file type of open file is error.
399 other - An error occurred when operation the disk.
403 return FatIFileAccess (FHand
, READ_DATA
, BufferSize
, Buffer
, NULL
);
409 IN EFI_FILE_PROTOCOL
*FHand
,
410 IN OUT EFI_FILE_IO_TOKEN
*Token
420 FHand - The handle of the file.
421 Token - A pointer to the token associated with the transaction.
425 EFI_SUCCESS - Get the file info successfully.
426 EFI_DEVICE_ERROR - Can not find the OFile for the file.
427 EFI_VOLUME_CORRUPTED - The file type of open file is error.
428 other - An error occurred when operation the disk.
432 return FatIFileAccess (FHand
, READ_DATA
, &Token
->BufferSize
, Token
->Buffer
, Token
);
438 IN EFI_FILE_PROTOCOL
*FHand
,
439 IN OUT UINTN
*BufferSize
,
446 Write the content of buffer into files.
450 FHand - The handle of the file.
451 BufferSize - Size of Buffer.
452 Buffer - Buffer containing write data.
456 EFI_SUCCESS - Set the file info successfully.
457 EFI_WRITE_PROTECTED - The disk is write protect.
458 EFI_ACCESS_DENIED - The file is read-only.
459 EFI_DEVICE_ERROR - The OFile is not valid.
460 EFI_UNSUPPORTED - The open file is not a file.
461 - The writing file size is larger than 4GB.
462 other - An error occurred when operation the disk.
466 return FatIFileAccess (FHand
, WRITE_DATA
, BufferSize
, Buffer
, NULL
);
472 IN EFI_FILE_PROTOCOL
*FHand
,
473 IN OUT EFI_FILE_IO_TOKEN
*Token
483 FHand - The handle of the file.
484 Token - A pointer to the token associated with the transaction.
488 EFI_SUCCESS - Get the file info successfully.
489 EFI_DEVICE_ERROR - Can not find the OFile for the file.
490 EFI_VOLUME_CORRUPTED - The file type of open file is error.
491 other - An error occurred when operation the disk.
495 return FatIFileAccess (FHand
, WRITE_DATA
, &Token
->BufferSize
, Token
->Buffer
, Token
);
503 IN OUT UINTN
*DataBufferSize
,
504 IN OUT UINT8
*UserBuffer
,
511 This function reads data from a file or writes data to a file.
512 It uses OFile->PosRem to determine how much data can be accessed in one time.
516 OFile - The open file.
517 IoMode - Indicate whether the access mode is reading or writing.
518 Position - The position where data will be accessed.
519 DataBufferSize - Size of Buffer.
520 UserBuffer - Buffer containing data.
524 EFI_SUCCESS - Access the data successfully.
525 other - An error occurred when operating on the disk.
534 BufferSize
= *DataBufferSize
;
535 Volume
= OFile
->Volume
;
536 ASSERT_VOLUME_LOCKED (Volume
);
538 Status
= EFI_SUCCESS
;
539 while (BufferSize
> 0) {
541 // Seek the OFile to the file position
543 Status
= FatOFilePosition (OFile
, Position
, BufferSize
);
544 if (EFI_ERROR (Status
)) {
548 // Clip length to block run
550 Len
= BufferSize
> OFile
->PosRem
? OFile
->PosRem
: BufferSize
;
555 Status
= FatDiskIo (Volume
, IoMode
, OFile
->PosDisk
, Len
, UserBuffer
, Task
);
556 if (EFI_ERROR (Status
)) {
560 // Data was successfully accessed
565 if (IoMode
== WRITE_DATA
) {
567 OFile
->Archive
= TRUE
;
570 // Make sure no outbound occurred
572 ASSERT (Position
<= OFile
->FileSize
);
575 // Update the number of bytes accessed
577 *DataBufferSize
-= BufferSize
;
584 IN UINT64 ExpandedSize
590 Expand OFile by appending zero bytes at the end of OFile.
594 OFile - The open file.
595 ExpandedSize - The number of zero bytes appended at the end of the file.
599 EFI_SUCCESS - The file is expanded successfully.
600 other - An error occurred when expanding file.
607 WritePos
= OFile
->FileSize
;
608 Status
= FatGrowEof (OFile
, ExpandedSize
);
609 if (!EFI_ERROR (Status
)) {
610 Status
= FatWriteZeroPool (OFile
, WritePos
);
625 Write zero pool from the WritePos to the end of OFile.
629 OFile - The open file to write zero pool.
630 WritePos - The number of zero bytes written.
634 EFI_SUCCESS - Write the zero pool successfully.
635 EFI_OUT_OF_RESOURCES - Not enough memory to perform the operation.
636 other - An error occurred when writing disk.
646 AppendedSize
= OFile
->FileSize
- WritePos
;
647 BufferSize
= AppendedSize
;
648 if (AppendedSize
> FAT_MAX_ALLOCATE_SIZE
) {
650 // If the appended size is larger, maybe we can not allocate the whole
651 // memory once. So if the growed size is larger than 10M, we just
652 // allocate 10M memory (one healthy system should have 10M available
653 // memory), and then write the zerobuffer to the file several times.
655 BufferSize
= FAT_MAX_ALLOCATE_SIZE
;
658 ZeroBuffer
= AllocateZeroPool (BufferSize
);
659 if (ZeroBuffer
== NULL
) {
660 return EFI_OUT_OF_RESOURCES
;
664 WriteSize
= AppendedSize
> BufferSize
? BufferSize
: (UINTN
) AppendedSize
;
665 AppendedSize
-= WriteSize
;
666 Status
= FatAccessOFile (OFile
, WRITE_DATA
, WritePos
, &WriteSize
, ZeroBuffer
, NULL
);
667 if (EFI_ERROR (Status
)) {
671 WritePos
+= WriteSize
;
672 } while (AppendedSize
> 0);
674 FreePool (ZeroBuffer
);
681 IN UINTN TruncatedSize
687 Truncate the OFile to smaller file size.
691 OFile - The open file.
692 TruncatedSize - The new file size.
696 EFI_SUCCESS - The file is truncated successfully.
697 other - An error occurred when truncating file.
701 OFile
->FileSize
= TruncatedSize
;
702 return FatShrinkEof (OFile
);