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