2 Functions that perform file read/write.
4 Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
14 Get the file's position of the file.
17 @param FHand - The handle of file.
18 @param Position - The file's position of the file.
20 @retval EFI_SUCCESS - Get the info successfully.
21 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
22 @retval EFI_UNSUPPORTED - The open file is not a file.
28 IN EFI_FILE_PROTOCOL
*FHand
,
35 IFile
= IFILE_FROM_FHAND (FHand
);
38 if (OFile
->Error
== EFI_NOT_FOUND
) {
39 return EFI_DEVICE_ERROR
;
42 if (OFile
->ODir
!= NULL
) {
43 return EFI_UNSUPPORTED
;
46 *Position
= IFile
->Position
;
52 Set the file's position of the file.
54 @param FHand - The handle of file.
55 @param Position - The file's position of the file.
57 @retval EFI_SUCCESS - Set the info successfully.
58 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
59 @retval EFI_UNSUPPORTED - Set a directory with a not-zero position.
65 IN EFI_FILE_PROTOCOL
*FHand
,
72 IFile
= IFILE_FROM_FHAND (FHand
);
75 if (OFile
->Error
== EFI_NOT_FOUND
) {
76 return EFI_DEVICE_ERROR
;
79 FatWaitNonblockingTask (IFile
);
82 // If this is a directory, we can only set back to position 0
84 if (OFile
->ODir
!= NULL
) {
87 // Reset current directory cursor;
89 return EFI_UNSUPPORTED
;
92 FatResetODirCursor (OFile
);
98 if (Position
== (UINT64
)-1) {
99 Position
= OFile
->FileSize
;
105 IFile
->Position
= Position
;
111 Get the file info from the open file of the IFile into Buffer.
113 @param IFile - The instance of the open file.
114 @param BufferSize - Size of Buffer.
115 @param Buffer - Buffer containing read data.
117 @retval EFI_SUCCESS - Get the file info successfully.
118 @retval other - An error occurred when operation the disk.
124 IN OUT UINTN
*BufferSize
,
134 OFile
= IFile
->OFile
;
136 CurrentPos
= ((UINT32
)IFile
->Position
) / sizeof (FAT_DIRECTORY_ENTRY
);
139 // We need to relocate the directory
141 if (CurrentPos
< ODir
->CurrentPos
) {
143 // The directory cursor has been modified by another IFile, we reset the cursor
145 FatResetODirCursor (OFile
);
149 // We seek the next directory entry's position
152 Status
= FatGetNextDirEnt (OFile
, &DirEnt
);
153 if (EFI_ERROR (Status
) || (DirEnt
== NULL
)) {
155 // Something error occurred or reach the end of directory,
156 // return 0 buffersize
161 } while (ODir
->CurrentPos
<= CurrentPos
);
163 Status
= FatGetDirEntInfo (OFile
->Volume
, DirEnt
, BufferSize
, Buffer
);
167 // Update IFile's Position
169 if (!EFI_ERROR (Status
)) {
171 // Update IFile->Position, if everything is all right
173 CurrentPos
= ODir
->CurrentPos
;
174 IFile
->Position
= CurrentPos
* sizeof (FAT_DIRECTORY_ENTRY
);
182 Get the file info from the open file of the IFile into Buffer.
184 @param FHand - The file handle to access.
185 @param IoMode - Indicate whether the access mode is reading or writing.
186 @param BufferSize - Size of Buffer.
187 @param Buffer - Buffer containing read data.
188 @param Token - A pointer to the token associated with the transaction.
190 @retval EFI_SUCCESS - Get the file info successfully.
191 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
192 @retval EFI_VOLUME_CORRUPTED - The file type of open file is error.
193 @retval EFI_WRITE_PROTECTED - The disk is write protect.
194 @retval EFI_ACCESS_DENIED - The file is read-only.
195 @return other - An error occurred when operating on the disk.
200 IN EFI_FILE_PROTOCOL
*FHand
,
202 IN OUT UINTN
*BufferSize
,
204 IN EFI_FILE_IO_TOKEN
*Token
214 IFile
= IFILE_FROM_FHAND (FHand
);
215 OFile
= IFile
->OFile
;
216 Volume
= OFile
->Volume
;
220 // Write to a directory is unsupported
222 if ((OFile
->ODir
!= NULL
) && (IoMode
== WriteData
)) {
223 return EFI_UNSUPPORTED
;
226 if (OFile
->Error
== EFI_NOT_FOUND
) {
227 return EFI_DEVICE_ERROR
;
230 if (IoMode
== ReadData
) {
232 // If position is at EOF, then return device error
234 if (IFile
->Position
> OFile
->FileSize
) {
235 return EFI_DEVICE_ERROR
;
239 // Check if the we can write data
241 if (Volume
->ReadOnly
) {
242 return EFI_WRITE_PROTECTED
;
245 if (IFile
->ReadOnly
) {
246 return EFI_ACCESS_DENIED
;
251 FatWaitNonblockingTask (IFile
);
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.
257 if (FHand
->Revision
< EFI_FILE_PROTOCOL_REVISION2
) {
258 return EFI_UNSUPPORTED
;
261 Task
= FatCreateTask (IFile
, Token
);
263 return EFI_OUT_OF_RESOURCES
;
269 Status
= OFile
->Error
;
270 if (!EFI_ERROR (Status
)) {
271 if (OFile
->ODir
!= NULL
) {
273 // Read a directory is supported
275 ASSERT (IoMode
== ReadData
);
276 Status
= FatIFileReadDir (IFile
, BufferSize
, Buffer
);
282 EndPosition
= IFile
->Position
+ *BufferSize
;
283 if (EndPosition
> OFile
->FileSize
) {
285 // The position goes beyond the end of file
287 if (IoMode
== ReadData
) {
289 // Adjust the actual size read
291 *BufferSize
-= (UINTN
)EndPosition
- OFile
->FileSize
;
294 // We expand the file size of OFile
296 Status
= FatGrowEof (OFile
, EndPosition
);
297 if (EFI_ERROR (Status
)) {
299 // Must update the file's info into the file's Directory Entry
300 // and then flush the dirty cache info into disk.
303 FatOFileFlush (OFile
);
308 FatUpdateDirEntClusterSizeInfo (OFile
);
312 Status
= FatAccessOFile (OFile
, IoMode
, (UINTN
)IFile
->Position
, BufferSize
, Buffer
, Task
);
313 IFile
->Position
+= *BufferSize
;
318 if (!EFI_ERROR (Status
)) {
319 Status
= FatQueueTask (IFile
, Task
);
321 FatDestroyTask (Task
);
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.
335 if (EFI_ERROR (Status
)) {
336 Status
= FatCleanupVolume (Volume
, OFile
, Status
, NULL
);
347 @param FHand - The handle of the file.
348 @param BufferSize - Size of Buffer.
349 @param Buffer - Buffer containing read data.
352 @retval EFI_SUCCESS - Get the file info successfully.
353 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
354 @retval EFI_VOLUME_CORRUPTED - The file type of open file is error.
355 @return other - An error occurred when operation the disk.
361 IN EFI_FILE_PROTOCOL
*FHand
,
362 IN OUT UINTN
*BufferSize
,
366 return FatIFileAccess (FHand
, ReadData
, BufferSize
, Buffer
, NULL
);
373 @param FHand - The handle of the file.
374 @param Token - A pointer to the token associated with the transaction.
376 @retval EFI_SUCCESS - Get the file info successfully.
377 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
378 @retval EFI_VOLUME_CORRUPTED - The file type of open file is error.
379 @return other - An error occurred when operation the disk.
385 IN EFI_FILE_PROTOCOL
*FHand
,
386 IN OUT EFI_FILE_IO_TOKEN
*Token
389 return FatIFileAccess (FHand
, ReadData
, &Token
->BufferSize
, Token
->Buffer
, Token
);
394 Write the content of buffer into files.
396 @param FHand - The handle of the file.
397 @param BufferSize - Size of Buffer.
398 @param Buffer - Buffer containing write data.
400 @retval EFI_SUCCESS - Set the file info successfully.
401 @retval EFI_WRITE_PROTECTED - The disk is write protect.
402 @retval EFI_ACCESS_DENIED - The file is read-only.
403 @retval EFI_DEVICE_ERROR - The OFile is not valid.
404 @retval EFI_UNSUPPORTED - The open file is not a file.
405 - The writing file size is larger than 4GB.
406 @return other - An error occurred when operation the disk.
412 IN EFI_FILE_PROTOCOL
*FHand
,
413 IN OUT UINTN
*BufferSize
,
417 return FatIFileAccess (FHand
, WriteData
, BufferSize
, Buffer
, NULL
);
424 @param FHand - The handle of the file.
425 @param Token - A pointer to the token associated with the transaction.
427 @retval EFI_SUCCESS - Get the file info successfully.
428 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
429 @retval EFI_VOLUME_CORRUPTED - The file type of open file is error.
430 @return other - An error occurred when operation the disk.
436 IN EFI_FILE_PROTOCOL
*FHand
,
437 IN OUT EFI_FILE_IO_TOKEN
*Token
440 return FatIFileAccess (FHand
, WriteData
, &Token
->BufferSize
, Token
->Buffer
, Token
);
445 This function reads data from a file or writes data to a file.
446 It uses OFile->PosRem to determine how much data can be accessed in one time.
448 @param OFile - The open file.
449 @param IoMode - Indicate whether the access mode is reading or writing.
450 @param Position - The position where data will be accessed.
451 @param DataBufferSize - Size of Buffer.
452 @param UserBuffer - Buffer containing data.
453 @param Task point to task instance.
455 @retval EFI_SUCCESS - Access the data successfully.
456 @return other - An error occurred when operating on the disk.
464 IN OUT UINTN
*DataBufferSize
,
465 IN OUT UINT8
*UserBuffer
,
474 BufferSize
= *DataBufferSize
;
475 Volume
= OFile
->Volume
;
476 ASSERT_VOLUME_LOCKED (Volume
);
478 Status
= EFI_SUCCESS
;
479 while (BufferSize
> 0) {
481 // Seek the OFile to the file position
483 Status
= FatOFilePosition (OFile
, Position
, BufferSize
);
484 if (EFI_ERROR (Status
)) {
489 // Clip length to block run
491 Len
= BufferSize
> OFile
->PosRem
? OFile
->PosRem
: BufferSize
;
496 Status
= FatDiskIo (Volume
, IoMode
, OFile
->PosDisk
, Len
, UserBuffer
, Task
);
497 if (EFI_ERROR (Status
)) {
502 // Data was successfully accessed
507 if (IoMode
== WriteData
) {
509 OFile
->Archive
= TRUE
;
513 // Make sure no outbound occurred
515 ASSERT (Position
<= OFile
->FileSize
);
519 // Update the number of bytes accessed
521 *DataBufferSize
-= BufferSize
;
527 Expand OFile by appending zero bytes at the end of OFile.
529 @param OFile - The open file.
530 @param ExpandedSize - The number of zero bytes appended at the end of the file.
532 @retval EFI_SUCCESS - The file is expanded successfully.
533 @return other - An error occurred when expanding file.
539 IN UINT64 ExpandedSize
545 WritePos
= OFile
->FileSize
;
546 Status
= FatGrowEof (OFile
, ExpandedSize
);
547 if (!EFI_ERROR (Status
)) {
548 Status
= FatWriteZeroPool (OFile
, WritePos
);
556 Write zero pool from the WritePos to the end of OFile.
558 @param OFile - The open file to write zero pool.
559 @param WritePos - The number of zero bytes written.
561 @retval EFI_SUCCESS - Write the zero pool successfully.
562 @retval EFI_OUT_OF_RESOURCES - Not enough memory to perform the operation.
563 @return other - An error occurred when writing disk.
578 AppendedSize
= OFile
->FileSize
- WritePos
;
579 BufferSize
= AppendedSize
;
580 if (AppendedSize
> FAT_MAX_ALLOCATE_SIZE
) {
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.
587 BufferSize
= FAT_MAX_ALLOCATE_SIZE
;
590 ZeroBuffer
= AllocateZeroPool (BufferSize
);
591 if (ZeroBuffer
== NULL
) {
592 return EFI_OUT_OF_RESOURCES
;
596 WriteSize
= AppendedSize
> BufferSize
? BufferSize
: (UINTN
)AppendedSize
;
597 AppendedSize
-= WriteSize
;
598 Status
= FatAccessOFile (OFile
, WriteData
, WritePos
, &WriteSize
, ZeroBuffer
, NULL
);
599 if (EFI_ERROR (Status
)) {
603 WritePos
+= WriteSize
;
604 } while (AppendedSize
> 0);
606 FreePool (ZeroBuffer
);
612 Truncate the OFile to smaller file size.
614 @param OFile - The open file.
615 @param TruncatedSize - The new file size.
617 @retval EFI_SUCCESS - The file is truncated successfully.
618 @return other - An error occurred when truncating file.
624 IN UINTN TruncatedSize
627 OFile
->FileSize
= TruncatedSize
;
628 return FatShrinkEof (OFile
);