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