]> git.proxmox.com Git - mirror_edk2.git/blob - EdkUnixPkg/Dxe/UnixThunk/Bus/SimpleFileSystem/UnixSimpleFileSystem.c
fix build warning issue
[mirror_edk2.git] / EdkUnixPkg / Dxe / UnixThunk / Bus / SimpleFileSystem / UnixSimpleFileSystem.c
1 /*++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 UnixSimpleFileSystem.c
15
16 Abstract:
17
18 Produce Simple File System abstractions for directories on your PC using Posix APIs.
19 The configuration of what devices to mount or emulate comes from UNIX
20 environment variables. The variables must be visible to the Microsoft*
21 Developer Studio for them to work.
22
23 * Other names and brands may be claimed as the property of others.
24
25 --*/
26
27 #include "UnixSimpleFileSystem.h"
28
29 EFI_DRIVER_BINDING_PROTOCOL gUnixSimpleFileSystemDriverBinding = {
30 UnixSimpleFileSystemDriverBindingSupported,
31 UnixSimpleFileSystemDriverBindingStart,
32 UnixSimpleFileSystemDriverBindingStop,
33 0xa,
34 NULL,
35 NULL
36 };
37
38
39 CHAR16 *
40 EfiStrChr (
41 IN CHAR16 *Str,
42 IN CHAR16 Chr
43 )
44 /*++
45
46 Routine Description:
47
48 Locate the first occurance of a character in a string.
49
50 Arguments:
51
52 Str - Pointer to NULL terminated unicode string.
53 Chr - Character to locate.
54
55 Returns:
56
57 If Str is NULL, then NULL is returned.
58 If Chr is not contained in Str, then NULL is returned.
59 If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.
60
61 --*/
62 {
63 if (Str == NULL) {
64 return Str;
65 }
66
67 while (*Str != '\0' && *Str != Chr) {
68 ++Str;
69 }
70
71 return (*Str == Chr) ? Str : NULL;
72 }
73
74 BOOLEAN
75 IsZero (
76 IN VOID *Buffer,
77 IN UINTN Length
78 )
79 /*++
80
81 Routine Description:
82
83 TODO: Add function description
84
85 Arguments:
86
87 Buffer - TODO: add argument description
88 Length - TODO: add argument description
89
90 Returns:
91
92 TODO: add return values
93
94 --*/
95 {
96 if (Buffer == NULL || Length == 0) {
97 return FALSE;
98 }
99
100 if (*(UINT8 *) Buffer != 0) {
101 return FALSE;
102 }
103
104 if (Length > 1) {
105 if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) {
106 return FALSE;
107 }
108 }
109
110 return TRUE;
111 }
112
113 VOID
114 CutPrefix (
115 IN CHAR8 *Str,
116 IN UINTN Count
117 )
118 /*++
119
120 Routine Description:
121
122 TODO: Add function description
123
124 Arguments:
125
126 Str - TODO: add argument description
127 Count - TODO: add argument description
128
129 Returns:
130
131 TODO: add return values
132
133 --*/
134 {
135 CHAR8 *Pointer;
136
137 if (AsciiStrLen (Str) < Count) {
138 ASSERT (0);
139 }
140
141 for (Pointer = Str; *(Pointer + Count); Pointer++) {
142 *Pointer = *(Pointer + Count);
143 }
144
145 *Pointer = *(Pointer + Count);
146 }
147
148
149
150 EFI_STATUS
151 EFIAPI
152 UnixSimpleFileSystemDriverBindingSupported (
153 IN EFI_DRIVER_BINDING_PROTOCOL *This,
154 IN EFI_HANDLE ControllerHandle,
155 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
156 )
157 /*++
158
159 Routine Description:
160
161 Check to see if the driver supports a given controller.
162
163 Arguments:
164
165 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
166
167 ControllerHandle - EFI handle of the controller to test.
168
169 RemainingDevicePath - Pointer to remaining portion of a device path.
170
171 Returns:
172
173 EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver
174 specified by This.
175
176 EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
177 the driver specified by This.
178
179 EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
180 a different driver or an application that requires exclusive access.
181
182 EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the
183 driver specified by This.
184
185 --*/
186 {
187 EFI_STATUS Status;
188 EFI_UNIX_IO_PROTOCOL *UnixIo;
189
190 //
191 // Open the IO Abstraction(s) needed to perform the supported test
192 //
193 Status = gBS->OpenProtocol (
194 ControllerHandle,
195 &gEfiUnixIoProtocolGuid,
196 (VOID **)&UnixIo,
197 This->DriverBindingHandle,
198 ControllerHandle,
199 EFI_OPEN_PROTOCOL_BY_DRIVER
200 );
201 if (EFI_ERROR (Status)) {
202 return Status;
203 }
204
205 //
206 // Make sure GUID is for a File System handle.
207 //
208 Status = EFI_UNSUPPORTED;
209 if (CompareGuid (UnixIo->TypeGuid, &gEfiUnixFileSystemGuid)) {
210 Status = EFI_SUCCESS;
211 }
212
213 //
214 // Close the I/O Abstraction(s) used to perform the supported test
215 //
216 gBS->CloseProtocol (
217 ControllerHandle,
218 &gEfiUnixIoProtocolGuid,
219 This->DriverBindingHandle,
220 ControllerHandle
221 );
222
223 return Status;
224 }
225
226 EFI_STATUS
227 EFIAPI
228 UnixSimpleFileSystemDriverBindingStart (
229 IN EFI_DRIVER_BINDING_PROTOCOL *This,
230 IN EFI_HANDLE ControllerHandle,
231 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
232 )
233 /*++
234
235 Routine Description:
236
237 Starts a device controller or a bus controller.
238
239 Arguments:
240
241 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
242
243 ControllerHandle - EFI handle of the controller to start.
244
245 RemainingDevicePath - Pointer to remaining portion of a device path.
246
247 Returns:
248
249 EFI_SUCCESS - The device or bus controller has been started.
250
251 EFI_DEVICE_ERROR - The device could not be started due to a device failure.
252
253 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
254
255 --*/
256 {
257 EFI_STATUS Status;
258 EFI_UNIX_IO_PROTOCOL *UnixIo;
259 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
260 INTN i;
261
262 Private = NULL;
263
264 //
265 // Open the IO Abstraction(s) needed
266 //
267 Status = gBS->OpenProtocol (
268 ControllerHandle,
269 &gEfiUnixIoProtocolGuid,
270 (VOID **)&UnixIo,
271 This->DriverBindingHandle,
272 ControllerHandle,
273 EFI_OPEN_PROTOCOL_BY_DRIVER
274 );
275 if (EFI_ERROR (Status)) {
276 return Status;
277 }
278
279 //
280 // Validate GUID
281 //
282 if (!CompareGuid (UnixIo->TypeGuid, &gEfiUnixFileSystemGuid)) {
283 Status = EFI_UNSUPPORTED;
284 goto Done;
285 }
286
287 Status = gBS->AllocatePool (
288 EfiBootServicesData,
289 sizeof (UNIX_SIMPLE_FILE_SYSTEM_PRIVATE),
290 (VOID **)&Private
291 );
292 if (EFI_ERROR (Status)) {
293 goto Done;
294 }
295
296 Private->Signature = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;
297 Private->UnixThunk = UnixIo->UnixThunk;
298 Private->FilePath = NULL;
299 Private->VolumeLabel = NULL;
300
301 Status = gBS->AllocatePool (
302 EfiBootServicesData,
303 StrLen (UnixIo->EnvString) + 1,
304 (VOID **)&Private->FilePath
305 );
306
307 if (EFI_ERROR (Status)) {
308 goto Done;
309 }
310
311 for (i = 0; UnixIo->EnvString[i] != 0; i++)
312 Private->FilePath[i] = UnixIo->EnvString[i];
313 Private->FilePath[i] = 0;
314
315 Private->VolumeLabel = NULL;
316 Status = gBS->AllocatePool (
317 EfiBootServicesData,
318 StrSize (L"EFI_EMULATED"),
319 (VOID **)&Private->VolumeLabel
320 );
321
322 if (EFI_ERROR (Status)) {
323 goto Done;
324 }
325
326 StrCpy (Private->VolumeLabel, L"EFI_EMULATED");
327
328 Private->SimpleFileSystem.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
329 Private->SimpleFileSystem.OpenVolume = UnixSimpleFileSystemOpenVolume;
330
331 Private->ControllerNameTable = NULL;
332
333 AddUnicodeString (
334 "eng",
335 gUnixSimpleFileSystemComponentName.SupportedLanguages,
336 &Private->ControllerNameTable,
337 UnixIo->EnvString
338 );
339
340 Status = gBS->InstallMultipleProtocolInterfaces (
341 &ControllerHandle,
342 &gEfiSimpleFileSystemProtocolGuid,
343 &Private->SimpleFileSystem,
344 NULL
345 );
346
347 Done:
348 if (EFI_ERROR (Status)) {
349
350 if (Private != NULL) {
351
352 if (Private->VolumeLabel != NULL)
353 gBS->FreePool (Private->VolumeLabel);
354 if (Private->FilePath != NULL)
355 gBS->FreePool (Private->FilePath);
356 FreeUnicodeStringTable (Private->ControllerNameTable);
357
358 gBS->FreePool (Private);
359 }
360
361 gBS->CloseProtocol (
362 ControllerHandle,
363 &gEfiUnixIoProtocolGuid,
364 This->DriverBindingHandle,
365 ControllerHandle
366 );
367 }
368
369 return Status;
370 }
371
372 EFI_STATUS
373 EFIAPI
374 UnixSimpleFileSystemDriverBindingStop (
375 IN EFI_DRIVER_BINDING_PROTOCOL *This,
376 IN EFI_HANDLE ControllerHandle,
377 IN UINTN NumberOfChildren,
378 IN EFI_HANDLE *ChildHandleBuffer
379 )
380 /*++
381
382 Routine Description:
383
384 TODO: Add function description
385
386 Arguments:
387
388 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
389
390 ControllerHandle - A handle to the device to be stopped.
391
392 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
393
394 ChildHandleBuffer - An array of child device handles to be freed.
395
396 Returns:
397
398 EFI_SUCCESS - The device has been stopped.
399
400 EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.
401
402 --*/
403 // TODO: EFI_UNSUPPORTED - add return value to function comment
404 {
405 EFI_STATUS Status;
406 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
407 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
408
409 //
410 // Get our context back
411 //
412 Status = gBS->OpenProtocol (
413 ControllerHandle,
414 &gEfiSimpleFileSystemProtocolGuid,
415 (VOID **)&SimpleFileSystem,
416 This->DriverBindingHandle,
417 ControllerHandle,
418 EFI_OPEN_PROTOCOL_GET_PROTOCOL
419 );
420 if (EFI_ERROR (Status)) {
421 return EFI_UNSUPPORTED;
422 }
423
424 Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem);
425
426 //
427 // Uninstall the Simple File System Protocol from ControllerHandle
428 //
429 Status = gBS->UninstallMultipleProtocolInterfaces (
430 ControllerHandle,
431 &gEfiSimpleFileSystemProtocolGuid,
432 &Private->SimpleFileSystem,
433 NULL
434 );
435 if (!EFI_ERROR (Status)) {
436 Status = gBS->CloseProtocol (
437 ControllerHandle,
438 &gEfiUnixIoProtocolGuid,
439 This->DriverBindingHandle,
440 ControllerHandle
441 );
442 }
443
444 if (!EFI_ERROR (Status)) {
445 //
446 // Free our instance data
447 //
448 FreeUnicodeStringTable (Private->ControllerNameTable);
449
450 gBS->FreePool (Private);
451 }
452
453 return Status;
454 }
455
456 EFI_STATUS
457 EFIAPI
458 UnixSimpleFileSystemOpenVolume (
459 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
460 OUT EFI_FILE **Root
461 )
462 /*++
463
464 Routine Description:
465
466 Open the root directory on a volume.
467
468 Arguments:
469
470 This - A pointer to the volume to open.
471
472 Root - A pointer to storage for the returned opened file handle of the root directory.
473
474 Returns:
475
476 EFI_SUCCESS - The volume was opened.
477
478 EFI_UNSUPPORTED - The volume does not support the requested file system type.
479
480 EFI_NO_MEDIA - The device has no media.
481
482 EFI_DEVICE_ERROR - The device reported an error.
483
484 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
485
486 EFI_ACCESS_DENIED - The service denied access to the file.
487
488 EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.
489
490 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
491
492 --*/
493 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
494 {
495 EFI_STATUS Status;
496 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
497 UNIX_EFI_FILE_PRIVATE *PrivateFile;
498 EFI_TPL OldTpl;
499
500 if (This == NULL || Root == NULL) {
501 return EFI_INVALID_PARAMETER;
502 }
503 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
504
505 Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);
506
507 PrivateFile = NULL;
508 Status = gBS->AllocatePool (
509 EfiBootServicesData,
510 sizeof (UNIX_EFI_FILE_PRIVATE),
511 (VOID **)&PrivateFile
512 );
513 if (EFI_ERROR (Status)) {
514 goto Done;
515 }
516
517 PrivateFile->FileName = NULL;
518 Status = gBS->AllocatePool (
519 EfiBootServicesData,
520 AsciiStrSize (Private->FilePath),
521 (VOID **)&PrivateFile->FileName
522 );
523 if (EFI_ERROR (Status)) {
524 goto Done;
525 }
526
527 AsciiStrCpy (PrivateFile->FileName, Private->FilePath);
528 PrivateFile->Signature = UNIX_EFI_FILE_PRIVATE_SIGNATURE;
529 PrivateFile->UnixThunk = Private->UnixThunk;
530 PrivateFile->SimpleFileSystem = This;
531 PrivateFile->IsRootDirectory = TRUE;
532 PrivateFile->IsDirectoryPath = TRUE;
533 PrivateFile->IsOpenedByRead = TRUE;
534 PrivateFile->EfiFile.Revision = EFI_FILE_HANDLE_REVISION;
535 PrivateFile->EfiFile.Open = UnixSimpleFileSystemOpen;
536 PrivateFile->EfiFile.Close = UnixSimpleFileSystemClose;
537 PrivateFile->EfiFile.Delete = UnixSimpleFileSystemDelete;
538 PrivateFile->EfiFile.Read = UnixSimpleFileSystemRead;
539 PrivateFile->EfiFile.Write = UnixSimpleFileSystemWrite;
540 PrivateFile->EfiFile.GetPosition = UnixSimpleFileSystemGetPosition;
541 PrivateFile->EfiFile.SetPosition = UnixSimpleFileSystemSetPosition;
542 PrivateFile->EfiFile.GetInfo = UnixSimpleFileSystemGetInfo;
543 PrivateFile->EfiFile.SetInfo = UnixSimpleFileSystemSetInfo;
544 PrivateFile->EfiFile.Flush = UnixSimpleFileSystemFlush;
545 PrivateFile->fd = -1;
546 PrivateFile->Dir = NULL;
547 PrivateFile->Dirent = NULL;
548
549 *Root = &PrivateFile->EfiFile;
550
551 PrivateFile->Dir = PrivateFile->UnixThunk->OpenDir(PrivateFile->FileName);
552
553 if (PrivateFile->Dir == NULL) {
554 Status = EFI_ACCESS_DENIED;
555 }
556 else {
557 Status = EFI_SUCCESS;
558 }
559
560 Done:
561 if (EFI_ERROR (Status)) {
562 if (PrivateFile) {
563 if (PrivateFile->FileName) {
564 gBS->FreePool (PrivateFile->FileName);
565 }
566
567 gBS->FreePool (PrivateFile);
568 }
569 }
570
571 gBS->RestoreTPL (OldTpl);
572
573 return Status;
574 }
575
576 EFI_STATUS
577 EFIAPI
578 UnixSimpleFileSystemOpen (
579 IN EFI_FILE *This,
580 OUT EFI_FILE **NewHandle,
581 IN CHAR16 *FileName,
582 IN UINT64 OpenMode,
583 IN UINT64 Attributes
584 )
585 /*++
586
587 Routine Description:
588
589 Open a file relative to the source file location.
590
591 Arguments:
592
593 This - A pointer to the source file location.
594
595 NewHandle - Pointer to storage for the new file handle.
596
597 FileName - Pointer to the file name to be opened.
598
599 OpenMode - File open mode information.
600
601 Attributes - File creation attributes.
602
603 Returns:
604
605 EFI_SUCCESS - The file was opened.
606
607 EFI_NOT_FOUND - The file could not be found in the volume.
608
609 EFI_NO_MEDIA - The device has no media.
610
611 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
612
613 EFI_DEVICE_ERROR - The device reported an error.
614
615 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
616
617 EFI_WRITE_PROTECTED - The volume or file is write protected.
618
619 EFI_ACCESS_DENIED - The service denied access to the file.
620
621 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
622
623 EFI_VOLUME_FULL - There is not enough space left to create the new file.
624
625 --*/
626 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
627 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
628 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
629 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
630 {
631 EFI_FILE *Root;
632 UNIX_EFI_FILE_PRIVATE *PrivateFile;
633 UNIX_EFI_FILE_PRIVATE *NewPrivateFile;
634 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
635 EFI_STATUS Status;
636 CHAR16 *Src;
637 char *Dst;
638 CHAR8 *RealFileName;
639 char *ParseFileName;
640 char *GuardPointer;
641 CHAR8 TempChar;
642 UINTN Count;
643 BOOLEAN TrailingDash;
644 BOOLEAN LoopFinish;
645 UINTN InfoSize;
646 EFI_FILE_INFO *Info;
647
648 TrailingDash = FALSE;
649
650 //
651 // Check for obvious invalid parameters.
652 //
653 if (This == NULL || NewHandle == NULL || FileName == NULL) {
654 return EFI_INVALID_PARAMETER;
655 }
656
657 switch (OpenMode) {
658 case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
659 if (Attributes &~EFI_FILE_VALID_ATTR) {
660 return EFI_INVALID_PARAMETER;
661 }
662
663 if (Attributes & EFI_FILE_READ_ONLY) {
664 return EFI_INVALID_PARAMETER;
665 }
666
667 //
668 // fall through
669 //
670 case EFI_FILE_MODE_READ:
671 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
672 break;
673
674 default:
675 return EFI_INVALID_PARAMETER;
676 }
677
678
679 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
680 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
681 NewPrivateFile = NULL;
682
683 //
684 // BUGBUG: assume an open of root
685 // if current location, return current data
686 //
687 if (StrCmp (FileName, L"\\") == 0
688 || (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) {
689 //
690 // BUGBUG: assume an open root
691 //
692 OpenRoot:
693 Status = UnixSimpleFileSystemOpenVolume (PrivateFile->SimpleFileSystem, &Root);
694 NewPrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root);
695 goto Done;
696 }
697
698 if (FileName[StrLen (FileName) - 1] == L'\\') {
699 TrailingDash = TRUE;
700 FileName[StrLen (FileName) - 1] = 0;
701 }
702
703 //
704 // Attempt to open the file
705 //
706 Status = gBS->AllocatePool (
707 EfiBootServicesData,
708 sizeof (UNIX_EFI_FILE_PRIVATE),
709 (VOID **)&NewPrivateFile
710 );
711
712 if (EFI_ERROR (Status)) {
713 goto Done;
714 }
715
716 CopyMem (NewPrivateFile, PrivateFile, sizeof (UNIX_EFI_FILE_PRIVATE));
717
718 NewPrivateFile->FileName = NULL;
719 Status = gBS->AllocatePool (
720 EfiBootServicesData,
721 AsciiStrSize (PrivateFile->FileName) + 1 + StrLen (FileName) + 1,
722 (VOID **)&NewPrivateFile->FileName
723 );
724
725 if (EFI_ERROR (Status)) {
726 goto Done;
727 }
728
729 if (*FileName == L'\\') {
730 AsciiStrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);
731 // Skip first '\'.
732 Src = FileName + 1;
733 } else {
734 AsciiStrCpy (NewPrivateFile->FileName, PrivateFile->FileName);
735 Src = FileName;
736 }
737 Dst = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName);
738 GuardPointer = NewPrivateFile->FileName + AsciiStrLen(PrivateRoot->FilePath);
739 *Dst++ = '/';
740 // Convert unicode to ascii and '\' to '/'
741 while (*Src) {
742 if (*Src == '\\')
743 *Dst++ = '/';
744 else
745 *Dst++ = *Src;
746 Src++;
747 }
748 *Dst = 0;
749
750
751 //
752 // Get rid of . and .., except leading . or ..
753 //
754
755 //
756 // GuardPointer protect simplefilesystem root path not be destroyed
757 //
758
759 LoopFinish = FALSE;
760
761 while (!LoopFinish) {
762
763 LoopFinish = TRUE;
764
765 for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {
766 if (*ParseFileName == '.' &&
767 (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == '/') &&
768 *(ParseFileName - 1) == '/'
769 ) {
770
771 //
772 // cut /.
773 //
774 CutPrefix (ParseFileName - 1, 2);
775 LoopFinish = FALSE;
776 break;
777 }
778
779 if (*ParseFileName == '.' &&
780 *(ParseFileName + 1) == '.' &&
781 (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == '/') &&
782 *(ParseFileName - 1) == '/'
783 ) {
784
785 ParseFileName--;
786 Count = 3;
787
788 while (ParseFileName != GuardPointer) {
789 ParseFileName--;
790 Count++;
791 if (*ParseFileName == '/') {
792 break;
793 }
794 }
795
796 //
797 // cut /.. and its left directory
798 //
799 CutPrefix (ParseFileName, Count);
800 LoopFinish = FALSE;
801 break;
802 }
803 }
804 }
805
806 if (AsciiStrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {
807 NewPrivateFile->IsRootDirectory = TRUE;
808 gBS->FreePool (NewPrivateFile->FileName);
809 gBS->FreePool (NewPrivateFile);
810 goto OpenRoot;
811 }
812
813 RealFileName = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName) - 1;
814 while (RealFileName > NewPrivateFile->FileName && *RealFileName != '/')
815 RealFileName--;
816
817 TempChar = *(RealFileName - 1);
818 *(RealFileName - 1) = 0;
819
820 *(RealFileName - 1) = TempChar;
821
822
823
824 //
825 // Test whether file or directory
826 //
827 NewPrivateFile->IsRootDirectory = FALSE;
828 NewPrivateFile->fd = -1;
829 NewPrivateFile->Dir = NULL;
830 if (OpenMode & EFI_FILE_MODE_CREATE) {
831 if (Attributes & EFI_FILE_DIRECTORY) {
832 NewPrivateFile->IsDirectoryPath = TRUE;
833 } else {
834 NewPrivateFile->IsDirectoryPath = FALSE;
835 }
836 } else {
837 struct stat finfo;
838 int res = NewPrivateFile->UnixThunk->Stat (NewPrivateFile->FileName, &finfo);
839 if (res == 0 && S_ISDIR(finfo.st_mode))
840 NewPrivateFile->IsDirectoryPath = TRUE;
841 else
842 NewPrivateFile->IsDirectoryPath = FALSE;
843 }
844
845 if (OpenMode & EFI_FILE_MODE_WRITE) {
846 NewPrivateFile->IsOpenedByRead = FALSE;
847 } else {
848 NewPrivateFile->IsOpenedByRead = TRUE;
849 }
850
851 Status = EFI_SUCCESS;
852
853 //
854 // deal with directory
855 //
856 if (NewPrivateFile->IsDirectoryPath) {
857
858 if ((OpenMode & EFI_FILE_MODE_CREATE)) {
859 //
860 // Create a directory
861 //
862 if (NewPrivateFile->UnixThunk->MkDir (NewPrivateFile->FileName, 0777) != 0) {
863 INTN LastError;
864
865 LastError = PrivateFile->UnixThunk->GetErrno ();
866 if (LastError != EEXIST) {
867 //gBS->FreePool (TempFileName);
868 Status = EFI_ACCESS_DENIED;
869 goto Done;
870 }
871 }
872 }
873
874 NewPrivateFile->Dir = NewPrivateFile->UnixThunk->OpenDir
875 (NewPrivateFile->FileName);
876
877 if (NewPrivateFile->Dir == NULL) {
878 if (PrivateFile->UnixThunk->GetErrno () == EACCES) {
879 Status = EFI_ACCESS_DENIED;
880 } else {
881 Status = EFI_NOT_FOUND;
882 }
883
884 goto Done;
885 }
886
887 } else {
888 //
889 // deal with file
890 //
891 NewPrivateFile->fd = NewPrivateFile->UnixThunk->Open
892 (NewPrivateFile->FileName,
893 ((OpenMode & EFI_FILE_MODE_CREATE) ? O_CREAT : 0)
894 | (NewPrivateFile->IsOpenedByRead ? O_RDONLY : O_RDWR),
895 0666);
896 if (NewPrivateFile->fd < 0) {
897 if (PrivateFile->UnixThunk->GetErrno () == ENOENT) {
898 Status = EFI_NOT_FOUND;
899 } else {
900 Status = EFI_ACCESS_DENIED;
901 }
902 }
903 }
904
905 if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {
906 //
907 // Set the attribute
908 //
909 InfoSize = 0;
910 Info = NULL;
911
912 Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
913
914 if (Status != EFI_BUFFER_TOO_SMALL) {
915 Status = EFI_DEVICE_ERROR;
916 goto Done;
917 }
918
919 Status = gBS->AllocatePool (
920 EfiBootServicesData,
921 InfoSize,
922 (VOID **)&Info
923 );
924
925 if (EFI_ERROR (Status)) {
926 goto Done;
927 }
928
929 Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
930
931 if (EFI_ERROR (Status)) {
932 goto Done;
933 }
934
935 Info->Attribute = Attributes;
936
937 UnixSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);
938 }
939
940 Done: ;
941 if (TrailingDash) {
942 FileName[StrLen (FileName) + 1] = 0;
943 FileName[StrLen (FileName)] = L'\\';
944 }
945
946 if (EFI_ERROR (Status)) {
947 if (NewPrivateFile) {
948 if (NewPrivateFile->FileName) {
949 gBS->FreePool (NewPrivateFile->FileName);
950 }
951
952 gBS->FreePool (NewPrivateFile);
953 }
954 } else {
955 *NewHandle = &NewPrivateFile->EfiFile;
956 }
957
958 return Status;
959 }
960
961 EFI_STATUS
962 EFIAPI
963 UnixSimpleFileSystemClose (
964 IN EFI_FILE *This
965 )
966 /*++
967
968 Routine Description:
969
970 Close the specified file handle.
971
972 Arguments:
973
974 This - Pointer to a returned opened file handle.
975
976 Returns:
977
978 EFI_SUCCESS - The file handle has been closed.
979
980 --*/
981 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
982 {
983 UNIX_EFI_FILE_PRIVATE *PrivateFile;
984 EFI_TPL OldTpl;
985
986 if (This == NULL) {
987 return EFI_INVALID_PARAMETER;
988 }
989
990 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
991
992 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
993
994 if (PrivateFile->fd >= 0) {
995 PrivateFile->UnixThunk->Close (PrivateFile->fd);
996 }
997 if (PrivateFile->Dir != NULL) {
998 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);
999 }
1000
1001 PrivateFile->fd = -1;
1002 PrivateFile->Dir = NULL;
1003
1004 if (PrivateFile->FileName) {
1005 gBS->FreePool (PrivateFile->FileName);
1006 }
1007
1008 gBS->FreePool (PrivateFile);
1009
1010 gBS->RestoreTPL (OldTpl);
1011
1012 return EFI_SUCCESS;
1013 }
1014
1015 EFI_STATUS
1016 EFIAPI
1017 UnixSimpleFileSystemDelete (
1018 IN EFI_FILE *This
1019 )
1020 /*++
1021
1022 Routine Description:
1023
1024 Close and delete a file.
1025
1026 Arguments:
1027
1028 This - Pointer to a returned opened file handle.
1029
1030 Returns:
1031
1032 EFI_SUCCESS - The file handle was closed and deleted.
1033
1034 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1035
1036 --*/
1037 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1038 {
1039 EFI_STATUS Status;
1040 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1041 EFI_TPL OldTpl;
1042
1043 if (This == NULL) {
1044 return EFI_INVALID_PARAMETER;
1045 }
1046
1047 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
1048
1049 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1050
1051 Status = EFI_WARN_DELETE_FAILURE;
1052
1053 if (PrivateFile->IsDirectoryPath) {
1054 if (PrivateFile->Dir != NULL) {
1055 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);
1056 PrivateFile->Dir = NULL;
1057 }
1058
1059 if (PrivateFile->UnixThunk->RmDir (PrivateFile->FileName) == 0) {
1060 Status = EFI_SUCCESS;
1061 }
1062 } else {
1063 PrivateFile->UnixThunk->Close (PrivateFile->fd);
1064 PrivateFile->fd = -1;
1065
1066 if (!PrivateFile->IsOpenedByRead) {
1067 if (!PrivateFile->UnixThunk->UnLink (PrivateFile->FileName)) {
1068 Status = EFI_SUCCESS;
1069 }
1070 }
1071 }
1072
1073 gBS->FreePool (PrivateFile->FileName);
1074 gBS->FreePool (PrivateFile);
1075
1076 gBS->RestoreTPL (OldTpl);
1077
1078 return Status;
1079 }
1080
1081 STATIC
1082 VOID
1083 UnixSystemTimeToEfiTime (
1084 EFI_UNIX_THUNK_PROTOCOL *UnixThunk,
1085 IN time_t SystemTime,
1086 OUT EFI_TIME *Time
1087 )
1088 /*++
1089
1090 Routine Description:
1091
1092 TODO: Add function description
1093
1094 Arguments:
1095
1096 SystemTime - TODO: add argument description
1097 TimeZone - TODO: add argument description
1098 Time - TODO: add argument description
1099
1100 Returns:
1101
1102 TODO: add return values
1103
1104 --*/
1105 {
1106 struct tm *tm;
1107 tm = UnixThunk->GmTime (&SystemTime);
1108 Time->Year = tm->tm_year;
1109 Time->Month = tm->tm_mon;
1110 Time->Day = tm->tm_mday;
1111 Time->Hour = tm->tm_hour;
1112 Time->Minute = tm->tm_min;
1113 Time->Second = tm->tm_sec;
1114 Time->Nanosecond = 0;
1115
1116 Time->TimeZone = UnixThunk->GetTimeZone ();
1117
1118 if (UnixThunk->GetDayLight ()) {
1119 Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;
1120 }
1121 }
1122
1123 STATIC
1124 EFI_STATUS
1125 UnixSimpleFileSystemFileInfo (
1126 UNIX_EFI_FILE_PRIVATE *PrivateFile,
1127 IN CHAR8 *FileName,
1128 IN OUT UINTN *BufferSize,
1129 OUT VOID *Buffer
1130 )
1131 /*++
1132
1133 Routine Description:
1134
1135 TODO: Add function description
1136
1137 Arguments:
1138
1139 PrivateFile - TODO: add argument description
1140 BufferSize - TODO: add argument description
1141 Buffer - TODO: add argument description
1142
1143 Returns:
1144
1145 TODO: add return values
1146
1147 --*/
1148 {
1149 EFI_STATUS Status;
1150 UINTN Size;
1151 UINTN NameSize;
1152 UINTN ResultSize;
1153 EFI_FILE_INFO *Info;
1154 CHAR8 *RealFileName;
1155 CHAR8 *TempPointer;
1156 CHAR16 *BufferFileName;
1157 struct stat buf;
1158
1159 if (FileName != NULL) {
1160 RealFileName = FileName;
1161 }
1162 else if (PrivateFile->IsRootDirectory) {
1163 RealFileName = "";
1164 } else {
1165 RealFileName = PrivateFile->FileName;
1166 }
1167
1168 TempPointer = RealFileName;
1169 while (*TempPointer) {
1170 if (*TempPointer == '/') {
1171 RealFileName = TempPointer + 1;
1172 }
1173
1174 TempPointer++;
1175 }
1176
1177 Size = SIZE_OF_EFI_FILE_INFO;
1178 NameSize = AsciiStrSize (RealFileName) * 2;
1179 ResultSize = Size + NameSize;
1180
1181 if (*BufferSize < ResultSize) {
1182 *BufferSize = ResultSize;
1183 return EFI_BUFFER_TOO_SMALL;
1184 }
1185 if (PrivateFile->UnixThunk->Stat (
1186 FileName == NULL ? PrivateFile->FileName : FileName,
1187 &buf) < 0)
1188 return EFI_DEVICE_ERROR;
1189
1190 Status = EFI_SUCCESS;
1191
1192 Info = Buffer;
1193 ZeroMem (Info, ResultSize);
1194
1195 Info->Size = ResultSize;
1196 Info->FileSize = buf.st_size;
1197 Info->PhysicalSize = MultU64x32 (buf.st_blocks, buf.st_blksize);
1198
1199 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_ctime, &Info->CreateTime);
1200 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_atime, &Info->LastAccessTime);
1201 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_mtime, &Info->ModificationTime);
1202
1203 if (!(buf.st_mode & S_IWUSR)) {
1204 Info->Attribute |= EFI_FILE_READ_ONLY;
1205 }
1206
1207 if (S_ISDIR(buf.st_mode)) {
1208 Info->Attribute |= EFI_FILE_DIRECTORY;
1209 }
1210
1211
1212 BufferFileName = (CHAR16 *)((CHAR8 *) Buffer + Size);
1213 while (*RealFileName)
1214 *BufferFileName++ = *RealFileName++;
1215 *BufferFileName = 0;
1216
1217 *BufferSize = ResultSize;
1218 return Status;
1219 }
1220
1221 EFI_STATUS
1222 EFIAPI
1223 UnixSimpleFileSystemRead (
1224 IN EFI_FILE *This,
1225 IN OUT UINTN *BufferSize,
1226 OUT VOID *Buffer
1227 )
1228 /*++
1229
1230 Routine Description:
1231
1232 Read data from a file.
1233
1234 Arguments:
1235
1236 This - Pointer to a returned open file handle.
1237
1238 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1239
1240 Buffer - Pointer to the first byte of the read Buffer.
1241
1242 Returns:
1243
1244 EFI_SUCCESS - The data was read.
1245
1246 EFI_NO_MEDIA - The device has no media.
1247
1248 EFI_DEVICE_ERROR - The device reported an error.
1249
1250 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1251
1252 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1253 *BufferSize has been updated with the size needed to complete the request.
1254
1255 --*/
1256 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1257 {
1258 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1259 EFI_STATUS Status;
1260 INTN Res;
1261 UINTN Size;
1262 UINTN NameSize;
1263 UINTN ResultSize;
1264 CHAR8 *FullFileName;
1265 EFI_TPL OldTpl;
1266
1267 if (This == NULL || BufferSize == NULL || Buffer == NULL) {
1268 return EFI_INVALID_PARAMETER;
1269 }
1270
1271 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
1272
1273 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1274
1275 if (!PrivateFile->IsDirectoryPath) {
1276
1277 if (PrivateFile->fd < 0) {
1278 Status = EFI_DEVICE_ERROR;
1279 goto Done;
1280 }
1281
1282 Res = PrivateFile->UnixThunk->Read (
1283 PrivateFile->fd,
1284 Buffer,
1285 *BufferSize);
1286 if (Res < 0) {
1287 Status = EFI_DEVICE_ERROR;
1288 goto Done;
1289 }
1290 *BufferSize = Res;
1291 Status = EFI_SUCCESS;
1292 goto Done;
1293 }
1294
1295 //
1296 // Read on a directory.
1297 //
1298 if (PrivateFile->Dir == NULL) {
1299 Status = EFI_DEVICE_ERROR;
1300 goto Done;
1301 }
1302
1303 if (PrivateFile->Dirent == NULL) {
1304 PrivateFile->Dirent = PrivateFile->UnixThunk->ReadDir (PrivateFile->Dir);
1305 if (PrivateFile->Dirent == NULL) {
1306 *BufferSize = 0;
1307 Status = EFI_SUCCESS;
1308 goto Done;
1309 }
1310 }
1311
1312 Size = SIZE_OF_EFI_FILE_INFO;
1313 NameSize = AsciiStrLen (PrivateFile->Dirent->d_name) + 1;
1314 ResultSize = Size + 2 * NameSize;
1315
1316 if (*BufferSize < ResultSize) {
1317 *BufferSize = ResultSize;
1318 Status = EFI_BUFFER_TOO_SMALL;
1319 goto Done;
1320 }
1321 Status = EFI_SUCCESS;
1322
1323 *BufferSize = ResultSize;
1324
1325 Status = gBS->AllocatePool (
1326 EfiBootServicesData,
1327 AsciiStrLen(PrivateFile->FileName) + 1 + NameSize,
1328 (VOID **)&FullFileName
1329 );
1330
1331 if (EFI_ERROR (Status)) {
1332 goto Done;
1333 }
1334
1335 AsciiStrCpy(FullFileName, PrivateFile->FileName);
1336 AsciiStrCat(FullFileName, "/");
1337 AsciiStrCat(FullFileName, PrivateFile->Dirent->d_name);
1338 Status = UnixSimpleFileSystemFileInfo (PrivateFile,
1339 FullFileName,
1340 BufferSize,
1341 Buffer);
1342 gBS->FreePool (FullFileName);
1343
1344 PrivateFile->Dirent = NULL;
1345
1346 Done:
1347 gBS->RestoreTPL (OldTpl);
1348
1349 return Status;
1350 }
1351
1352 EFI_STATUS
1353 EFIAPI
1354 UnixSimpleFileSystemWrite (
1355 IN EFI_FILE *This,
1356 IN OUT UINTN *BufferSize,
1357 IN VOID *Buffer
1358 )
1359 /*++
1360
1361 Routine Description:
1362
1363 Write data to a file.
1364
1365 Arguments:
1366
1367 This - Pointer to an opened file handle.
1368
1369 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1370 of data written to the file.
1371
1372 Buffer - Pointer to the first by of data in the buffer to write to the file.
1373
1374 Returns:
1375
1376 EFI_SUCCESS - The data was written to the file.
1377
1378 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1379
1380 EFI_NO_MEDIA - The device has no media.
1381
1382 EFI_DEVICE_ERROR - The device reported an error.
1383
1384 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1385
1386 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1387
1388 EFI_ACCESS_DENIED - The file was opened read-only.
1389
1390 EFI_VOLUME_FULL - The volume is full.
1391
1392 --*/
1393 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1394 {
1395 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1396 UINTN Res;
1397 EFI_STATUS Status;
1398 EFI_TPL OldTpl;
1399
1400 if (This == NULL || BufferSize == NULL || Buffer == NULL) {
1401 return EFI_INVALID_PARAMETER;
1402 }
1403
1404 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
1405
1406 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1407
1408 if (PrivateFile->fd < 0) {
1409 return EFI_DEVICE_ERROR;
1410 }
1411
1412 if (PrivateFile->IsDirectoryPath) {
1413 return EFI_UNSUPPORTED;
1414 }
1415
1416 if (PrivateFile->IsOpenedByRead) {
1417 return EFI_ACCESS_DENIED;
1418 }
1419
1420 Res = PrivateFile->UnixThunk->Write (
1421 PrivateFile->fd,
1422 Buffer,
1423 *BufferSize);
1424 if (Res == (UINTN)-1) {
1425 Status = EFI_DEVICE_ERROR;
1426 goto Done;
1427 }
1428 *BufferSize = Res;
1429 Status = EFI_SUCCESS;
1430
1431 Done:
1432 gBS->RestoreTPL (OldTpl);
1433 return Status;
1434
1435 //
1436 // bugbug: need to access unix error reporting
1437 //
1438 }
1439
1440 EFI_STATUS
1441 EFIAPI
1442 UnixSimpleFileSystemSetPosition (
1443 IN EFI_FILE *This,
1444 IN UINT64 Position
1445 )
1446 /*++
1447
1448 Routine Description:
1449
1450 Set a file's current position.
1451
1452 Arguments:
1453
1454 This - Pointer to an opened file handle.
1455
1456 Position - The byte position from the start of the file to set.
1457
1458 Returns:
1459
1460 EFI_SUCCESS - The file position has been changed.
1461
1462 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1463
1464 --*/
1465 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1466 {
1467 EFI_STATUS Status;
1468 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1469 UINT64 Pos;
1470 EFI_TPL OldTpl;
1471
1472 if (This == NULL) {
1473 return EFI_INVALID_PARAMETER;
1474 }
1475
1476 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
1477
1478 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1479
1480 if (PrivateFile->IsDirectoryPath) {
1481 if (Position != 0) {
1482 Status = EFI_UNSUPPORTED;
1483 goto Done;
1484 }
1485
1486 if (PrivateFile->Dir == NULL) {
1487 Status = EFI_DEVICE_ERROR;
1488 goto Done;
1489 }
1490 PrivateFile->UnixThunk->RewindDir (PrivateFile->Dir);
1491 Status = EFI_SUCCESS;
1492 goto Done;
1493 } else {
1494 if (Position == (UINT64) -1) {
1495 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_END);
1496 } else {
1497 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, Position, SEEK_SET);
1498 }
1499 Status = (Pos == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
1500 }
1501
1502 Done:
1503 gBS->RestoreTPL (OldTpl);
1504 return Status;
1505 }
1506
1507 EFI_STATUS
1508 EFIAPI
1509 UnixSimpleFileSystemGetPosition (
1510 IN EFI_FILE *This,
1511 OUT UINT64 *Position
1512 )
1513 /*++
1514
1515 Routine Description:
1516
1517 Get a file's current position.
1518
1519 Arguments:
1520
1521 This - Pointer to an opened file handle.
1522
1523 Position - Pointer to storage for the current position.
1524
1525 Returns:
1526
1527 EFI_SUCCESS - The file position has been reported.
1528
1529 EFI_UNSUPPORTED - Not valid for directories.
1530
1531 --*/
1532 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1533 {
1534 EFI_STATUS Status;
1535 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1536 EFI_TPL OldTpl;
1537
1538 if (This == NULL || Position == NULL) {
1539 return EFI_INVALID_PARAMETER;
1540 }
1541
1542 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
1543
1544 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1545
1546 if (PrivateFile->IsDirectoryPath) {
1547 Status = EFI_UNSUPPORTED;
1548 } else {
1549 *Position = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_CUR);
1550 Status = (*Position == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
1551 }
1552
1553 gBS->RestoreTPL (OldTpl);
1554 return Status;
1555 }
1556
1557 EFI_STATUS
1558 EFIAPI
1559 UnixSimpleFileSystemGetInfo (
1560 IN EFI_FILE *This,
1561 IN EFI_GUID *InformationType,
1562 IN OUT UINTN *BufferSize,
1563 OUT VOID *Buffer
1564 )
1565 /*++
1566
1567 Routine Description:
1568
1569 Return information about a file or volume.
1570
1571 Arguments:
1572
1573 This - Pointer to an opened file handle.
1574
1575 InformationType - GUID describing the type of information to be returned.
1576
1577 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
1578 information buffer.
1579
1580 Buffer - Pointer to the first byte of the information buffer.
1581
1582 Returns:
1583
1584 EFI_SUCCESS - The requested information has been written into the buffer.
1585
1586 EFI_UNSUPPORTED - The InformationType is not known.
1587
1588 EFI_NO_MEDIA - The device has no media.
1589
1590 EFI_DEVICE_ERROR - The device reported an error.
1591
1592 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1593
1594 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
1595 been updated with the size needed to complete the requested operation.
1596
1597 --*/
1598 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1599 {
1600 EFI_STATUS Status;
1601 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1602 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;
1603 INTN UnixStatus;
1604 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
1605 struct statfs buf;
1606 EFI_TPL OldTpl;
1607
1608 if (This == NULL || InformationType == NULL || BufferSize == NULL) {
1609 return EFI_INVALID_PARAMETER;
1610 }
1611
1612 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
1613
1614 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1615 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
1616
1617 Status = EFI_UNSUPPORTED;
1618
1619 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
1620 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, BufferSize, Buffer);
1621 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
1622 if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {
1623 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
1624 Status = EFI_BUFFER_TOO_SMALL;
1625 goto Done;
1626 }
1627
1628 UnixStatus = PrivateFile->UnixThunk->StatFs (PrivateFile->FileName, &buf);
1629 if (UnixStatus < 0) {
1630 Status = EFI_DEVICE_ERROR;
1631 goto Done;
1632 }
1633
1634 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;
1635 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
1636 FileSystemInfoBuffer->ReadOnly = FALSE;
1637
1638 //
1639 // Succeeded
1640 //
1641 FileSystemInfoBuffer->VolumeSize = MultU64x32 (buf.f_blocks, buf.f_bsize);
1642 FileSystemInfoBuffer->FreeSpace = MultU64x32 (buf.f_bavail, buf.f_bsize);
1643 FileSystemInfoBuffer->BlockSize = buf.f_bsize;
1644
1645
1646 StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);
1647 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
1648 Status = EFI_SUCCESS;
1649 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
1650 if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
1651 *BufferSize = StrSize (PrivateRoot->VolumeLabel);
1652 Status = EFI_BUFFER_TOO_SMALL;
1653 goto Done;
1654 }
1655
1656 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);
1657 *BufferSize = StrSize (PrivateRoot->VolumeLabel);
1658 Status = EFI_SUCCESS;
1659 }
1660
1661 Done:
1662 gBS->RestoreTPL (OldTpl);
1663 return Status;
1664 }
1665
1666 EFI_STATUS
1667 EFIAPI
1668 UnixSimpleFileSystemSetInfo (
1669 IN EFI_FILE *This,
1670 IN EFI_GUID *InformationType,
1671 IN UINTN BufferSize,
1672 IN VOID *Buffer
1673 )
1674 /*++
1675
1676 Routine Description:
1677
1678 Set information about a file or volume.
1679
1680 Arguments:
1681
1682 This - Pointer to an opened file handle.
1683
1684 InformationType - GUID identifying the type of information to set.
1685
1686 BufferSize - Number of bytes of data in the information buffer.
1687
1688 Buffer - Pointer to the first byte of data in the information buffer.
1689
1690 Returns:
1691
1692 EFI_SUCCESS - The file or volume information has been updated.
1693
1694 EFI_UNSUPPORTED - The information identifier is not recognised.
1695
1696 EFI_NO_MEDIA - The device has no media.
1697
1698 EFI_DEVICE_ERROR - The device reported an error.
1699
1700 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1701
1702 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1703
1704 EFI_ACCESS_DENIED - The file was opened read-only.
1705
1706 EFI_VOLUME_FULL - The volume is full.
1707
1708 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
1709
1710 --*/
1711 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1712 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1713 {
1714 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
1715 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1716 EFI_FILE_INFO *OldFileInfo;
1717 EFI_FILE_INFO *NewFileInfo;
1718 EFI_STATUS Status;
1719 UINTN OldInfoSize;
1720 EFI_TPL OldTpl;
1721 mode_t NewAttr;
1722 struct stat OldAttr;
1723 CHAR8 *OldFileName;
1724 CHAR8 *NewFileName;
1725 CHAR8 *CharPointer;
1726 BOOLEAN AttrChangeFlag;
1727 BOOLEAN NameChangeFlag;
1728 BOOLEAN SizeChangeFlag;
1729 BOOLEAN TimeChangeFlag;
1730 struct tm NewLastAccessSystemTime;
1731 struct tm NewLastWriteSystemTime;
1732 EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;
1733 CHAR8 *AsciiFilePtr;
1734 CHAR16 *UnicodeFilePtr;
1735 INTN UnixStatus;
1736
1737 //
1738 // Check for invalid parameters.
1739 //
1740 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {
1741 return EFI_INVALID_PARAMETER;
1742 }
1743
1744 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
1745
1746 //
1747 // Initialise locals.
1748 //
1749 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1750 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
1751
1752 Status = EFI_UNSUPPORTED;
1753 OldFileInfo = NewFileInfo = NULL;
1754 OldFileName = NewFileName = NULL;
1755 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;
1756
1757 //
1758 // Set file system information.
1759 //
1760 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
1761 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {
1762 Status = EFI_BAD_BUFFER_SIZE;
1763 goto Done;
1764 }
1765
1766 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;
1767
1768 gBS->FreePool (PrivateRoot->VolumeLabel);
1769
1770 PrivateRoot->VolumeLabel = NULL;
1771 Status = gBS->AllocatePool (
1772 EfiBootServicesData,
1773 StrSize (NewFileSystemInfo->VolumeLabel),
1774 (VOID **)&PrivateRoot->VolumeLabel
1775 );
1776
1777 if (EFI_ERROR (Status)) {
1778 goto Done;
1779 }
1780
1781 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);
1782
1783 Status = EFI_SUCCESS;
1784 goto Done;
1785 }
1786
1787 //
1788 // Set volume label information.
1789 //
1790 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
1791 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
1792 Status = EFI_BAD_BUFFER_SIZE;
1793 goto Done;
1794 }
1795
1796 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);
1797
1798 Status = EFI_SUCCESS;
1799 goto Done;
1800 }
1801
1802 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {
1803 Status = EFI_UNSUPPORTED;
1804 goto Done;
1805 }
1806
1807 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {
1808 Status = EFI_BAD_BUFFER_SIZE;
1809 goto Done;
1810 }
1811
1812 //
1813 // Set file/directory information.
1814 //
1815
1816 //
1817 // Check for invalid set file information parameters.
1818 //
1819 NewFileInfo = (EFI_FILE_INFO *) Buffer;
1820
1821 if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) ||
1822 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||
1823 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)
1824 ) {
1825 Status = EFI_INVALID_PARAMETER;
1826 goto Done;
1827 }
1828
1829 //
1830 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
1831 // that would have an additional parameter that would be the size
1832 // of the string array just in case there are no NULL characters in
1833 // the string array.
1834 //
1835 //
1836 // Get current file information so we can determine what kind
1837 // of change request this is.
1838 //
1839 OldInfoSize = 0;
1840 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, NULL);
1841
1842 if (Status != EFI_BUFFER_TOO_SMALL) {
1843 Status = EFI_DEVICE_ERROR;
1844 goto Done;
1845 }
1846
1847 Status = gBS->AllocatePool (EfiBootServicesData, OldInfoSize,
1848 (VOID **)&OldFileInfo);
1849
1850 if (EFI_ERROR (Status)) {
1851 goto Done;
1852 }
1853
1854 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, OldFileInfo);
1855
1856 if (EFI_ERROR (Status)) {
1857 goto Done;
1858 }
1859
1860 Status = gBS->AllocatePool (
1861 EfiBootServicesData,
1862 AsciiStrSize (PrivateFile->FileName),
1863 (VOID **)&OldFileName
1864 );
1865
1866 if (EFI_ERROR (Status)) {
1867 goto Done;
1868 }
1869
1870 AsciiStrCpy (OldFileName, PrivateFile->FileName);
1871
1872 //
1873 // Make full pathname from new filename and rootpath.
1874 //
1875 if (NewFileInfo->FileName[0] == '\\') {
1876 Status = gBS->AllocatePool (
1877 EfiBootServicesData,
1878 AsciiStrLen (PrivateRoot->FilePath) + 1 + StrLen (NewFileInfo->FileName) + 1,
1879 (VOID **)&NewFileName
1880 );
1881
1882 if (EFI_ERROR (Status)) {
1883 goto Done;
1884 }
1885
1886 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);
1887 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);
1888 UnicodeFilePtr = NewFileInfo->FileName + 1;
1889 *AsciiFilePtr++ ='/';
1890 } else {
1891 Status = gBS->AllocatePool (
1892 EfiBootServicesData,
1893 AsciiStrLen (PrivateFile->FileName) + 1 + StrLen (NewFileInfo->FileName) + 1,
1894 (VOID **)&NewFileName
1895 );
1896
1897 if (EFI_ERROR (Status)) {
1898 goto Done;
1899 }
1900
1901 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);
1902 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);
1903 while (AsciiFilePtr > NewFileName && AsciiFilePtr[-1] != '/') {
1904 AsciiFilePtr--;
1905 }
1906 UnicodeFilePtr = NewFileInfo->FileName;
1907 }
1908 // Convert to ascii.
1909 while (*UnicodeFilePtr) {
1910 *AsciiFilePtr++ = *UnicodeFilePtr++;
1911 }
1912 *AsciiFilePtr = 0;
1913
1914
1915 //
1916 // Is there an attribute change request?
1917 //
1918 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {
1919 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
1920 Status = EFI_INVALID_PARAMETER;
1921 goto Done;
1922 }
1923
1924 AttrChangeFlag = TRUE;
1925 }
1926
1927 //
1928 // Is there a name change request?
1929 // bugbug: - Need EfiStrCaseCmp()
1930 //
1931 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {
1932 NameChangeFlag = TRUE;
1933 }
1934
1935 //
1936 // Is there a size change request?
1937 //
1938 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {
1939 SizeChangeFlag = TRUE;
1940 }
1941
1942 //
1943 // Is there a time stamp change request?
1944 //
1945 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&
1946 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))
1947 ) {
1948 TimeChangeFlag = TRUE;
1949 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&
1950 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))
1951 ) {
1952 TimeChangeFlag = TRUE;
1953 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&
1954 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))
1955 ) {
1956 TimeChangeFlag = TRUE;
1957 }
1958
1959 //
1960 // All done if there are no change requests being made.
1961 //
1962 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {
1963 Status = EFI_SUCCESS;
1964 goto Done;
1965 }
1966
1967 //
1968 // Set file or directory information.
1969 //
1970 if (PrivateFile->UnixThunk->Stat (OldFileName, &OldAttr) != 0) {
1971 Status = EFI_DEVICE_ERROR;
1972 goto Done;
1973 }
1974
1975 //
1976 // Name change.
1977 //
1978 if (NameChangeFlag) {
1979 //
1980 // Close the handles first
1981 //
1982 if (PrivateFile->IsOpenedByRead) {
1983 Status = EFI_ACCESS_DENIED;
1984 goto Done;
1985 }
1986
1987 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {
1988 }
1989
1990 if (*CharPointer != 0) {
1991 Status = EFI_ACCESS_DENIED;
1992 goto Done;
1993 }
1994
1995 UnixStatus = PrivateFile->UnixThunk->Rename (OldFileName, NewFileName);
1996
1997 if (UnixStatus == 0) {
1998 //
1999 // modify file name
2000 //
2001 gBS->FreePool (PrivateFile->FileName);
2002
2003 Status = gBS->AllocatePool (
2004 EfiBootServicesData,
2005 AsciiStrSize (NewFileName),
2006 (VOID **)&PrivateFile->FileName
2007 );
2008
2009 if (EFI_ERROR (Status)) {
2010 goto Done;
2011 }
2012
2013 AsciiStrCpy (PrivateFile->FileName, NewFileName);
2014 } else {
2015 Status = EFI_DEVICE_ERROR;
2016 goto Done;
2017 }
2018 }
2019
2020 //
2021 // Size change
2022 //
2023 if (SizeChangeFlag) {
2024 if (PrivateFile->IsDirectoryPath) {
2025 Status = EFI_UNSUPPORTED;
2026 goto Done;
2027 }
2028
2029 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {
2030 Status = EFI_ACCESS_DENIED;
2031 goto Done;
2032 }
2033
2034 if (PrivateFile->UnixThunk->FTruncate (PrivateFile->fd, NewFileInfo->FileSize) != 0) {
2035 Status = EFI_DEVICE_ERROR;
2036 goto Done;
2037 }
2038
2039 }
2040
2041 //
2042 // Time change
2043 //
2044 if (TimeChangeFlag) {
2045 struct utimbuf utime;
2046
2047 NewLastAccessSystemTime.tm_year = NewFileInfo->LastAccessTime.Year;
2048 NewLastAccessSystemTime.tm_mon = NewFileInfo->LastAccessTime.Month;
2049 NewLastAccessSystemTime.tm_mday = NewFileInfo->LastAccessTime.Day;
2050 NewLastAccessSystemTime.tm_hour = NewFileInfo->LastAccessTime.Hour;
2051 NewLastAccessSystemTime.tm_min = NewFileInfo->LastAccessTime.Minute;
2052 NewLastAccessSystemTime.tm_sec = NewFileInfo->LastAccessTime.Second;
2053 NewLastAccessSystemTime.tm_isdst = 0;
2054
2055 utime.actime = PrivateFile->UnixThunk->MkTime (&NewLastAccessSystemTime);
2056
2057 NewLastWriteSystemTime.tm_year = NewFileInfo->ModificationTime.Year;
2058 NewLastWriteSystemTime.tm_mon = NewFileInfo->ModificationTime.Month;
2059 NewLastWriteSystemTime.tm_mday = NewFileInfo->ModificationTime.Day;
2060 NewLastWriteSystemTime.tm_hour = NewFileInfo->ModificationTime.Hour;
2061 NewLastWriteSystemTime.tm_min = NewFileInfo->ModificationTime.Minute;
2062 NewLastWriteSystemTime.tm_sec = NewFileInfo->ModificationTime.Second;
2063 NewLastWriteSystemTime.tm_isdst = 0;
2064
2065 utime.modtime = PrivateFile->UnixThunk->MkTime (&NewLastWriteSystemTime);
2066
2067 if (utime.actime == (time_t)-1 || utime.modtime == (time_t)-1) {
2068 goto Done;
2069 }
2070
2071 if (PrivateFile->UnixThunk->UTime (PrivateFile->FileName, &utime) == -1) {
2072 goto Done;
2073 }
2074 }
2075
2076 //
2077 // No matter about AttrChangeFlag, Attribute must be set.
2078 // Because operation before may cause attribute change.
2079 //
2080 NewAttr = OldAttr.st_mode;
2081
2082 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {
2083 NewAttr &= ~(S_IRUSR | S_IRGRP | S_IROTH);
2084 } else {
2085 NewAttr |= S_IRUSR;
2086 }
2087
2088 UnixStatus = PrivateFile->UnixThunk->Chmod (NewFileName, NewAttr);
2089
2090 if (UnixStatus != 0) {
2091 Status = EFI_DEVICE_ERROR;
2092 }
2093
2094 Done:
2095 if (OldFileInfo != NULL) {
2096 gBS->FreePool (OldFileInfo);
2097 }
2098
2099 if (OldFileName != NULL) {
2100 gBS->FreePool (OldFileName);
2101 }
2102
2103 if (NewFileName != NULL) {
2104 gBS->FreePool (NewFileName);
2105 }
2106
2107 gBS->RestoreTPL (OldTpl);
2108
2109 return Status;
2110 }
2111
2112 EFI_STATUS
2113 EFIAPI
2114 UnixSimpleFileSystemFlush (
2115 IN EFI_FILE *This
2116 )
2117 /*++
2118
2119 Routine Description:
2120
2121 Flush all modified data to the media.
2122
2123 Arguments:
2124
2125 This - Pointer to an opened file handle.
2126
2127 Returns:
2128
2129 EFI_SUCCESS - The data has been flushed.
2130
2131 EFI_NO_MEDIA - The device has no media.
2132
2133 EFI_DEVICE_ERROR - The device reported an error.
2134
2135 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2136
2137 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2138
2139 EFI_ACCESS_DENIED - The file was opened read-only.
2140
2141 EFI_VOLUME_FULL - The volume is full.
2142
2143 --*/
2144 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2145 {
2146 UNIX_EFI_FILE_PRIVATE *PrivateFile;
2147 EFI_STATUS Status;
2148 EFI_TPL OldTpl;
2149
2150 if (This == NULL) {
2151 return EFI_INVALID_PARAMETER;
2152 }
2153
2154 Status = EFI_SUCCESS;
2155 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
2156
2157 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
2158
2159
2160 if (PrivateFile->IsDirectoryPath) {
2161 goto Done;
2162 }
2163
2164 if (PrivateFile->IsOpenedByRead) {
2165 Status = EFI_ACCESS_DENIED;
2166 goto Done;
2167 }
2168
2169 if (PrivateFile->fd < 0) {
2170 Status = EFI_DEVICE_ERROR;
2171 goto Done;
2172 }
2173
2174 PrivateFile->UnixThunk->FSync (PrivateFile->fd) == 0 ? EFI_SUCCESS : EFI_DEVICE_ERROR;
2175
2176 Done:
2177 gBS->RestoreTPL (OldTpl);
2178
2179 return Status;
2180
2181 //
2182 // bugbug: - Use Unix error reporting.
2183 //
2184 }
2185
2186