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