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