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