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