]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Disk/UdfDxe/File.c
MdeModulePkg/UdfDxe: Update GetInfo() for FS VolumeLabel info request
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / UdfDxe / File.c
... / ...
CommitLineData
1/** @file\r
2 Handle operations in files and directories from UDF/ECMA-167 file systems.\r
3\r
4 Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>\r
5 Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
6\r
7 This program and the accompanying materials are licensed and made available\r
8 under the terms and conditions of the BSD License which accompanies this\r
9 distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
13 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14**/\r
15\r
16#include "Udf.h"\r
17\r
18EFI_FILE_PROTOCOL gUdfFileIoOps = {\r
19 EFI_FILE_PROTOCOL_REVISION,\r
20 UdfOpen,\r
21 UdfClose,\r
22 UdfDelete,\r
23 UdfRead,\r
24 UdfWrite,\r
25 UdfGetPosition,\r
26 UdfSetPosition,\r
27 UdfGetInfo,\r
28 UdfSetInfo,\r
29 UdfFlush,\r
30 NULL,\r
31 NULL,\r
32 NULL,\r
33 NULL\r
34};\r
35\r
36#define _ROOT_FILE(_PrivData) (_PrivData)->Root\r
37#define _PARENT_FILE(_PrivData) \\r
38 ((_PrivData)->IsRootDirectory ? (_PrivData)->Root : &(_PrivData)->File)\r
39#define _FILE(_PrivData) _PARENT_FILE(_PrivData)\r
40\r
41/**\r
42 Open the root directory on a volume.\r
43\r
44 @param This Protocol instance pointer.\r
45 @param Root Returns an Open file handle for the root directory\r
46\r
47 @retval EFI_SUCCESS The device was opened.\r
48 @retval EFI_UNSUPPORTED This volume does not support the file system.\r
49 @retval EFI_NO_MEDIA The device has no media.\r
50 @retval EFI_DEVICE_ERROR The device reported an error.\r
51 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
52 @retval EFI_ACCESS_DENIED The service denied access to the file.\r
53 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of\r
54 resources.\r
55\r
56**/\r
57EFI_STATUS\r
58EFIAPI\r
59UdfOpenVolume (\r
60 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
61 OUT EFI_FILE_PROTOCOL **Root\r
62 )\r
63{\r
64 EFI_TPL OldTpl;\r
65 EFI_STATUS Status;\r
66 PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;\r
67 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
68\r
69 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
70\r
71 if (This == NULL || Root == NULL) {\r
72 Status = EFI_INVALID_PARAMETER;\r
73 goto Error_Invalid_Params;\r
74 }\r
75\r
76 PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (This);\r
77\r
78 if (PrivFsData->OpenFiles == 0) {\r
79 //\r
80 // There is no more open files. Read volume information again since it was\r
81 // cleaned up on the last UdfClose() call.\r
82 //\r
83 Status = ReadUdfVolumeInformation (\r
84 PrivFsData->BlockIo,\r
85 PrivFsData->DiskIo,\r
86 &PrivFsData->Volume\r
87 );\r
88 if (EFI_ERROR (Status)) {\r
89 goto Error_Read_Udf_Volume;\r
90 }\r
91 }\r
92\r
93 CleanupFileInformation (&PrivFsData->Root);\r
94\r
95 //\r
96 // Find root directory file.\r
97 //\r
98 Status = FindRootDirectory (\r
99 PrivFsData->BlockIo,\r
100 PrivFsData->DiskIo,\r
101 &PrivFsData->Volume,\r
102 &PrivFsData->Root\r
103 );\r
104 if (EFI_ERROR (Status)) {\r
105 goto Error_Find_Root_Dir;\r
106 }\r
107\r
108 PrivFileData =\r
109 (PRIVATE_UDF_FILE_DATA *) AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));\r
110 if (PrivFileData == NULL) {\r
111 Status = EFI_OUT_OF_RESOURCES;\r
112 goto Error_Alloc_Priv_File_Data;\r
113 }\r
114\r
115 PrivFileData->Signature = PRIVATE_UDF_FILE_DATA_SIGNATURE;\r
116 PrivFileData->SimpleFs = This;\r
117 PrivFileData->Root = &PrivFsData->Root;\r
118 PrivFileData->IsRootDirectory = TRUE;\r
119\r
120 CopyMem ((VOID *)&PrivFileData->FileIo, (VOID *)&gUdfFileIoOps,\r
121 sizeof (EFI_FILE_PROTOCOL));\r
122\r
123 *Root = &PrivFileData->FileIo;\r
124\r
125 PrivFsData->OpenFiles++;\r
126\r
127 gBS->RestoreTPL (OldTpl);\r
128\r
129 return EFI_SUCCESS;\r
130\r
131Error_Alloc_Priv_File_Data:\r
132 CleanupFileInformation (&PrivFsData->Root);\r
133\r
134Error_Find_Root_Dir:\r
135\r
136Error_Read_Udf_Volume:\r
137Error_Invalid_Params:\r
138 gBS->RestoreTPL (OldTpl);\r
139\r
140 return Status;\r
141}\r
142\r
143/**\r
144 Opens a new file relative to the source file's location.\r
145\r
146 @param This The protocol instance pointer.\r
147 @param NewHandle Returns File Handle for FileName.\r
148 @param FileName Null terminated string. "\", ".", and ".." are supported.\r
149 @param OpenMode Open mode for file.\r
150 @param Attributes Only used for EFI_FILE_MODE_CREATE.\r
151\r
152 @retval EFI_SUCCESS The device was opened.\r
153 @retval EFI_NOT_FOUND The specified file could not be found on the\r
154 device.\r
155 @retval EFI_NO_MEDIA The device has no media.\r
156 @retval EFI_MEDIA_CHANGED The media has changed.\r
157 @retval EFI_DEVICE_ERROR The device reported an error.\r
158 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
159 @retval EFI_ACCESS_DENIED The service denied access to the file.\r
160 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of\r
161 resources.\r
162 @retval EFI_VOLUME_FULL The volume is full.\r
163\r
164**/\r
165EFI_STATUS\r
166EFIAPI\r
167UdfOpen (\r
168 IN EFI_FILE_PROTOCOL *This,\r
169 OUT EFI_FILE_PROTOCOL **NewHandle,\r
170 IN CHAR16 *FileName,\r
171 IN UINT64 OpenMode,\r
172 IN UINT64 Attributes\r
173 )\r
174{\r
175 EFI_TPL OldTpl;\r
176 EFI_STATUS Status;\r
177 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
178 PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;\r
179 CHAR16 FilePath[UDF_PATH_LENGTH];\r
180 UDF_FILE_INFO File;\r
181 PRIVATE_UDF_FILE_DATA *NewPrivFileData;\r
182 CHAR16 *TempFileName;\r
183\r
184 ZeroMem (FilePath, sizeof FilePath);\r
185 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
186\r
187 if (This == NULL || NewHandle == NULL || FileName == NULL) {\r
188 Status = EFI_INVALID_PARAMETER;\r
189 goto Error_Invalid_Params;\r
190 }\r
191\r
192 if (OpenMode != EFI_FILE_MODE_READ) {\r
193 Status = EFI_WRITE_PROTECTED;\r
194 goto Error_Invalid_Params;\r
195 }\r
196\r
197 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
198\r
199 PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);\r
200\r
201 //\r
202 // Build full path\r
203 //\r
204 if (*FileName == L'\\') {\r
205 StrCpyS (FilePath, UDF_PATH_LENGTH, FileName);\r
206 } else {\r
207 StrCpyS (FilePath, UDF_PATH_LENGTH, PrivFileData->AbsoluteFileName);\r
208 StrCatS (FilePath, UDF_PATH_LENGTH, L"\\");\r
209 StrCatS (FilePath, UDF_PATH_LENGTH, FileName);\r
210 }\r
211\r
212 MangleFileName (FilePath);\r
213 if (FilePath[0] == L'\0') {\r
214 Status = EFI_NOT_FOUND;\r
215 goto Error_Bad_FileName;\r
216 }\r
217\r
218 Status = FindFile (\r
219 PrivFsData->BlockIo,\r
220 PrivFsData->DiskIo,\r
221 &PrivFsData->Volume,\r
222 FilePath,\r
223 _ROOT_FILE (PrivFileData),\r
224 _PARENT_FILE (PrivFileData),\r
225 &_PARENT_FILE(PrivFileData)->FileIdentifierDesc->Icb,\r
226 &File\r
227 );\r
228 if (EFI_ERROR (Status)) {\r
229 goto Error_Find_File;\r
230 }\r
231\r
232 NewPrivFileData =\r
233 (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));\r
234 if (NewPrivFileData == NULL) {\r
235 Status = EFI_OUT_OF_RESOURCES;\r
236 goto Error_Alloc_New_Priv_File_Data;\r
237 }\r
238\r
239 CopyMem ((VOID *)NewPrivFileData, (VOID *)PrivFileData,\r
240 sizeof (PRIVATE_UDF_FILE_DATA));\r
241 CopyMem ((VOID *)&NewPrivFileData->File, &File, sizeof (UDF_FILE_INFO));\r
242\r
243 NewPrivFileData->IsRootDirectory = FALSE;\r
244\r
245 StrCpyS (NewPrivFileData->AbsoluteFileName, UDF_PATH_LENGTH, FilePath);\r
246 FileName = NewPrivFileData->AbsoluteFileName;\r
247\r
248 while ((TempFileName = StrStr (FileName, L"\\")) != NULL) {\r
249 FileName = TempFileName + 1;\r
250 }\r
251\r
252 StrCpyS (NewPrivFileData->FileName, UDF_FILENAME_LENGTH, FileName);\r
253\r
254 Status = GetFileSize (\r
255 PrivFsData->BlockIo,\r
256 PrivFsData->DiskIo,\r
257 &PrivFsData->Volume,\r
258 &NewPrivFileData->File,\r
259 &NewPrivFileData->FileSize\r
260 );\r
261 if (EFI_ERROR (Status)) {\r
262 DEBUG ((\r
263 DEBUG_ERROR,\r
264 "%a: GetFileSize() fails with status - %r.\n",\r
265 __FUNCTION__, Status\r
266 ));\r
267 goto Error_Get_File_Size;\r
268 }\r
269\r
270 NewPrivFileData->FilePosition = 0;\r
271 ZeroMem ((VOID *)&NewPrivFileData->ReadDirInfo,\r
272 sizeof (UDF_READ_DIRECTORY_INFO));\r
273\r
274 *NewHandle = &NewPrivFileData->FileIo;\r
275\r
276 PrivFsData->OpenFiles++;\r
277\r
278 gBS->RestoreTPL (OldTpl);\r
279\r
280 return Status;\r
281\r
282Error_Get_File_Size:\r
283 FreePool ((VOID *)NewPrivFileData);\r
284\r
285Error_Alloc_New_Priv_File_Data:\r
286 CleanupFileInformation (&File);\r
287\r
288Error_Find_File:\r
289Error_Bad_FileName:\r
290Error_Invalid_Params:\r
291 gBS->RestoreTPL (OldTpl);\r
292\r
293 return Status;\r
294}\r
295\r
296/**\r
297 Read data from the file.\r
298\r
299 @param This Protocol instance pointer.\r
300 @param BufferSize On input size of buffer, on output amount of data in\r
301 buffer.\r
302 @param Buffer The buffer in which data is read.\r
303\r
304 @retval EFI_SUCCESS Data was read.\r
305 @retval EFI_NO_MEDIA The device has no media.\r
306 @retval EFI_DEVICE_ERROR The device reported an error.\r
307 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
308 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains\r
309 required size.\r
310\r
311**/\r
312EFI_STATUS\r
313EFIAPI\r
314UdfRead (\r
315 IN EFI_FILE_PROTOCOL *This,\r
316 IN OUT UINTN *BufferSize,\r
317 OUT VOID *Buffer\r
318 )\r
319{\r
320 EFI_TPL OldTpl;\r
321 EFI_STATUS Status;\r
322 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
323 PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;\r
324 UDF_VOLUME_INFO *Volume;\r
325 UDF_FILE_INFO *Parent;\r
326 UDF_READ_DIRECTORY_INFO *ReadDirInfo;\r
327 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
328 EFI_DISK_IO_PROTOCOL *DiskIo;\r
329 UDF_FILE_INFO FoundFile;\r
330 UDF_FILE_IDENTIFIER_DESCRIPTOR *NewFileIdentifierDesc;\r
331 VOID *NewFileEntryData;\r
332 CHAR16 FileName[UDF_FILENAME_LENGTH];\r
333 UINT64 FileSize;\r
334 UINT64 BufferSizeUint64;\r
335\r
336 ZeroMem (FileName, sizeof FileName);\r
337 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
338\r
339 if (This == NULL || BufferSize == NULL || (*BufferSize != 0 &&\r
340 Buffer == NULL)) {\r
341 Status = EFI_INVALID_PARAMETER;\r
342 goto Error_Invalid_Params;\r
343 }\r
344\r
345 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
346 PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);\r
347\r
348 BlockIo = PrivFsData->BlockIo;\r
349 DiskIo = PrivFsData->DiskIo;\r
350 Volume = &PrivFsData->Volume;\r
351 ReadDirInfo = &PrivFileData->ReadDirInfo;\r
352 NewFileIdentifierDesc = NULL;\r
353 NewFileEntryData = NULL;\r
354\r
355 Parent = _PARENT_FILE (PrivFileData);\r
356\r
357 Status = EFI_VOLUME_CORRUPTED;\r
358\r
359 if (IS_FID_NORMAL_FILE (Parent->FileIdentifierDesc)) {\r
360 if (PrivFileData->FilePosition > PrivFileData->FileSize) {\r
361 //\r
362 // File's position is beyond the EOF\r
363 //\r
364 Status = EFI_DEVICE_ERROR;\r
365 goto Error_File_Beyond_The_Eof;\r
366 }\r
367\r
368 if (PrivFileData->FilePosition == PrivFileData->FileSize) {\r
369 *BufferSize = 0;\r
370 Status = EFI_SUCCESS;\r
371 goto Done;\r
372 }\r
373\r
374 BufferSizeUint64 = *BufferSize;\r
375\r
376 Status = ReadFileData (\r
377 BlockIo,\r
378 DiskIo,\r
379 Volume,\r
380 Parent,\r
381 PrivFileData->FileSize,\r
382 &PrivFileData->FilePosition,\r
383 Buffer,\r
384 &BufferSizeUint64\r
385 );\r
386 ASSERT (BufferSizeUint64 <= MAX_UINTN);\r
387 *BufferSize = (UINTN)BufferSizeUint64;\r
388 } else if (IS_FID_DIRECTORY_FILE (Parent->FileIdentifierDesc)) {\r
389 if (ReadDirInfo->FidOffset == 0 && PrivFileData->FilePosition > 0) {\r
390 Status = EFI_DEVICE_ERROR;\r
391 *BufferSize = 0;\r
392 goto Done;\r
393 }\r
394\r
395 for (;;) {\r
396 Status = ReadDirectoryEntry (\r
397 BlockIo,\r
398 DiskIo,\r
399 Volume,\r
400 &Parent->FileIdentifierDesc->Icb,\r
401 Parent->FileEntry,\r
402 ReadDirInfo,\r
403 &NewFileIdentifierDesc\r
404 );\r
405 if (EFI_ERROR (Status)) {\r
406 if (Status == EFI_DEVICE_ERROR) {\r
407 FreePool (ReadDirInfo->DirectoryData);\r
408 ZeroMem ((VOID *)ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO));\r
409\r
410 *BufferSize = 0;\r
411 Status = EFI_SUCCESS;\r
412 }\r
413\r
414 goto Done;\r
415 }\r
416 //\r
417 // After calling function ReadDirectoryEntry(), if 'NewFileIdentifierDesc'\r
418 // is NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the\r
419 // code reaches here, 'NewFileIdentifierDesc' must be not NULL.\r
420 //\r
421 // The ASSERT here is for addressing a false positive NULL pointer\r
422 // dereference issue raised from static analysis.\r
423 //\r
424 ASSERT (NewFileIdentifierDesc != NULL);\r
425\r
426 if (!IS_FID_PARENT_FILE (NewFileIdentifierDesc)) {\r
427 break;\r
428 }\r
429\r
430 FreePool ((VOID *)NewFileIdentifierDesc);\r
431 }\r
432\r
433 Status = FindFileEntry (\r
434 BlockIo,\r
435 DiskIo,\r
436 Volume,\r
437 &NewFileIdentifierDesc->Icb,\r
438 &NewFileEntryData\r
439 );\r
440 if (EFI_ERROR (Status)) {\r
441 goto Error_Find_Fe;\r
442 }\r
443 ASSERT (NewFileEntryData != NULL);\r
444\r
445 if (FE_ICB_FILE_TYPE (NewFileEntryData) == UdfFileEntrySymlink) {\r
446 Status = ResolveSymlink (\r
447 BlockIo,\r
448 DiskIo,\r
449 Volume,\r
450 Parent,\r
451 NewFileEntryData,\r
452 &FoundFile\r
453 );\r
454 if (EFI_ERROR (Status)) {\r
455 goto Error_Resolve_Symlink;\r
456 }\r
457\r
458 FreePool ((VOID *)NewFileEntryData);\r
459 NewFileEntryData = FoundFile.FileEntry;\r
460\r
461 Status = GetFileNameFromFid (NewFileIdentifierDesc, ARRAY_SIZE (FileName), FileName);\r
462 if (EFI_ERROR (Status)) {\r
463 FreePool ((VOID *)FoundFile.FileIdentifierDesc);\r
464 goto Error_Get_FileName;\r
465 }\r
466\r
467 FreePool ((VOID *)NewFileIdentifierDesc);\r
468 NewFileIdentifierDesc = FoundFile.FileIdentifierDesc;\r
469 } else {\r
470 FoundFile.FileIdentifierDesc = NewFileIdentifierDesc;\r
471 FoundFile.FileEntry = NewFileEntryData;\r
472\r
473 Status = GetFileNameFromFid (FoundFile.FileIdentifierDesc, ARRAY_SIZE (FileName), FileName);\r
474 if (EFI_ERROR (Status)) {\r
475 goto Error_Get_FileName;\r
476 }\r
477 }\r
478\r
479 Status = GetFileSize (\r
480 BlockIo,\r
481 DiskIo,\r
482 Volume,\r
483 &FoundFile,\r
484 &FileSize\r
485 );\r
486 if (EFI_ERROR (Status)) {\r
487 goto Error_Get_File_Size;\r
488 }\r
489\r
490 Status = SetFileInfo (\r
491 &FoundFile,\r
492 FileSize,\r
493 FileName,\r
494 BufferSize,\r
495 Buffer\r
496 );\r
497 if (EFI_ERROR (Status)) {\r
498 goto Error_Set_File_Info;\r
499 }\r
500\r
501 PrivFileData->FilePosition++;\r
502 Status = EFI_SUCCESS;\r
503 } else if (IS_FID_DELETED_FILE (Parent->FileIdentifierDesc)) {\r
504 //\r
505 // Code should never reach here.\r
506 //\r
507 ASSERT (FALSE);\r
508 Status = EFI_DEVICE_ERROR;\r
509 }\r
510\r
511Error_Set_File_Info:\r
512Error_Get_File_Size:\r
513Error_Get_FileName:\r
514Error_Resolve_Symlink:\r
515 if (NewFileEntryData != NULL) {\r
516 FreePool (NewFileEntryData);\r
517 }\r
518\r
519Error_Find_Fe:\r
520 if (NewFileIdentifierDesc != NULL) {\r
521 FreePool ((VOID *)NewFileIdentifierDesc);\r
522 }\r
523\r
524Done:\r
525Error_File_Beyond_The_Eof:\r
526Error_Invalid_Params:\r
527 gBS->RestoreTPL (OldTpl);\r
528\r
529 return Status;\r
530}\r
531\r
532/**\r
533 Close the file handle.\r
534\r
535 @param This Protocol instance pointer.\r
536\r
537 @retval EFI_SUCCESS The file was closed.\r
538\r
539**/\r
540EFI_STATUS\r
541EFIAPI\r
542UdfClose (\r
543 IN EFI_FILE_PROTOCOL *This\r
544 )\r
545{\r
546 EFI_TPL OldTpl;\r
547 EFI_STATUS Status;\r
548 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
549\r
550 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
551\r
552 Status = EFI_SUCCESS;\r
553\r
554 if (This == NULL) {\r
555 Status = EFI_INVALID_PARAMETER;\r
556 goto Exit;\r
557 }\r
558\r
559 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
560\r
561 if (!PrivFileData->IsRootDirectory) {\r
562 CleanupFileInformation (&PrivFileData->File);\r
563\r
564 if (PrivFileData->ReadDirInfo.DirectoryData != NULL) {\r
565 FreePool (PrivFileData->ReadDirInfo.DirectoryData);\r
566 }\r
567 }\r
568\r
569 FreePool ((VOID *)PrivFileData);\r
570\r
571Exit:\r
572 gBS->RestoreTPL (OldTpl);\r
573\r
574 return Status;\r
575}\r
576\r
577/**\r
578 Close and delete the file handle.\r
579\r
580 @param This Protocol instance pointer.\r
581\r
582 @retval EFI_SUCCESS The file was closed and deleted.\r
583 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not\r
584 deleted.\r
585\r
586**/\r
587EFI_STATUS\r
588EFIAPI\r
589UdfDelete (\r
590 IN EFI_FILE_PROTOCOL *This\r
591 )\r
592{\r
593 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
594\r
595 if (This == NULL) {\r
596 return EFI_INVALID_PARAMETER;\r
597 }\r
598\r
599 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
600\r
601 (VOID)PrivFileData->FileIo.Close(This);\r
602\r
603 return EFI_WARN_DELETE_FAILURE;\r
604}\r
605\r
606/**\r
607 Write data to a file.\r
608\r
609 @param This Protocol instance pointer.\r
610 @param BufferSize On input size of buffer, on output amount of data in\r
611 buffer.\r
612 @param Buffer The buffer in which data to write.\r
613\r
614 @retval EFI_SUCCESS Data was written.\r
615 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.\r
616 @retval EFI_NO_MEDIA The device has no media.\r
617 @retval EFI_DEVICE_ERROR The device reported an error.\r
618 @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.\r
619 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
620 @retval EFI_WRITE_PROTECTED The device is write protected.\r
621 @retval EFI_ACCESS_DENIED The file was open for read only.\r
622 @retval EFI_VOLUME_FULL The volume is full.\r
623\r
624**/\r
625EFI_STATUS\r
626EFIAPI\r
627UdfWrite (\r
628 IN EFI_FILE_PROTOCOL *This,\r
629 IN OUT UINTN *BufferSize,\r
630 IN VOID *Buffer\r
631 )\r
632{\r
633 return EFI_UNSUPPORTED;\r
634}\r
635\r
636/**\r
637 Get file's current position.\r
638\r
639 @param This Protocol instance pointer.\r
640 @param Position Byte position from the start of the file.\r
641\r
642 @retval EFI_SUCCESS Position was updated.\r
643 @retval EFI_UNSUPPORTED Seek request for directories is not valid.\r
644\r
645**/\r
646EFI_STATUS\r
647EFIAPI\r
648UdfGetPosition (\r
649 IN EFI_FILE_PROTOCOL *This,\r
650 OUT UINT64 *Position\r
651 )\r
652{\r
653 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
654\r
655 if (This == NULL || Position == NULL) {\r
656 return EFI_INVALID_PARAMETER;\r
657 }\r
658\r
659 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
660\r
661 //\r
662 // As per UEFI spec, if the file handle is a directory, then the current file\r
663 // position has no meaning and the operation is not supported.\r
664 //\r
665 if (IS_FID_DIRECTORY_FILE (PrivFileData->File.FileIdentifierDesc)) {\r
666 return EFI_UNSUPPORTED;\r
667 }\r
668\r
669 //\r
670 // The file is not a directory. So, return its position.\r
671 //\r
672 *Position = PrivFileData->FilePosition;\r
673\r
674 return EFI_SUCCESS;\r
675}\r
676\r
677/**\r
678 Set file's current position.\r
679\r
680 @param This Protocol instance pointer.\r
681 @param Position Byte position from the start of the file.\r
682\r
683 @retval EFI_SUCCESS Position was updated.\r
684 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.\r
685\r
686**/\r
687EFI_STATUS\r
688EFIAPI\r
689UdfSetPosition (\r
690 IN EFI_FILE_PROTOCOL *This,\r
691 IN UINT64 Position\r
692 )\r
693{\r
694 EFI_STATUS Status;\r
695 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
696 UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;\r
697\r
698 if (This == NULL) {\r
699 return EFI_INVALID_PARAMETER;\r
700 }\r
701\r
702 Status = EFI_UNSUPPORTED;\r
703\r
704 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
705\r
706 FileIdentifierDesc = _FILE (PrivFileData)->FileIdentifierDesc;\r
707 ASSERT (FileIdentifierDesc != NULL);\r
708 if (IS_FID_DIRECTORY_FILE (FileIdentifierDesc)) {\r
709 //\r
710 // If the file handle is a directory, the _only_ position that may be set is\r
711 // zero. This has no effect of starting the read proccess of the directory\r
712 // entries over.\r
713 //\r
714 if (Position == 0) {\r
715 PrivFileData->FilePosition = Position;\r
716 PrivFileData->ReadDirInfo.FidOffset = 0;\r
717 Status = EFI_SUCCESS;\r
718 }\r
719 } else if (IS_FID_NORMAL_FILE (FileIdentifierDesc)) {\r
720 //\r
721 // Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to be\r
722 // set to the EOF.\r
723 //\r
724 if (Position == 0xFFFFFFFFFFFFFFFF) {\r
725 PrivFileData->FilePosition = PrivFileData->FileSize;\r
726 } else {\r
727 PrivFileData->FilePosition = Position;\r
728 }\r
729\r
730 Status = EFI_SUCCESS;\r
731 }\r
732\r
733 return Status;\r
734}\r
735\r
736/**\r
737 Get information about a file.\r
738\r
739 @param This Protocol instance pointer.\r
740 @param InformationType Type of information to return in Buffer.\r
741 @param BufferSize On input size of buffer, on output amount of data in\r
742 buffer.\r
743 @param Buffer The buffer to return data.\r
744\r
745 @retval EFI_SUCCESS Data was returned.\r
746 @retval EFI_UNSUPPORTED InformationType is not supported.\r
747 @retval EFI_NO_MEDIA The device has no media.\r
748 @retval EFI_DEVICE_ERROR The device reported an error.\r
749 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
750 @retval EFI_WRITE_PROTECTED The device is write protected.\r
751 @retval EFI_ACCESS_DENIED The file was open for read only.\r
752 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in\r
753 BufferSize.\r
754\r
755**/\r
756EFI_STATUS\r
757EFIAPI\r
758UdfGetInfo (\r
759 IN EFI_FILE_PROTOCOL *This,\r
760 IN EFI_GUID *InformationType,\r
761 IN OUT UINTN *BufferSize,\r
762 OUT VOID *Buffer\r
763 )\r
764{\r
765 EFI_STATUS Status;\r
766 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
767 PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;\r
768 EFI_FILE_SYSTEM_INFO *FileSystemInfo;\r
769 UINTN FileSystemInfoLength;\r
770 UINT64 VolumeSize;\r
771 UINT64 FreeSpaceSize;\r
772 EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;\r
773 UINTN FileSystemVolumeLabelLength;\r
774 CHAR16 VolumeLabel[64];\r
775\r
776 if (This == NULL || InformationType == NULL || BufferSize == NULL ||\r
777 (*BufferSize != 0 && Buffer == NULL)) {\r
778 return EFI_INVALID_PARAMETER;\r
779 }\r
780\r
781 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
782\r
783 PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);\r
784\r
785 Status = EFI_UNSUPPORTED;\r
786\r
787 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
788 Status = SetFileInfo (\r
789 _FILE (PrivFileData),\r
790 PrivFileData->FileSize,\r
791 PrivFileData->FileName,\r
792 BufferSize,\r
793 Buffer\r
794 );\r
795 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
796 Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);\r
797 if (EFI_ERROR (Status)) {\r
798 return Status;\r
799 }\r
800\r
801 FileSystemInfoLength = StrSize (VolumeLabel) +\r
802 sizeof (EFI_FILE_SYSTEM_INFO);\r
803 if (*BufferSize < FileSystemInfoLength) {\r
804 *BufferSize = FileSystemInfoLength;\r
805 return EFI_BUFFER_TOO_SMALL;\r
806 }\r
807\r
808 FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;\r
809 StrCpyS (\r
810 FileSystemInfo->VolumeLabel,\r
811 (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_INFO) / sizeof (CHAR16),\r
812 VolumeLabel\r
813 );\r
814 Status = GetVolumeSize (\r
815 PrivFsData->BlockIo,\r
816 PrivFsData->DiskIo,\r
817 &PrivFsData->Volume,\r
818 &VolumeSize,\r
819 &FreeSpaceSize\r
820 );\r
821 if (EFI_ERROR (Status)) {\r
822 return Status;\r
823 }\r
824\r
825 FileSystemInfo->Size = FileSystemInfoLength;\r
826 FileSystemInfo->ReadOnly = TRUE;\r
827 FileSystemInfo->BlockSize =\r
828 PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize;\r
829 FileSystemInfo->VolumeSize = VolumeSize;\r
830 FileSystemInfo->FreeSpace = FreeSpaceSize;\r
831\r
832 *BufferSize = FileSystemInfoLength;\r
833 Status = EFI_SUCCESS;\r
834 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
835 Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);\r
836 if (EFI_ERROR (Status)) {\r
837 return Status;\r
838 }\r
839\r
840 FileSystemVolumeLabelLength = StrSize (VolumeLabel) +\r
841 sizeof (EFI_FILE_SYSTEM_VOLUME_LABEL);\r
842 if (*BufferSize < FileSystemVolumeLabelLength) {\r
843 *BufferSize = FileSystemVolumeLabelLength;\r
844 return EFI_BUFFER_TOO_SMALL;\r
845 }\r
846\r
847 FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer;\r
848 StrCpyS (\r
849 FileSystemVolumeLabel->VolumeLabel,\r
850 (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL) / sizeof (CHAR16),\r
851 VolumeLabel\r
852 );\r
853 Status = EFI_SUCCESS;\r
854 }\r
855\r
856 return Status;\r
857}\r
858\r
859/**\r
860 Set information about a file.\r
861\r
862 @param This Protocol instance pointer.\r
863 @param InformationType Type of information in Buffer.\r
864 @param BufferSize Size of buffer.\r
865 @param Buffer The data to write.\r
866\r
867 @retval EFI_SUCCESS Data was set.\r
868 @retval EFI_UNSUPPORTED InformationType is not supported.\r
869 @retval EFI_NO_MEDIA The device has no media.\r
870 @retval EFI_DEVICE_ERROR The device reported an error.\r
871 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
872 @retval EFI_WRITE_PROTECTED The device is write protected.\r
873 @retval EFI_ACCESS_DENIED The file was open for read only.\r
874\r
875**/\r
876EFI_STATUS\r
877EFIAPI\r
878UdfSetInfo (\r
879 IN EFI_FILE_PROTOCOL *This,\r
880 IN EFI_GUID *InformationType,\r
881 IN UINTN BufferSize,\r
882 IN VOID *Buffer\r
883 )\r
884{\r
885 return EFI_WRITE_PROTECTED;\r
886}\r
887\r
888/**\r
889 Flush data back for the file handle.\r
890\r
891 @param This Protocol instance pointer.\r
892\r
893 @retval EFI_SUCCESS Data was flushed.\r
894 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.\r
895 @retval EFI_NO_MEDIA The device has no media.\r
896 @retval EFI_DEVICE_ERROR The device reported an error.\r
897 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
898 @retval EFI_WRITE_PROTECTED The device is write protected.\r
899 @retval EFI_ACCESS_DENIED The file was open for read only.\r
900 @retval EFI_VOLUME_FULL The volume is full.\r
901\r
902**/\r
903EFI_STATUS\r
904EFIAPI\r
905UdfFlush (\r
906 IN EFI_FILE_PROTOCOL *This\r
907 )\r
908{\r
909 return EFI_WRITE_PROTECTED;\r
910}\r