Info.c 16 KB

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