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