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