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