]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/EnhancedFatDxe/Info.c
FatPkg/EnhancedFatDxe: Make the comments align with EDKIIcoding style
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / Info.c
CommitLineData
cae7420b
DB
1/** @file\r
2 Routines dealing with setting/getting file/volume info\r
b9ec9330 3\r
55248f85 4Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
6163cc98 5This program and the accompanying materials are licensed and made available\r
b9ec9330
QH
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
b9ec9330 14\r
cae7420b 15**/\r
b9ec9330
QH
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
5d7cee9d
DB
29 IN UINTN BufferSize,\r
30 IN VOID *Buffer\r
b9ec9330
QH
31 );\r
32\r
33EFI_STATUS\r
34FatSetOrGetInfo (\r
dba03ba1
QH
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
b9ec9330
QH
40 );\r
41\r
cae7420b
DB
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
b9ec9330
QH
54EFI_STATUS\r
55FatGetFileInfo (\r
56 IN FAT_OFILE *OFile,\r
57 IN OUT UINTN *BufferSize,\r
58 OUT VOID *Buffer\r
59 )\r
cae7420b
DB
60{\r
61 return FatGetDirEntInfo (OFile->Volume, OFile->DirEnt, BufferSize, Buffer);\r
62}\r
b9ec9330 63\r
cae7420b 64/**\r
b9ec9330 65\r
cae7420b 66 Get the volume's info into Buffer.\r
b9ec9330 67\r
cae7420b
DB
68 @param Volume - FAT file system volume.\r
69 @param BufferSize - Size of Buffer.\r
70 @param Buffer - Buffer containing volume info.\r
b9ec9330 71\r
cae7420b
DB
72 @retval EFI_SUCCESS - Get the volume info successfully.\r
73 @retval EFI_BUFFER_TOO_SMALL - The buffer is too small.\r
b9ec9330 74\r
cae7420b 75**/\r
b9ec9330
QH
76EFI_STATUS\r
77FatGetVolumeInfo (\r
78 IN FAT_VOLUME *Volume,\r
79 IN OUT UINTN *BufferSize,\r
80 OUT VOID *Buffer\r
81 )\r
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330
QH
136EFI_STATUS\r
137FatGetVolumeLabelInfo (\r
138 IN FAT_VOLUME *Volume,\r
139 IN OUT UINTN *BufferSize,\r
140 OUT VOID *Buffer\r
141 )\r
b9ec9330
QH
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
80d70ac3 149 Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL;\r
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330
QH
178EFI_STATUS\r
179FatSetVolumeInfo (\r
180 IN FAT_VOLUME *Volume,\r
181 IN UINTN BufferSize,\r
182 IN VOID *Buffer\r
183 )\r
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330
QH
210EFI_STATUS\r
211FatSetVolumeLabelInfo (\r
212 IN FAT_VOLUME *Volume,\r
213 IN UINTN BufferSize,\r
214 IN VOID *Buffer\r
215 )\r
b9ec9330 216{\r
80d70ac3 217 EFI_FILE_SYSTEM_VOLUME_LABEL *Info;\r
b9ec9330 218\r
80d70ac3 219 Info = (EFI_FILE_SYSTEM_VOLUME_LABEL *) Buffer;\r
b9ec9330 220\r
80d70ac3 221 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 2) {\r
b9ec9330
QH
222 return EFI_BAD_BUFFER_SIZE;\r
223 }\r
224\r
225 return FatSetVolumeEntry (Volume, Info->VolumeLabel);\r
226}\r
227\r
cae7420b
DB
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
b9ec9330
QH
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
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330
QH
445EFI_STATUS\r
446FatSetOrGetInfo (\r
dba03ba1
QH
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
b9ec9330 452 )\r
b9ec9330
QH
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
149d6335
RN
468 FatWaitNonblockingTask (IFile);\r
469\r
b9ec9330
QH
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
55248f85
RN
481 if (CompareGuid (Type, &gEfiFileInfoGuid)) {\r
482 Status = Volume->ReadOnly ? EFI_WRITE_PROTECTED : FatSetFileInfo (Volume, IFile, OFile, *BufferSize, Buffer);\r
483 }\r
b9ec9330 484\r
55248f85
RN
485 if (CompareGuid (Type, &gEfiFileSystemInfoGuid)) {\r
486 Status = Volume->ReadOnly ? EFI_WRITE_PROTECTED : FatSetVolumeInfo (Volume, *BufferSize, Buffer);\r
487 }\r
b9ec9330 488\r
55248f85
RN
489 if (CompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
490 Status = Volume->ReadOnly ? EFI_WRITE_PROTECTED : FatSetVolumeLabelInfo (Volume, *BufferSize, Buffer);\r
b9ec9330
QH
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
149d6335 507 Status = FatCleanupVolume (Volume, NULL, Status, NULL);\r
b9ec9330
QH
508\r
509 FatReleaseLock ();\r
510 return Status;\r
511}\r
512\r
cae7420b
DB
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
b9ec9330
QH
526EFI_STATUS\r
527EFIAPI\r
528FatGetInfo (\r
dba03ba1
QH
529 IN EFI_FILE_PROTOCOL *FHand,\r
530 IN EFI_GUID *Type,\r
531 IN OUT UINTN *BufferSize,\r
532 OUT VOID *Buffer\r
b9ec9330 533 )\r
cae7420b
DB
534{\r
535 return FatSetOrGetInfo (FALSE, FHand, Type, BufferSize, Buffer);\r
536}\r
b9ec9330 537\r
cae7420b 538/**\r
b9ec9330 539\r
cae7420b 540 Set the some types info of the file into Buffer.\r
b9ec9330 541\r
cae7420b
DB
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
b9ec9330 546\r
cae7420b
DB
547 @retval EFI_SUCCESS - Set the info successfully.\r
548 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.\r
b9ec9330 549\r
cae7420b 550**/\r
b9ec9330
QH
551EFI_STATUS\r
552EFIAPI\r
553FatSetInfo (\r
dba03ba1
QH
554 IN EFI_FILE_PROTOCOL *FHand,\r
555 IN EFI_GUID *Type,\r
556 IN UINTN BufferSize,\r
557 IN VOID *Buffer\r
b9ec9330 558 )\r
b9ec9330
QH
559{\r
560 return FatSetOrGetInfo (TRUE, FHand, Type, &BufferSize, Buffer);\r
561}\r