2 Routines dealing with setting/getting file/volume info
4 Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 IN FAT_VOLUME
*Volume
,
22 IN OUT UINTN
*BufferSize
,
28 IN FAT_VOLUME
*Volume
,
36 IN EFI_FILE_PROTOCOL
*FHand
,
38 IN OUT UINTN
*BufferSize
,
44 Get the open file's info into Buffer.
46 @param OFile - The open file.
47 @param BufferSize - Size of Buffer.
48 @param Buffer - Buffer containing file info.
50 @retval EFI_SUCCESS - Get the file info successfully.
51 @retval EFI_BUFFER_TOO_SMALL - The buffer is too small.
57 IN OUT UINTN
*BufferSize
,
61 return FatGetDirEntInfo (OFile
->Volume
, OFile
->DirEnt
, BufferSize
, Buffer
);
66 Get the volume's info into Buffer.
68 @param Volume - FAT file system volume.
69 @param BufferSize - Size of Buffer.
70 @param Buffer - Buffer containing volume info.
72 @retval EFI_SUCCESS - Get the volume info successfully.
73 @retval EFI_BUFFER_TOO_SMALL - The buffer is too small.
78 IN FAT_VOLUME
*Volume
,
79 IN OUT UINTN
*BufferSize
,
86 CHAR16 Name
[FAT_NAME_LEN
+ 1];
88 EFI_FILE_SYSTEM_INFO
*Info
;
89 UINT8 ClusterAlignment
;
91 Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
92 Status
= FatGetVolumeEntry (Volume
, Name
);
93 NameSize
= StrSize (Name
);
94 ResultSize
= Size
+ NameSize
;
95 ClusterAlignment
= Volume
->ClusterAlignment
;
98 // If we don't have valid info, compute it now
100 FatComputeFreeInfo (Volume
);
102 Status
= EFI_BUFFER_TOO_SMALL
;
103 if (*BufferSize
>= ResultSize
) {
104 Status
= EFI_SUCCESS
;
107 ZeroMem (Info
, SIZE_OF_EFI_FILE_SYSTEM_INFO
);
109 Info
->Size
= ResultSize
;
110 Info
->ReadOnly
= Volume
->ReadOnly
;
111 Info
->BlockSize
= (UINT32
) Volume
->ClusterSize
;
112 Info
->VolumeSize
= LShiftU64 (Volume
->MaxCluster
, ClusterAlignment
);
113 Info
->FreeSpace
= LShiftU64 (
114 Volume
->FatInfoSector
.FreeInfo
.ClusterCount
,
117 CopyMem ((CHAR8
*) Buffer
+ Size
, Name
, NameSize
);
120 *BufferSize
= ResultSize
;
126 Get the volume's label info into Buffer.
128 @param Volume - FAT file system volume.
129 @param BufferSize - Size of Buffer.
130 @param Buffer - Buffer containing volume's label info.
132 @retval EFI_SUCCESS - Get the volume's label info successfully.
133 @retval EFI_BUFFER_TOO_SMALL - The buffer is too small.
137 FatGetVolumeLabelInfo (
138 IN FAT_VOLUME
*Volume
,
139 IN OUT UINTN
*BufferSize
,
146 CHAR16 Name
[FAT_NAME_LEN
+ 1];
149 Size
= SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL
;
150 Status
= FatGetVolumeEntry (Volume
, Name
);
151 NameSize
= StrSize (Name
);
152 ResultSize
= Size
+ NameSize
;
154 Status
= EFI_BUFFER_TOO_SMALL
;
155 if (*BufferSize
>= ResultSize
) {
156 Status
= EFI_SUCCESS
;
157 CopyMem ((CHAR8
*) Buffer
+ Size
, Name
, NameSize
);
160 *BufferSize
= ResultSize
;
166 Set the volume's info.
168 @param Volume - FAT file system volume.
169 @param BufferSize - Size of Buffer.
170 @param Buffer - Buffer containing the new volume info.
172 @retval EFI_SUCCESS - Set the volume info successfully.
173 @retval EFI_BAD_BUFFER_SIZE - The buffer size is error.
174 @retval EFI_WRITE_PROTECTED - The volume is read only.
175 @return other - An error occurred when operation the disk.
180 IN FAT_VOLUME
*Volume
,
185 EFI_FILE_SYSTEM_INFO
*Info
;
187 Info
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
189 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ 2 || Info
->Size
> BufferSize
) {
190 return EFI_BAD_BUFFER_SIZE
;
193 return FatSetVolumeEntry (Volume
, Info
->VolumeLabel
);
198 Set the volume's label info.
200 @param Volume - FAT file system volume.
201 @param BufferSize - Size of Buffer.
202 @param Buffer - Buffer containing the new volume label info.
204 @retval EFI_SUCCESS - Set the volume label info successfully.
205 @retval EFI_WRITE_PROTECTED - The disk is write protected.
206 @retval EFI_BAD_BUFFER_SIZE - The buffer size is error.
207 @return other - An error occurred when operation the disk.
211 FatSetVolumeLabelInfo (
212 IN FAT_VOLUME
*Volume
,
217 EFI_FILE_SYSTEM_VOLUME_LABEL
*Info
;
219 Info
= (EFI_FILE_SYSTEM_VOLUME_LABEL
*) Buffer
;
221 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL
+ 2) {
222 return EFI_BAD_BUFFER_SIZE
;
225 return FatSetVolumeEntry (Volume
, Info
->VolumeLabel
);
232 @param Volume - FAT file system volume.
233 @param IFile - The instance of the open file.
234 @param OFile - The open file.
235 @param BufferSize - Size of Buffer.
236 @param Buffer - Buffer containing the new file info.
238 @retval EFI_SUCCESS - Set the file info successfully.
239 @retval EFI_ACCESS_DENIED - It is the root directory
240 or the directory attribute bit can not change
241 or try to change a directory size
243 @retval EFI_UNSUPPORTED - The new file size is larger than 4GB.
244 @retval EFI_WRITE_PROTECTED - The disk is write protected.
245 @retval EFI_BAD_BUFFER_SIZE - The buffer size is error.
246 @retval EFI_INVALID_PARAMETER - The time info or attributes info is error.
247 @retval EFI_OUT_OF_RESOURCES - Can not allocate new memory.
248 @retval EFI_VOLUME_CORRUPTED - The volume is corrupted.
249 @return other - An error occurred when operation the disk.
254 IN FAT_VOLUME
*Volume
,
262 EFI_FILE_INFO
*NewInfo
;
265 CHAR16 NewFileName
[EFI_PATH_STRING_LENGTH
];
268 FAT_DIRENT
*TempDirEnt
;
272 ZeroMem (&ZeroTime
, sizeof (EFI_TIME
));
273 Parent
= OFile
->Parent
;
274 DirEnt
= OFile
->DirEnt
;
276 // If this is the root directory, we can't make any updates
278 if (Parent
== NULL
) {
279 return EFI_ACCESS_DENIED
;
282 // Make sure there's a valid input buffer
285 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
+ 2 || NewInfo
->Size
> BufferSize
) {
286 return EFI_BAD_BUFFER_SIZE
;
289 ReadOnly
= (BOOLEAN
)(IFile
->ReadOnly
|| (DirEnt
->Entry
.Attributes
& EFI_FILE_READ_ONLY
));
291 // if a zero time is specified, then the original time is preserved
293 if (CompareMem (&ZeroTime
, &NewInfo
->CreateTime
, sizeof (EFI_TIME
)) != 0) {
294 if (!FatIsValidTime (&NewInfo
->CreateTime
)) {
295 return EFI_INVALID_PARAMETER
;
299 FatEfiTimeToFatTime (&NewInfo
->CreateTime
, &DirEnt
->Entry
.FileCreateTime
);
303 if (CompareMem (&ZeroTime
, &NewInfo
->ModificationTime
, sizeof (EFI_TIME
)) != 0) {
304 if (!FatIsValidTime (&NewInfo
->ModificationTime
)) {
305 return EFI_INVALID_PARAMETER
;
309 FatEfiTimeToFatTime (&NewInfo
->ModificationTime
, &DirEnt
->Entry
.FileModificationTime
);
312 OFile
->PreserveLastModification
= TRUE
;
315 if (NewInfo
->Attribute
& (~EFI_FILE_VALID_ATTR
)) {
316 return EFI_INVALID_PARAMETER
;
319 NewAttribute
= (UINT8
) NewInfo
->Attribute
;
321 // Can not change the directory attribute bit
323 if ((NewAttribute
^ DirEnt
->Entry
.Attributes
) & EFI_FILE_DIRECTORY
) {
324 return EFI_ACCESS_DENIED
;
327 // Set the current attributes even if the IFile->ReadOnly is TRUE
329 DirEnt
->Entry
.Attributes
= (UINT8
) ((DirEnt
->Entry
.Attributes
&~EFI_FILE_VALID_ATTR
) | NewAttribute
);
331 // Open the filename and see if it refers to an existing file
333 Status
= FatLocateOFile (&Parent
, NewInfo
->FileName
, DirEnt
->Entry
.Attributes
, NewFileName
);
334 if (EFI_ERROR (Status
)) {
338 if (*NewFileName
!= 0) {
340 // File was not found. We do not allow rename of the current directory if
341 // there are open files below the current directory
343 if (!IsListEmpty (&OFile
->ChildHead
) || Parent
== OFile
) {
344 return EFI_ACCESS_DENIED
;
348 return EFI_ACCESS_DENIED
;
351 Status
= FatRemoveDirEnt (OFile
->Parent
, DirEnt
);
352 if (EFI_ERROR (Status
)) {
358 Status
= FatCreateDirEnt (Parent
, NewFileName
, DirEnt
->Entry
.Attributes
, &TempDirEnt
);
359 if (EFI_ERROR (Status
)) {
363 FatCloneDirEnt (TempDirEnt
, DirEnt
);
364 FatFreeDirEnt (DirEnt
);
366 DirEnt
->OFile
= OFile
;
367 OFile
->DirEnt
= DirEnt
;
368 OFile
->Parent
= Parent
;
369 RemoveEntryList (&OFile
->ChildLink
);
370 InsertHeadList (&Parent
->ChildHead
, &OFile
->ChildLink
);
372 // If this is a directory, synchronize its dot directory entry
374 if (OFile
->ODir
!= NULL
) {
376 // Syncronize its dot entry
378 FatResetODirCursor (OFile
);
379 ASSERT (OFile
->Parent
!= NULL
);
380 for (DotOFile
= OFile
; DotOFile
!= OFile
->Parent
->Parent
; DotOFile
= DotOFile
->Parent
) {
381 Status
= FatGetNextDirEnt (OFile
, &DirEnt
);
382 if (EFI_ERROR (Status
) || DirEnt
== NULL
|| !FatIsDotDirEnt (DirEnt
)) {
383 return EFI_VOLUME_CORRUPTED
;
386 FatCloneDirEnt (DirEnt
, DotOFile
->DirEnt
);
387 Status
= FatStoreDirEnt (OFile
, DirEnt
);
388 if (EFI_ERROR (Status
)) {
394 // If the file is renamed, we should append the ARCHIVE attribute
396 OFile
->Archive
= TRUE
;
397 } else if (Parent
!= OFile
) {
399 // filename is to a different filename that already exists
401 return EFI_ACCESS_DENIED
;
404 // If the file size has changed, apply it
406 if (NewInfo
->FileSize
!= OFile
->FileSize
) {
407 if (OFile
->ODir
!= NULL
|| ReadOnly
) {
409 // If this is a directory or the file is read only, we can't change the file size
411 return EFI_ACCESS_DENIED
;
414 if (NewInfo
->FileSize
> OFile
->FileSize
) {
415 Status
= FatExpandOFile (OFile
, NewInfo
->FileSize
);
417 Status
= FatTruncateOFile (OFile
, (UINTN
) NewInfo
->FileSize
);
420 if (EFI_ERROR (Status
)) {
424 FatUpdateDirEntClusterSizeInfo (OFile
);
428 return FatOFileFlush (OFile
);
433 Set or Get the some types info of the file into Buffer.
435 @param IsSet - TRUE:The access is set, else is get
436 @param FHand - The handle of file
437 @param Type - The type of the info
438 @param BufferSize - Size of Buffer
439 @param Buffer - Buffer containing volume info
441 @retval EFI_SUCCESS - Get the info successfully
442 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file
448 IN EFI_FILE_PROTOCOL
*FHand
,
450 IN OUT UINTN
*BufferSize
,
459 IFile
= IFILE_FROM_FHAND (FHand
);
460 OFile
= IFile
->OFile
;
461 Volume
= OFile
->Volume
;
463 Status
= OFile
->Error
;
464 if (Status
== EFI_NOT_FOUND
) {
465 return EFI_DEVICE_ERROR
;
468 FatWaitNonblockingTask (IFile
);
473 // Verify the file handle isn't in an error state
475 if (!EFI_ERROR (Status
)) {
477 // Get the proper information based on the request
479 Status
= EFI_UNSUPPORTED
;
481 if (CompareGuid (Type
, &gEfiFileInfoGuid
)) {
482 Status
= Volume
->ReadOnly
? EFI_WRITE_PROTECTED
: FatSetFileInfo (Volume
, IFile
, OFile
, *BufferSize
, Buffer
);
485 if (CompareGuid (Type
, &gEfiFileSystemInfoGuid
)) {
486 Status
= Volume
->ReadOnly
? EFI_WRITE_PROTECTED
: FatSetVolumeInfo (Volume
, *BufferSize
, Buffer
);
489 if (CompareGuid (Type
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
490 Status
= Volume
->ReadOnly
? EFI_WRITE_PROTECTED
: FatSetVolumeLabelInfo (Volume
, *BufferSize
, Buffer
);
493 if (CompareGuid (Type
, &gEfiFileInfoGuid
)) {
494 Status
= FatGetFileInfo (OFile
, BufferSize
, Buffer
);
497 if (CompareGuid (Type
, &gEfiFileSystemInfoGuid
)) {
498 Status
= FatGetVolumeInfo (Volume
, BufferSize
, Buffer
);
501 if (CompareGuid (Type
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
502 Status
= FatGetVolumeLabelInfo (Volume
, BufferSize
, Buffer
);
507 Status
= FatCleanupVolume (Volume
, NULL
, Status
, NULL
);
515 Get the some types info of the file into Buffer.
517 @param FHand - The handle of file.
518 @param Type - The type of the info.
519 @param BufferSize - Size of Buffer.
520 @param Buffer - Buffer containing volume info.
522 @retval EFI_SUCCESS - Get the info successfully.
523 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
529 IN EFI_FILE_PROTOCOL
*FHand
,
531 IN OUT UINTN
*BufferSize
,
535 return FatSetOrGetInfo (FALSE
, FHand
, Type
, BufferSize
, Buffer
);
540 Set the some types info of the file into Buffer.
542 @param FHand - The handle of file.
543 @param Type - The type of the info.
544 @param BufferSize - Size of Buffer
545 @param Buffer - Buffer containing volume info.
547 @retval EFI_SUCCESS - Set the info successfully.
548 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
554 IN EFI_FILE_PROTOCOL
*FHand
,
560 return FatSetOrGetInfo (TRUE
, FHand
, Type
, &BufferSize
, Buffer
);