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