]> git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/EnhancedFatDxe/Info.c
FatPkg/EnhancedFatDxe: Add comments for functions
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / Info.c
1 /** @file
2 Routines dealing with setting/getting file/volume info
3
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
9
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.
12
13
14
15 **/
16
17 #include "Fat.h"
18
19 /**
20
21 Get the volume's info into Buffer.
22
23 @param Volume - FAT file system volume.
24 @param BufferSize - Size of Buffer.
25 @param Buffer - Buffer containing volume info.
26
27 @retval EFI_SUCCESS - Get the volume info successfully.
28 @retval EFI_BUFFER_TOO_SMALL - The buffer is too small.
29
30 **/
31 EFI_STATUS
32 FatGetVolumeInfo (
33 IN FAT_VOLUME *Volume,
34 IN OUT UINTN *BufferSize,
35 OUT VOID *Buffer
36 );
37
38 /**
39
40 Set the volume's info.
41
42 @param Volume - FAT file system volume.
43 @param BufferSize - Size of Buffer.
44 @param Buffer - Buffer containing the new volume info.
45
46 @retval EFI_SUCCESS - Set the volume info successfully.
47 @retval EFI_BAD_BUFFER_SIZE - The buffer size is error.
48 @retval EFI_WRITE_PROTECTED - The volume is read only.
49 @return other - An error occurred when operation the disk.
50
51 **/
52 EFI_STATUS
53 FatSetVolumeInfo (
54 IN FAT_VOLUME *Volume,
55 IN UINTN BufferSize,
56 IN VOID *Buffer
57 );
58
59 /**
60
61 Set or Get the some types info of the file into Buffer.
62
63 @param IsSet - TRUE:The access is set, else is get
64 @param FHand - The handle of file
65 @param Type - The type of the info
66 @param BufferSize - Size of Buffer
67 @param Buffer - Buffer containing volume info
68
69 @retval EFI_SUCCESS - Get the info successfully
70 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file
71
72 **/
73 EFI_STATUS
74 FatSetOrGetInfo (
75 IN BOOLEAN IsSet,
76 IN EFI_FILE_PROTOCOL *FHand,
77 IN EFI_GUID *Type,
78 IN OUT UINTN *BufferSize,
79 IN OUT VOID *Buffer
80 );
81
82 /**
83
84 Get the open file's info into Buffer.
85
86 @param OFile - The open file.
87 @param BufferSize - Size of Buffer.
88 @param Buffer - Buffer containing file info.
89
90 @retval EFI_SUCCESS - Get the file info successfully.
91 @retval EFI_BUFFER_TOO_SMALL - The buffer is too small.
92
93 **/
94 EFI_STATUS
95 FatGetFileInfo (
96 IN FAT_OFILE *OFile,
97 IN OUT UINTN *BufferSize,
98 OUT VOID *Buffer
99 )
100 {
101 return FatGetDirEntInfo (OFile->Volume, OFile->DirEnt, BufferSize, Buffer);
102 }
103
104 /**
105
106 Get the volume's info into Buffer.
107
108 @param Volume - FAT file system volume.
109 @param BufferSize - Size of Buffer.
110 @param Buffer - Buffer containing volume info.
111
112 @retval EFI_SUCCESS - Get the volume info successfully.
113 @retval EFI_BUFFER_TOO_SMALL - The buffer is too small.
114
115 **/
116 EFI_STATUS
117 FatGetVolumeInfo (
118 IN FAT_VOLUME *Volume,
119 IN OUT UINTN *BufferSize,
120 OUT VOID *Buffer
121 )
122 {
123 UINTN Size;
124 UINTN NameSize;
125 UINTN ResultSize;
126 CHAR16 Name[FAT_NAME_LEN + 1];
127 EFI_STATUS Status;
128 EFI_FILE_SYSTEM_INFO *Info;
129 UINT8 ClusterAlignment;
130
131 Size = SIZE_OF_EFI_FILE_SYSTEM_INFO;
132 Status = FatGetVolumeEntry (Volume, Name);
133 NameSize = StrSize (Name);
134 ResultSize = Size + NameSize;
135 ClusterAlignment = Volume->ClusterAlignment;
136
137 //
138 // If we don't have valid info, compute it now
139 //
140 FatComputeFreeInfo (Volume);
141
142 Status = EFI_BUFFER_TOO_SMALL;
143 if (*BufferSize >= ResultSize) {
144 Status = EFI_SUCCESS;
145
146 Info = Buffer;
147 ZeroMem (Info, SIZE_OF_EFI_FILE_SYSTEM_INFO);
148
149 Info->Size = ResultSize;
150 Info->ReadOnly = Volume->ReadOnly;
151 Info->BlockSize = (UINT32) Volume->ClusterSize;
152 Info->VolumeSize = LShiftU64 (Volume->MaxCluster, ClusterAlignment);
153 Info->FreeSpace = LShiftU64 (
154 Volume->FatInfoSector.FreeInfo.ClusterCount,
155 ClusterAlignment
156 );
157 CopyMem ((CHAR8 *) Buffer + Size, Name, NameSize);
158 }
159
160 *BufferSize = ResultSize;
161 return Status;
162 }
163
164 /**
165
166 Get the volume's label info into Buffer.
167
168 @param Volume - FAT file system volume.
169 @param BufferSize - Size of Buffer.
170 @param Buffer - Buffer containing volume's label info.
171
172 @retval EFI_SUCCESS - Get the volume's label info successfully.
173 @retval EFI_BUFFER_TOO_SMALL - The buffer is too small.
174
175 **/
176 EFI_STATUS
177 FatGetVolumeLabelInfo (
178 IN FAT_VOLUME *Volume,
179 IN OUT UINTN *BufferSize,
180 OUT VOID *Buffer
181 )
182 {
183 UINTN Size;
184 UINTN NameSize;
185 UINTN ResultSize;
186 CHAR16 Name[FAT_NAME_LEN + 1];
187 EFI_STATUS Status;
188
189 Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL;
190 Status = FatGetVolumeEntry (Volume, Name);
191 NameSize = StrSize (Name);
192 ResultSize = Size + NameSize;
193
194 Status = EFI_BUFFER_TOO_SMALL;
195 if (*BufferSize >= ResultSize) {
196 Status = EFI_SUCCESS;
197 CopyMem ((CHAR8 *) Buffer + Size, Name, NameSize);
198 }
199
200 *BufferSize = ResultSize;
201 return Status;
202 }
203
204 /**
205
206 Set the volume's info.
207
208 @param Volume - FAT file system volume.
209 @param BufferSize - Size of Buffer.
210 @param Buffer - Buffer containing the new volume info.
211
212 @retval EFI_SUCCESS - Set the volume info successfully.
213 @retval EFI_BAD_BUFFER_SIZE - The buffer size is error.
214 @retval EFI_WRITE_PROTECTED - The volume is read only.
215 @return other - An error occurred when operation the disk.
216
217 **/
218 EFI_STATUS
219 FatSetVolumeInfo (
220 IN FAT_VOLUME *Volume,
221 IN UINTN BufferSize,
222 IN VOID *Buffer
223 )
224 {
225 EFI_FILE_SYSTEM_INFO *Info;
226
227 Info = (EFI_FILE_SYSTEM_INFO *) Buffer;
228
229 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + 2 || Info->Size > BufferSize) {
230 return EFI_BAD_BUFFER_SIZE;
231 }
232
233 return FatSetVolumeEntry (Volume, Info->VolumeLabel);
234 }
235
236 /**
237
238 Set the volume's label info.
239
240 @param Volume - FAT file system volume.
241 @param BufferSize - Size of Buffer.
242 @param Buffer - Buffer containing the new volume label info.
243
244 @retval EFI_SUCCESS - Set the volume label info successfully.
245 @retval EFI_WRITE_PROTECTED - The disk is write protected.
246 @retval EFI_BAD_BUFFER_SIZE - The buffer size is error.
247 @return other - An error occurred when operation the disk.
248
249 **/
250 EFI_STATUS
251 FatSetVolumeLabelInfo (
252 IN FAT_VOLUME *Volume,
253 IN UINTN BufferSize,
254 IN VOID *Buffer
255 )
256 {
257 EFI_FILE_SYSTEM_VOLUME_LABEL *Info;
258
259 Info = (EFI_FILE_SYSTEM_VOLUME_LABEL *) Buffer;
260
261 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 2) {
262 return EFI_BAD_BUFFER_SIZE;
263 }
264
265 return FatSetVolumeEntry (Volume, Info->VolumeLabel);
266 }
267
268 /**
269
270 Set the file info.
271
272 @param Volume - FAT file system volume.
273 @param IFile - The instance of the open file.
274 @param OFile - The open file.
275 @param BufferSize - Size of Buffer.
276 @param Buffer - Buffer containing the new file info.
277
278 @retval EFI_SUCCESS - Set the file info successfully.
279 @retval EFI_ACCESS_DENIED - It is the root directory
280 or the directory attribute bit can not change
281 or try to change a directory size
282 or something else.
283 @retval EFI_UNSUPPORTED - The new file size is larger than 4GB.
284 @retval EFI_WRITE_PROTECTED - The disk is write protected.
285 @retval EFI_BAD_BUFFER_SIZE - The buffer size is error.
286 @retval EFI_INVALID_PARAMETER - The time info or attributes info is error.
287 @retval EFI_OUT_OF_RESOURCES - Can not allocate new memory.
288 @retval EFI_VOLUME_CORRUPTED - The volume is corrupted.
289 @return other - An error occurred when operation the disk.
290
291 **/
292 EFI_STATUS
293 FatSetFileInfo (
294 IN FAT_VOLUME *Volume,
295 IN FAT_IFILE *IFile,
296 IN FAT_OFILE *OFile,
297 IN UINTN BufferSize,
298 IN VOID *Buffer
299 )
300 {
301 EFI_STATUS Status;
302 EFI_FILE_INFO *NewInfo;
303 FAT_OFILE *DotOFile;
304 FAT_OFILE *Parent;
305 CHAR16 NewFileName[EFI_PATH_STRING_LENGTH];
306 EFI_TIME ZeroTime;
307 FAT_DIRENT *DirEnt;
308 FAT_DIRENT *TempDirEnt;
309 UINT8 NewAttribute;
310 BOOLEAN ReadOnly;
311
312 ZeroMem (&ZeroTime, sizeof (EFI_TIME));
313 Parent = OFile->Parent;
314 DirEnt = OFile->DirEnt;
315 //
316 // If this is the root directory, we can't make any updates
317 //
318 if (Parent == NULL) {
319 return EFI_ACCESS_DENIED;
320 }
321 //
322 // Make sure there's a valid input buffer
323 //
324 NewInfo = Buffer;
325 if (BufferSize < SIZE_OF_EFI_FILE_INFO + 2 || NewInfo->Size > BufferSize) {
326 return EFI_BAD_BUFFER_SIZE;
327 }
328
329 ReadOnly = (BOOLEAN)(IFile->ReadOnly || (DirEnt->Entry.Attributes & EFI_FILE_READ_ONLY));
330 //
331 // if a zero time is specified, then the original time is preserved
332 //
333 if (CompareMem (&ZeroTime, &NewInfo->CreateTime, sizeof (EFI_TIME)) != 0) {
334 if (!FatIsValidTime (&NewInfo->CreateTime)) {
335 return EFI_INVALID_PARAMETER;
336 }
337
338 if (!ReadOnly) {
339 FatEfiTimeToFatTime (&NewInfo->CreateTime, &DirEnt->Entry.FileCreateTime);
340 }
341 }
342
343 if (CompareMem (&ZeroTime, &NewInfo->ModificationTime, sizeof (EFI_TIME)) != 0) {
344 if (!FatIsValidTime (&NewInfo->ModificationTime)) {
345 return EFI_INVALID_PARAMETER;
346 }
347
348 if (!ReadOnly) {
349 FatEfiTimeToFatTime (&NewInfo->ModificationTime, &DirEnt->Entry.FileModificationTime);
350 }
351
352 OFile->PreserveLastModification = TRUE;
353 }
354
355 if (NewInfo->Attribute & (~EFI_FILE_VALID_ATTR)) {
356 return EFI_INVALID_PARAMETER;
357 }
358
359 NewAttribute = (UINT8) NewInfo->Attribute;
360 //
361 // Can not change the directory attribute bit
362 //
363 if ((NewAttribute ^ DirEnt->Entry.Attributes) & EFI_FILE_DIRECTORY) {
364 return EFI_ACCESS_DENIED;
365 }
366 //
367 // Set the current attributes even if the IFile->ReadOnly is TRUE
368 //
369 DirEnt->Entry.Attributes = (UINT8) ((DirEnt->Entry.Attributes &~EFI_FILE_VALID_ATTR) | NewAttribute);
370 //
371 // Open the filename and see if it refers to an existing file
372 //
373 Status = FatLocateOFile (&Parent, NewInfo->FileName, DirEnt->Entry.Attributes, NewFileName);
374 if (EFI_ERROR (Status)) {
375 return Status;
376 }
377
378 if (*NewFileName != 0) {
379 //
380 // File was not found. We do not allow rename of the current directory if
381 // there are open files below the current directory
382 //
383 if (!IsListEmpty (&OFile->ChildHead) || Parent == OFile) {
384 return EFI_ACCESS_DENIED;
385 }
386
387 if (ReadOnly) {
388 return EFI_ACCESS_DENIED;
389 }
390
391 Status = FatRemoveDirEnt (OFile->Parent, DirEnt);
392 if (EFI_ERROR (Status)) {
393 return Status;
394 }
395 //
396 // Create new dirent
397 //
398 Status = FatCreateDirEnt (Parent, NewFileName, DirEnt->Entry.Attributes, &TempDirEnt);
399 if (EFI_ERROR (Status)) {
400 return Status;
401 }
402
403 FatCloneDirEnt (TempDirEnt, DirEnt);
404 FatFreeDirEnt (DirEnt);
405 DirEnt = TempDirEnt;
406 DirEnt->OFile = OFile;
407 OFile->DirEnt = DirEnt;
408 OFile->Parent = Parent;
409 RemoveEntryList (&OFile->ChildLink);
410 InsertHeadList (&Parent->ChildHead, &OFile->ChildLink);
411 //
412 // If this is a directory, synchronize its dot directory entry
413 //
414 if (OFile->ODir != NULL) {
415 //
416 // Syncronize its dot entry
417 //
418 FatResetODirCursor (OFile);
419 ASSERT (OFile->Parent != NULL);
420 for (DotOFile = OFile; DotOFile != OFile->Parent->Parent; DotOFile = DotOFile->Parent) {
421 Status = FatGetNextDirEnt (OFile, &DirEnt);
422 if (EFI_ERROR (Status) || DirEnt == NULL || !FatIsDotDirEnt (DirEnt)) {
423 return EFI_VOLUME_CORRUPTED;
424 }
425
426 FatCloneDirEnt (DirEnt, DotOFile->DirEnt);
427 Status = FatStoreDirEnt (OFile, DirEnt);
428 if (EFI_ERROR (Status)) {
429 return Status;
430 }
431 }
432 }
433 //
434 // If the file is renamed, we should append the ARCHIVE attribute
435 //
436 OFile->Archive = TRUE;
437 } else if (Parent != OFile) {
438 //
439 // filename is to a different filename that already exists
440 //
441 return EFI_ACCESS_DENIED;
442 }
443 //
444 // If the file size has changed, apply it
445 //
446 if (NewInfo->FileSize != OFile->FileSize) {
447 if (OFile->ODir != NULL || ReadOnly) {
448 //
449 // If this is a directory or the file is read only, we can't change the file size
450 //
451 return EFI_ACCESS_DENIED;
452 }
453
454 if (NewInfo->FileSize > OFile->FileSize) {
455 Status = FatExpandOFile (OFile, NewInfo->FileSize);
456 } else {
457 Status = FatTruncateOFile (OFile, (UINTN) NewInfo->FileSize);
458 }
459
460 if (EFI_ERROR (Status)) {
461 return Status;
462 }
463
464 FatUpdateDirEntClusterSizeInfo (OFile);
465 }
466
467 OFile->Dirty = TRUE;
468 return FatOFileFlush (OFile);
469 }
470
471 /**
472
473 Set or Get the some types info of the file into Buffer.
474
475 @param IsSet - TRUE:The access is set, else is get
476 @param FHand - The handle of file
477 @param Type - The type of the info
478 @param BufferSize - Size of Buffer
479 @param Buffer - Buffer containing volume info
480
481 @retval EFI_SUCCESS - Get the info successfully
482 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file
483
484 **/
485 EFI_STATUS
486 FatSetOrGetInfo (
487 IN BOOLEAN IsSet,
488 IN EFI_FILE_PROTOCOL *FHand,
489 IN EFI_GUID *Type,
490 IN OUT UINTN *BufferSize,
491 IN OUT VOID *Buffer
492 )
493 {
494 FAT_IFILE *IFile;
495 FAT_OFILE *OFile;
496 FAT_VOLUME *Volume;
497 EFI_STATUS Status;
498
499 IFile = IFILE_FROM_FHAND (FHand);
500 OFile = IFile->OFile;
501 Volume = OFile->Volume;
502
503 Status = OFile->Error;
504 if (Status == EFI_NOT_FOUND) {
505 return EFI_DEVICE_ERROR;
506 }
507
508 FatWaitNonblockingTask (IFile);
509
510 FatAcquireLock ();
511
512 //
513 // Verify the file handle isn't in an error state
514 //
515 if (!EFI_ERROR (Status)) {
516 //
517 // Get the proper information based on the request
518 //
519 Status = EFI_UNSUPPORTED;
520 if (IsSet) {
521 if (CompareGuid (Type, &gEfiFileInfoGuid)) {
522 Status = Volume->ReadOnly ? EFI_WRITE_PROTECTED : FatSetFileInfo (Volume, IFile, OFile, *BufferSize, Buffer);
523 }
524
525 if (CompareGuid (Type, &gEfiFileSystemInfoGuid)) {
526 Status = Volume->ReadOnly ? EFI_WRITE_PROTECTED : FatSetVolumeInfo (Volume, *BufferSize, Buffer);
527 }
528
529 if (CompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
530 Status = Volume->ReadOnly ? EFI_WRITE_PROTECTED : FatSetVolumeLabelInfo (Volume, *BufferSize, Buffer);
531 }
532 } else {
533 if (CompareGuid (Type, &gEfiFileInfoGuid)) {
534 Status = FatGetFileInfo (OFile, BufferSize, Buffer);
535 }
536
537 if (CompareGuid (Type, &gEfiFileSystemInfoGuid)) {
538 Status = FatGetVolumeInfo (Volume, BufferSize, Buffer);
539 }
540
541 if (CompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
542 Status = FatGetVolumeLabelInfo (Volume, BufferSize, Buffer);
543 }
544 }
545 }
546
547 Status = FatCleanupVolume (Volume, NULL, Status, NULL);
548
549 FatReleaseLock ();
550 return Status;
551 }
552
553 /**
554
555 Get the some types info of the file into Buffer.
556
557 @param FHand - The handle of file.
558 @param Type - The type of the info.
559 @param BufferSize - Size of Buffer.
560 @param Buffer - Buffer containing volume info.
561
562 @retval EFI_SUCCESS - Get the info successfully.
563 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
564
565 **/
566 EFI_STATUS
567 EFIAPI
568 FatGetInfo (
569 IN EFI_FILE_PROTOCOL *FHand,
570 IN EFI_GUID *Type,
571 IN OUT UINTN *BufferSize,
572 OUT VOID *Buffer
573 )
574 {
575 return FatSetOrGetInfo (FALSE, FHand, Type, BufferSize, Buffer);
576 }
577
578 /**
579
580 Set the some types info of the file into Buffer.
581
582 @param FHand - The handle of file.
583 @param Type - The type of the info.
584 @param BufferSize - Size of Buffer
585 @param Buffer - Buffer containing volume info.
586
587 @retval EFI_SUCCESS - Set the info successfully.
588 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.
589
590 **/
591 EFI_STATUS
592 EFIAPI
593 FatSetInfo (
594 IN EFI_FILE_PROTOCOL *FHand,
595 IN EFI_GUID *Type,
596 IN UINTN BufferSize,
597 IN VOID *Buffer
598 )
599 {
600 return FatSetOrGetInfo (TRUE, FHand, Type, &BufferSize, Buffer);
601 }