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