3 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
4 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
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.
14 UnixSimpleFileSystem.c
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.
23 * Other names and brands may be claimed as the property of others.
27 #include "UnixSimpleFileSystem.h"
29 EFI_DRIVER_BINDING_PROTOCOL gUnixSimpleFileSystemDriverBinding
= {
30 UnixSimpleFileSystemDriverBindingSupported
,
31 UnixSimpleFileSystemDriverBindingStart
,
32 UnixSimpleFileSystemDriverBindingStop
,
48 Locate the first occurance of a character in a string.
52 Str - Pointer to NULL terminated unicode string.
53 Chr - Character to locate.
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.
67 while (*Str
!= '\0' && *Str
!= Chr
) {
71 return (*Str
== Chr
) ? Str
: NULL
;
83 TODO: Add function description
87 Buffer - TODO: add argument description
88 Length - TODO: add argument description
92 TODO: add return values
96 if (Buffer
== NULL
|| Length
== 0) {
100 if (*(UINT8
*) Buffer
!= 0) {
105 if (!CompareMem (Buffer
, (UINT8
*) Buffer
+ 1, Length
- 1)) {
122 TODO: Add function description
126 Str - TODO: add argument description
127 Count - TODO: add argument description
131 TODO: add return values
137 if (AsciiStrLen (Str
) < Count
) {
141 for (Pointer
= Str
; *(Pointer
+ Count
); Pointer
++) {
142 *Pointer
= *(Pointer
+ Count
);
145 *Pointer
= *(Pointer
+ Count
);
152 UnixSimpleFileSystemDriverBindingSupported (
153 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
154 IN EFI_HANDLE ControllerHandle
,
155 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
161 Check to see if the driver supports a given controller.
165 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
167 ControllerHandle - EFI handle of the controller to test.
169 RemainingDevicePath - Pointer to remaining portion of a device path.
173 EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver
176 EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
177 the driver specified by This.
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.
182 EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the
183 driver specified by This.
188 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
191 // Open the IO Abstraction(s) needed to perform the supported test
193 Status
= gBS
->OpenProtocol (
195 &gEfiUnixIoProtocolGuid
,
197 This
->DriverBindingHandle
,
199 EFI_OPEN_PROTOCOL_BY_DRIVER
201 if (EFI_ERROR (Status
)) {
206 // Make sure GUID is for a File System handle.
208 Status
= EFI_UNSUPPORTED
;
209 if (CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixFileSystemGuid
)) {
210 Status
= EFI_SUCCESS
;
214 // Close the I/O Abstraction(s) used to perform the supported test
218 &gEfiUnixIoProtocolGuid
,
219 This
->DriverBindingHandle
,
228 UnixSimpleFileSystemDriverBindingStart (
229 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
230 IN EFI_HANDLE ControllerHandle
,
231 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
237 Starts a device controller or a bus controller.
241 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
243 ControllerHandle - EFI handle of the controller to start.
245 RemainingDevicePath - Pointer to remaining portion of a device path.
249 EFI_SUCCESS - The device or bus controller has been started.
251 EFI_DEVICE_ERROR - The device could not be started due to a device failure.
253 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
258 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
259 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
265 // Open the IO Abstraction(s) needed
267 Status
= gBS
->OpenProtocol (
269 &gEfiUnixIoProtocolGuid
,
271 This
->DriverBindingHandle
,
273 EFI_OPEN_PROTOCOL_BY_DRIVER
275 if (EFI_ERROR (Status
)) {
282 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixFileSystemGuid
)) {
283 Status
= EFI_UNSUPPORTED
;
287 Status
= gBS
->AllocatePool (
289 sizeof (UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
),
292 if (EFI_ERROR (Status
)) {
296 Private
->Signature
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE
;
297 Private
->UnixThunk
= UnixIo
->UnixThunk
;
298 Private
->FilePath
= NULL
;
299 Private
->VolumeLabel
= NULL
;
301 Status
= gBS
->AllocatePool (
303 StrLen (UnixIo
->EnvString
) + 1,
304 (VOID
**)&Private
->FilePath
307 if (EFI_ERROR (Status
)) {
311 for (i
= 0; UnixIo
->EnvString
[i
] != 0; i
++)
312 Private
->FilePath
[i
] = UnixIo
->EnvString
[i
];
313 Private
->FilePath
[i
] = 0;
315 Private
->VolumeLabel
= NULL
;
316 Status
= gBS
->AllocatePool (
318 StrSize (L
"EFI_EMULATED"),
319 (VOID
**)&Private
->VolumeLabel
322 if (EFI_ERROR (Status
)) {
326 StrCpy (Private
->VolumeLabel
, L
"EFI_EMULATED");
328 Private
->SimpleFileSystem
.Revision
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
;
329 Private
->SimpleFileSystem
.OpenVolume
= UnixSimpleFileSystemOpenVolume
;
331 Private
->ControllerNameTable
= NULL
;
335 gUnixSimpleFileSystemComponentName
.SupportedLanguages
,
336 &Private
->ControllerNameTable
,
340 Status
= gBS
->InstallMultipleProtocolInterfaces (
342 &gEfiSimpleFileSystemProtocolGuid
,
343 &Private
->SimpleFileSystem
,
348 if (EFI_ERROR (Status
)) {
350 if (Private
!= NULL
) {
352 if (Private
->VolumeLabel
!= NULL
)
353 gBS
->FreePool (Private
->VolumeLabel
);
354 if (Private
->FilePath
!= NULL
)
355 gBS
->FreePool (Private
->FilePath
);
356 FreeUnicodeStringTable (Private
->ControllerNameTable
);
358 gBS
->FreePool (Private
);
363 &gEfiUnixIoProtocolGuid
,
364 This
->DriverBindingHandle
,
374 UnixSimpleFileSystemDriverBindingStop (
375 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
376 IN EFI_HANDLE ControllerHandle
,
377 IN UINTN NumberOfChildren
,
378 IN EFI_HANDLE
*ChildHandleBuffer
384 TODO: Add function description
388 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
390 ControllerHandle - A handle to the device to be stopped.
392 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
394 ChildHandleBuffer - An array of child device handles to be freed.
398 EFI_SUCCESS - The device has been stopped.
400 EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.
403 // TODO: EFI_UNSUPPORTED - add return value to function comment
406 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFileSystem
;
407 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
410 // Get our context back
412 Status
= gBS
->OpenProtocol (
414 &gEfiSimpleFileSystemProtocolGuid
,
415 (VOID
**)&SimpleFileSystem
,
416 This
->DriverBindingHandle
,
418 EFI_OPEN_PROTOCOL_GET_PROTOCOL
420 if (EFI_ERROR (Status
)) {
421 return EFI_UNSUPPORTED
;
424 Private
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem
);
427 // Uninstall the Simple File System Protocol from ControllerHandle
429 Status
= gBS
->UninstallMultipleProtocolInterfaces (
431 &gEfiSimpleFileSystemProtocolGuid
,
432 &Private
->SimpleFileSystem
,
435 if (!EFI_ERROR (Status
)) {
436 Status
= gBS
->CloseProtocol (
438 &gEfiUnixIoProtocolGuid
,
439 This
->DriverBindingHandle
,
444 if (!EFI_ERROR (Status
)) {
446 // Free our instance data
448 FreeUnicodeStringTable (Private
->ControllerNameTable
);
450 gBS
->FreePool (Private
);
458 UnixSimpleFileSystemOpenVolume (
459 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
460 OUT EFI_FILE_PROTOCOL
**Root
466 Open the root directory on a volume.
470 This - A pointer to the volume to open.
472 Root - A pointer to storage for the returned opened file handle of the root directory.
476 EFI_SUCCESS - The volume was opened.
478 EFI_UNSUPPORTED - The volume does not support the requested file system type.
480 EFI_NO_MEDIA - The device has no media.
482 EFI_DEVICE_ERROR - The device reported an error.
484 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
486 EFI_ACCESS_DENIED - The service denied access to the file.
488 EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.
490 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
493 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
496 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
497 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
500 if (This
== NULL
|| Root
== NULL
) {
501 return EFI_INVALID_PARAMETER
;
503 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
505 Private
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This
);
508 Status
= gBS
->AllocatePool (
510 sizeof (UNIX_EFI_FILE_PRIVATE
),
511 (VOID
**)&PrivateFile
513 if (EFI_ERROR (Status
)) {
517 PrivateFile
->FileName
= NULL
;
518 Status
= gBS
->AllocatePool (
520 AsciiStrSize (Private
->FilePath
),
521 (VOID
**)&PrivateFile
->FileName
523 if (EFI_ERROR (Status
)) {
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_SIMPLE_FILE_SYSTEM_PROTOCOL_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
;
549 *Root
= &PrivateFile
->EfiFile
;
551 PrivateFile
->Dir
= PrivateFile
->UnixThunk
->OpenDir(PrivateFile
->FileName
);
553 if (PrivateFile
->Dir
== NULL
) {
554 Status
= EFI_ACCESS_DENIED
;
557 Status
= EFI_SUCCESS
;
561 if (EFI_ERROR (Status
)) {
563 if (PrivateFile
->FileName
) {
564 gBS
->FreePool (PrivateFile
->FileName
);
567 gBS
->FreePool (PrivateFile
);
573 gBS
->RestoreTPL (OldTpl
);
580 UnixSimpleFileSystemOpen (
581 IN EFI_FILE_PROTOCOL
*This
,
582 OUT EFI_FILE_PROTOCOL
**NewHandle
,
591 Open a file relative to the source file location.
595 This - A pointer to the source file location.
597 NewHandle - Pointer to storage for the new file handle.
599 FileName - Pointer to the file name to be opened.
601 OpenMode - File open mode information.
603 Attributes - File creation attributes.
607 EFI_SUCCESS - The file was opened.
609 EFI_NOT_FOUND - The file could not be found in the volume.
611 EFI_NO_MEDIA - The device has no media.
613 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
615 EFI_DEVICE_ERROR - The device reported an error.
617 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
619 EFI_WRITE_PROTECTED - The volume or file is write protected.
621 EFI_ACCESS_DENIED - The service denied access to the file.
623 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
625 EFI_VOLUME_FULL - There is not enough space left to create the new file.
628 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
629 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
630 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
631 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
633 EFI_FILE_PROTOCOL
*Root
;
634 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
635 UNIX_EFI_FILE_PRIVATE
*NewPrivateFile
;
636 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
645 BOOLEAN TrailingDash
;
650 TrailingDash
= FALSE
;
653 // Check for obvious invalid parameters.
655 if (This
== NULL
|| NewHandle
== NULL
|| FileName
== NULL
) {
656 return EFI_INVALID_PARAMETER
;
660 case EFI_FILE_MODE_CREATE
| EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
661 if (Attributes
&~EFI_FILE_VALID_ATTR
) {
662 return EFI_INVALID_PARAMETER
;
665 if (Attributes
& EFI_FILE_READ_ONLY
) {
666 return EFI_INVALID_PARAMETER
;
672 case EFI_FILE_MODE_READ
:
673 case EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
677 return EFI_INVALID_PARAMETER
;
681 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
682 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
683 NewPrivateFile
= NULL
;
686 // BUGBUG: assume an open of root
687 // if current location, return current data
689 if (StrCmp (FileName
, L
"\\") == 0
690 || (StrCmp (FileName
, L
".") == 0 && PrivateFile
->IsRootDirectory
)) {
692 // BUGBUG: assume an open root
695 Status
= UnixSimpleFileSystemOpenVolume (PrivateFile
->SimpleFileSystem
, &Root
);
696 NewPrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root
);
700 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
702 FileName
[StrLen (FileName
) - 1] = 0;
706 // Attempt to open the file
708 Status
= gBS
->AllocatePool (
710 sizeof (UNIX_EFI_FILE_PRIVATE
),
711 (VOID
**)&NewPrivateFile
714 if (EFI_ERROR (Status
)) {
718 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (UNIX_EFI_FILE_PRIVATE
));
720 NewPrivateFile
->FileName
= NULL
;
721 Status
= gBS
->AllocatePool (
723 AsciiStrSize (PrivateFile
->FileName
) + 1 + StrLen (FileName
) + 1,
724 (VOID
**)&NewPrivateFile
->FileName
727 if (EFI_ERROR (Status
)) {
731 if (*FileName
== L
'\\') {
732 AsciiStrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
736 AsciiStrCpy (NewPrivateFile
->FileName
, PrivateFile
->FileName
);
739 Dst
= NewPrivateFile
->FileName
+ AsciiStrLen(NewPrivateFile
->FileName
);
740 GuardPointer
= NewPrivateFile
->FileName
+ AsciiStrLen(PrivateRoot
->FilePath
);
742 // Convert unicode to ascii and '\' to '/'
754 // Get rid of . and .., except leading . or ..
758 // GuardPointer protect simplefilesystem root path not be destroyed
763 while (!LoopFinish
) {
767 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
768 if (*ParseFileName
== '.' &&
769 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == '/') &&
770 *(ParseFileName
- 1) == '/'
776 CutPrefix (ParseFileName
- 1, 2);
781 if (*ParseFileName
== '.' &&
782 *(ParseFileName
+ 1) == '.' &&
783 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == '/') &&
784 *(ParseFileName
- 1) == '/'
790 while (ParseFileName
!= GuardPointer
) {
793 if (*ParseFileName
== '/') {
799 // cut /.. and its left directory
801 CutPrefix (ParseFileName
, Count
);
808 if (AsciiStrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
809 NewPrivateFile
->IsRootDirectory
= TRUE
;
810 gBS
->FreePool (NewPrivateFile
->FileName
);
811 gBS
->FreePool (NewPrivateFile
);
815 RealFileName
= NewPrivateFile
->FileName
+ AsciiStrLen(NewPrivateFile
->FileName
) - 1;
816 while (RealFileName
> NewPrivateFile
->FileName
&& *RealFileName
!= '/')
819 TempChar
= *(RealFileName
- 1);
820 *(RealFileName
- 1) = 0;
822 *(RealFileName
- 1) = TempChar
;
827 // Test whether file or directory
829 NewPrivateFile
->IsRootDirectory
= FALSE
;
830 NewPrivateFile
->fd
= -1;
831 NewPrivateFile
->Dir
= NULL
;
832 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
833 if (Attributes
& EFI_FILE_DIRECTORY
) {
834 NewPrivateFile
->IsDirectoryPath
= TRUE
;
836 NewPrivateFile
->IsDirectoryPath
= FALSE
;
840 int res
= NewPrivateFile
->UnixThunk
->Stat (NewPrivateFile
->FileName
, &finfo
);
841 if (res
== 0 && S_ISDIR(finfo
.st_mode
))
842 NewPrivateFile
->IsDirectoryPath
= TRUE
;
844 NewPrivateFile
->IsDirectoryPath
= FALSE
;
847 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
848 NewPrivateFile
->IsOpenedByRead
= FALSE
;
850 NewPrivateFile
->IsOpenedByRead
= TRUE
;
853 Status
= EFI_SUCCESS
;
856 // deal with directory
858 if (NewPrivateFile
->IsDirectoryPath
) {
860 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
862 // Create a directory
864 if (NewPrivateFile
->UnixThunk
->MkDir (NewPrivateFile
->FileName
, 0777) != 0) {
867 LastError
= PrivateFile
->UnixThunk
->GetErrno ();
868 if (LastError
!= EEXIST
) {
869 //gBS->FreePool (TempFileName);
870 Status
= EFI_ACCESS_DENIED
;
876 NewPrivateFile
->Dir
= NewPrivateFile
->UnixThunk
->OpenDir
877 (NewPrivateFile
->FileName
);
879 if (NewPrivateFile
->Dir
== NULL
) {
880 if (PrivateFile
->UnixThunk
->GetErrno () == EACCES
) {
881 Status
= EFI_ACCESS_DENIED
;
883 Status
= EFI_NOT_FOUND
;
893 NewPrivateFile
->fd
= NewPrivateFile
->UnixThunk
->Open
894 (NewPrivateFile
->FileName
,
895 ((OpenMode
& EFI_FILE_MODE_CREATE
) ? O_CREAT
: 0)
896 | (NewPrivateFile
->IsOpenedByRead
? O_RDONLY
: O_RDWR
),
898 if (NewPrivateFile
->fd
< 0) {
899 if (PrivateFile
->UnixThunk
->GetErrno () == ENOENT
) {
900 Status
= EFI_NOT_FOUND
;
902 Status
= EFI_ACCESS_DENIED
;
907 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
914 Status
= UnixSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
916 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
917 Status
= EFI_DEVICE_ERROR
;
921 Status
= gBS
->AllocatePool (
927 if (EFI_ERROR (Status
)) {
931 Status
= UnixSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
933 if (EFI_ERROR (Status
)) {
937 Info
->Attribute
= Attributes
;
939 UnixSimpleFileSystemSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
944 FileName
[StrLen (FileName
) + 1] = 0;
945 FileName
[StrLen (FileName
)] = L
'\\';
948 if (EFI_ERROR (Status
)) {
949 if (NewPrivateFile
) {
950 if (NewPrivateFile
->FileName
) {
951 gBS
->FreePool (NewPrivateFile
->FileName
);
954 gBS
->FreePool (NewPrivateFile
);
957 *NewHandle
= &NewPrivateFile
->EfiFile
;
965 UnixSimpleFileSystemClose (
966 IN EFI_FILE_PROTOCOL
*This
972 Close the specified file handle.
976 This - Pointer to a returned opened file handle.
980 EFI_SUCCESS - The file handle has been closed.
983 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
985 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
989 return EFI_INVALID_PARAMETER
;
992 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
994 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
996 if (PrivateFile
->fd
>= 0) {
997 PrivateFile
->UnixThunk
->Close (PrivateFile
->fd
);
999 if (PrivateFile
->Dir
!= NULL
) {
1000 PrivateFile
->UnixThunk
->CloseDir (PrivateFile
->Dir
);
1003 PrivateFile
->fd
= -1;
1004 PrivateFile
->Dir
= NULL
;
1006 if (PrivateFile
->FileName
) {
1007 gBS
->FreePool (PrivateFile
->FileName
);
1010 gBS
->FreePool (PrivateFile
);
1012 gBS
->RestoreTPL (OldTpl
);
1019 UnixSimpleFileSystemDelete (
1020 IN EFI_FILE_PROTOCOL
*This
1024 Routine Description:
1026 Close and delete a file.
1030 This - Pointer to a returned opened file handle.
1034 EFI_SUCCESS - The file handle was closed and deleted.
1036 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1039 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1042 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1046 return EFI_INVALID_PARAMETER
;
1049 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1051 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1053 Status
= EFI_WARN_DELETE_FAILURE
;
1055 if (PrivateFile
->IsDirectoryPath
) {
1056 if (PrivateFile
->Dir
!= NULL
) {
1057 PrivateFile
->UnixThunk
->CloseDir (PrivateFile
->Dir
);
1058 PrivateFile
->Dir
= NULL
;
1061 if (PrivateFile
->UnixThunk
->RmDir (PrivateFile
->FileName
) == 0) {
1062 Status
= EFI_SUCCESS
;
1065 PrivateFile
->UnixThunk
->Close (PrivateFile
->fd
);
1066 PrivateFile
->fd
= -1;
1068 if (!PrivateFile
->IsOpenedByRead
) {
1069 if (!PrivateFile
->UnixThunk
->UnLink (PrivateFile
->FileName
)) {
1070 Status
= EFI_SUCCESS
;
1075 gBS
->FreePool (PrivateFile
->FileName
);
1076 gBS
->FreePool (PrivateFile
);
1078 gBS
->RestoreTPL (OldTpl
);
1084 UnixSystemTimeToEfiTime (
1085 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
,
1086 IN
time_t SystemTime
,
1091 Routine Description:
1093 TODO: Add function description
1097 SystemTime - TODO: add argument description
1098 TimeZone - TODO: add argument description
1099 Time - TODO: add argument description
1103 TODO: add return values
1108 tm
= UnixThunk
->GmTime (&SystemTime
);
1109 Time
->Year
= tm
->tm_year
;
1110 Time
->Month
= tm
->tm_mon
+ 1;
1111 Time
->Day
= tm
->tm_mday
;
1112 Time
->Hour
= tm
->tm_hour
;
1113 Time
->Minute
= tm
->tm_min
;
1114 Time
->Second
= tm
->tm_sec
;
1115 Time
->Nanosecond
= 0;
1117 Time
->TimeZone
= UnixThunk
->GetTimeZone ();
1119 if (UnixThunk
->GetDayLight ()) {
1120 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1125 UnixSimpleFileSystemFileInfo (
1126 UNIX_EFI_FILE_PRIVATE
*PrivateFile
,
1128 IN OUT UINTN
*BufferSize
,
1133 Routine Description:
1135 TODO: Add function description
1139 PrivateFile - TODO: add argument description
1140 BufferSize - TODO: add argument description
1141 Buffer - TODO: add argument description
1145 TODO: add return values
1153 EFI_FILE_INFO
*Info
;
1154 CHAR8
*RealFileName
;
1156 CHAR16
*BufferFileName
;
1159 if (FileName
!= NULL
) {
1160 RealFileName
= FileName
;
1162 else if (PrivateFile
->IsRootDirectory
) {
1165 RealFileName
= PrivateFile
->FileName
;
1168 TempPointer
= RealFileName
;
1169 while (*TempPointer
) {
1170 if (*TempPointer
== '/') {
1171 RealFileName
= TempPointer
+ 1;
1177 Size
= SIZE_OF_EFI_FILE_INFO
;
1178 NameSize
= AsciiStrSize (RealFileName
) * 2;
1179 ResultSize
= Size
+ NameSize
;
1181 if (*BufferSize
< ResultSize
) {
1182 *BufferSize
= ResultSize
;
1183 return EFI_BUFFER_TOO_SMALL
;
1185 if (PrivateFile
->UnixThunk
->Stat (
1186 FileName
== NULL
? PrivateFile
->FileName
: FileName
,
1188 return EFI_DEVICE_ERROR
;
1190 Status
= EFI_SUCCESS
;
1193 ZeroMem (Info
, ResultSize
);
1195 Info
->Size
= ResultSize
;
1196 Info
->FileSize
= buf
.st_size
;
1197 Info
->PhysicalSize
= MultU64x32 (buf
.st_blocks
, buf
.st_blksize
);
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
);
1203 if (!(buf
.st_mode
& S_IWUSR
)) {
1204 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1207 if (S_ISDIR(buf
.st_mode
)) {
1208 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1212 BufferFileName
= (CHAR16
*)((CHAR8
*) Buffer
+ Size
);
1213 while (*RealFileName
)
1214 *BufferFileName
++ = *RealFileName
++;
1215 *BufferFileName
= 0;
1217 *BufferSize
= ResultSize
;
1223 UnixSimpleFileSystemRead (
1224 IN EFI_FILE_PROTOCOL
*This
,
1225 IN OUT UINTN
*BufferSize
,
1230 Routine Description:
1232 Read data from a file.
1236 This - Pointer to a returned open file handle.
1238 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1240 Buffer - Pointer to the first byte of the read Buffer.
1244 EFI_SUCCESS - The data was read.
1246 EFI_NO_MEDIA - The device has no media.
1248 EFI_DEVICE_ERROR - The device reported an error.
1250 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
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.
1256 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1258 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1264 CHAR8
*FullFileName
;
1267 if (This
== NULL
|| BufferSize
== NULL
) {
1268 return EFI_INVALID_PARAMETER
;
1271 if ((*BufferSize
!= 0) && (Buffer
== NULL
)) {
1272 // Buffer can be NULL if *BufferSize is zero
1273 return EFI_INVALID_PARAMETER
;
1276 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1278 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1280 if (!PrivateFile
->IsDirectoryPath
) {
1282 if (PrivateFile
->fd
< 0) {
1283 Status
= EFI_DEVICE_ERROR
;
1287 Res
= PrivateFile
->UnixThunk
->Read (
1292 Status
= EFI_DEVICE_ERROR
;
1296 Status
= EFI_SUCCESS
;
1301 // Read on a directory.
1303 if (PrivateFile
->Dir
== NULL
) {
1304 Status
= EFI_DEVICE_ERROR
;
1308 if (PrivateFile
->Dirent
== NULL
) {
1309 PrivateFile
->Dirent
= PrivateFile
->UnixThunk
->ReadDir (PrivateFile
->Dir
);
1310 if (PrivateFile
->Dirent
== NULL
) {
1312 Status
= EFI_SUCCESS
;
1317 Size
= SIZE_OF_EFI_FILE_INFO
;
1318 NameSize
= AsciiStrLen (PrivateFile
->Dirent
->d_name
) + 1;
1319 ResultSize
= Size
+ 2 * NameSize
;
1321 if (*BufferSize
< ResultSize
) {
1322 *BufferSize
= ResultSize
;
1323 Status
= EFI_BUFFER_TOO_SMALL
;
1326 Status
= EFI_SUCCESS
;
1328 *BufferSize
= ResultSize
;
1330 Status
= gBS
->AllocatePool (
1331 EfiBootServicesData
,
1332 AsciiStrLen(PrivateFile
->FileName
) + 1 + NameSize
,
1333 (VOID
**)&FullFileName
1336 if (EFI_ERROR (Status
)) {
1340 AsciiStrCpy(FullFileName
, PrivateFile
->FileName
);
1341 AsciiStrCat(FullFileName
, "/");
1342 AsciiStrCat(FullFileName
, PrivateFile
->Dirent
->d_name
);
1343 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
,
1347 gBS
->FreePool (FullFileName
);
1349 PrivateFile
->Dirent
= NULL
;
1352 gBS
->RestoreTPL (OldTpl
);
1359 UnixSimpleFileSystemWrite (
1360 IN EFI_FILE_PROTOCOL
*This
,
1361 IN OUT UINTN
*BufferSize
,
1366 Routine Description:
1368 Write data to a file.
1372 This - Pointer to an opened file handle.
1374 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1375 of data written to the file.
1377 Buffer - Pointer to the first by of data in the buffer to write to the file.
1381 EFI_SUCCESS - The data was written to the file.
1383 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1385 EFI_NO_MEDIA - The device has no media.
1387 EFI_DEVICE_ERROR - The device reported an error.
1389 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1391 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1393 EFI_ACCESS_DENIED - The file was opened read-only.
1395 EFI_VOLUME_FULL - The volume is full.
1398 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1400 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1405 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1406 return EFI_INVALID_PARAMETER
;
1409 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1411 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1413 if (PrivateFile
->fd
< 0) {
1414 return EFI_DEVICE_ERROR
;
1417 if (PrivateFile
->IsDirectoryPath
) {
1418 return EFI_UNSUPPORTED
;
1421 if (PrivateFile
->IsOpenedByRead
) {
1422 return EFI_ACCESS_DENIED
;
1425 Res
= PrivateFile
->UnixThunk
->Write (
1429 if (Res
== (UINTN
)-1) {
1430 Status
= EFI_DEVICE_ERROR
;
1434 Status
= EFI_SUCCESS
;
1437 gBS
->RestoreTPL (OldTpl
);
1441 // bugbug: need to access unix error reporting
1447 UnixSimpleFileSystemSetPosition (
1448 IN EFI_FILE_PROTOCOL
*This
,
1453 Routine Description:
1455 Set a file's current position.
1459 This - Pointer to an opened file handle.
1461 Position - The byte position from the start of the file to set.
1465 EFI_SUCCESS - The file position has been changed.
1467 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1470 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1473 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1478 return EFI_INVALID_PARAMETER
;
1481 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1483 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1485 if (PrivateFile
->IsDirectoryPath
) {
1486 if (Position
!= 0) {
1487 Status
= EFI_UNSUPPORTED
;
1491 if (PrivateFile
->Dir
== NULL
) {
1492 Status
= EFI_DEVICE_ERROR
;
1495 PrivateFile
->UnixThunk
->RewindDir (PrivateFile
->Dir
);
1496 Status
= EFI_SUCCESS
;
1499 if (Position
== (UINT64
) -1) {
1500 Pos
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, 0, SEEK_END
);
1502 Pos
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, Position
, SEEK_SET
);
1504 Status
= (Pos
== (UINT64
) -1) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1508 gBS
->RestoreTPL (OldTpl
);
1514 UnixSimpleFileSystemGetPosition (
1515 IN EFI_FILE_PROTOCOL
*This
,
1516 OUT UINT64
*Position
1520 Routine Description:
1522 Get a file's current position.
1526 This - Pointer to an opened file handle.
1528 Position - Pointer to storage for the current position.
1532 EFI_SUCCESS - The file position has been reported.
1534 EFI_UNSUPPORTED - Not valid for directories.
1537 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1540 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1543 if (This
== NULL
|| Position
== NULL
) {
1544 return EFI_INVALID_PARAMETER
;
1547 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1549 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1551 if (PrivateFile
->IsDirectoryPath
) {
1552 Status
= EFI_UNSUPPORTED
;
1554 *Position
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, 0, SEEK_CUR
);
1555 Status
= (*Position
== (UINT64
) -1) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1558 gBS
->RestoreTPL (OldTpl
);
1564 UnixSimpleFileSystemGetInfo (
1565 IN EFI_FILE_PROTOCOL
*This
,
1566 IN EFI_GUID
*InformationType
,
1567 IN OUT UINTN
*BufferSize
,
1572 Routine Description:
1574 Return information about a file or volume.
1578 This - Pointer to an opened file handle.
1580 InformationType - GUID describing the type of information to be returned.
1582 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
1585 Buffer - Pointer to the first byte of the information buffer.
1589 EFI_SUCCESS - The requested information has been written into the buffer.
1591 EFI_UNSUPPORTED - The InformationType is not known.
1593 EFI_NO_MEDIA - The device has no media.
1595 EFI_DEVICE_ERROR - The device reported an error.
1597 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1599 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
1600 been updated with the size needed to complete the requested operation.
1603 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1606 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1607 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
1609 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1613 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
1614 return EFI_INVALID_PARAMETER
;
1617 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1619 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1620 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1622 Status
= EFI_UNSUPPORTED
;
1624 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1625 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, BufferSize
, Buffer
);
1626 } else if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1627 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1628 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1629 Status
= EFI_BUFFER_TOO_SMALL
;
1633 UnixStatus
= PrivateFile
->UnixThunk
->StatFs (PrivateFile
->FileName
, &buf
);
1634 if (UnixStatus
< 0) {
1635 Status
= EFI_DEVICE_ERROR
;
1639 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
1640 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1641 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
1646 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (buf
.f_blocks
, buf
.f_bsize
);
1647 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (buf
.f_bavail
, buf
.f_bsize
);
1648 FileSystemInfoBuffer
->BlockSize
= buf
.f_bsize
;
1651 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
1652 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1653 Status
= EFI_SUCCESS
;
1654 } else if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1655 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1656 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1657 Status
= EFI_BUFFER_TOO_SMALL
;
1661 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
1662 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1663 Status
= EFI_SUCCESS
;
1667 gBS
->RestoreTPL (OldTpl
);
1673 UnixSimpleFileSystemSetInfo (
1674 IN EFI_FILE_PROTOCOL
*This
,
1675 IN EFI_GUID
*InformationType
,
1676 IN UINTN BufferSize
,
1681 Routine Description:
1683 Set information about a file or volume.
1687 This - Pointer to an opened file handle.
1689 InformationType - GUID identifying the type of information to set.
1691 BufferSize - Number of bytes of data in the information buffer.
1693 Buffer - Pointer to the first byte of data in the information buffer.
1697 EFI_SUCCESS - The file or volume information has been updated.
1699 EFI_UNSUPPORTED - The information identifier is not recognised.
1701 EFI_NO_MEDIA - The device has no media.
1703 EFI_DEVICE_ERROR - The device reported an error.
1705 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1707 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1709 EFI_ACCESS_DENIED - The file was opened read-only.
1711 EFI_VOLUME_FULL - The volume is full.
1713 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
1716 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1717 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1719 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1720 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1721 EFI_FILE_INFO
*OldFileInfo
;
1722 EFI_FILE_INFO
*NewFileInfo
;
1731 BOOLEAN AttrChangeFlag
;
1732 BOOLEAN NameChangeFlag
;
1733 BOOLEAN SizeChangeFlag
;
1734 BOOLEAN TimeChangeFlag
;
1735 struct tm NewLastAccessSystemTime
;
1736 struct tm NewLastWriteSystemTime
;
1737 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
1738 CHAR8
*AsciiFilePtr
;
1739 CHAR16
*UnicodeFilePtr
;
1743 // Check for invalid parameters.
1745 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
1746 return EFI_INVALID_PARAMETER
;
1749 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1752 // Initialise locals.
1754 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1755 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1757 Status
= EFI_UNSUPPORTED
;
1758 OldFileInfo
= NewFileInfo
= NULL
;
1759 OldFileName
= NewFileName
= NULL
;
1760 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
1763 // Set file system information.
1765 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1766 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1767 Status
= EFI_BAD_BUFFER_SIZE
;
1771 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
1773 gBS
->FreePool (PrivateRoot
->VolumeLabel
);
1775 PrivateRoot
->VolumeLabel
= NULL
;
1776 Status
= gBS
->AllocatePool (
1777 EfiBootServicesData
,
1778 StrSize (NewFileSystemInfo
->VolumeLabel
),
1779 (VOID
**)&PrivateRoot
->VolumeLabel
1782 if (EFI_ERROR (Status
)) {
1786 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
1788 Status
= EFI_SUCCESS
;
1793 // Set volume label information.
1795 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1796 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1797 Status
= EFI_BAD_BUFFER_SIZE
;
1801 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
1803 Status
= EFI_SUCCESS
;
1807 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1808 Status
= EFI_UNSUPPORTED
;
1812 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
1813 Status
= EFI_BAD_BUFFER_SIZE
;
1818 // Set file/directory information.
1822 // Check for invalid set file information parameters.
1824 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
1826 if ((NewFileInfo
->Size
<= SIZE_OF_EFI_FILE_INFO
) ||
1827 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
1828 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
1830 Status
= EFI_INVALID_PARAMETER
;
1835 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
1836 // that would have an additional parameter that would be the size
1837 // of the string array just in case there are no NULL characters in
1838 // the string array.
1841 // Get current file information so we can determine what kind
1842 // of change request this is.
1845 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, &OldInfoSize
, NULL
);
1847 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1848 Status
= EFI_DEVICE_ERROR
;
1852 Status
= gBS
->AllocatePool (EfiBootServicesData
, OldInfoSize
,
1853 (VOID
**)&OldFileInfo
);
1855 if (EFI_ERROR (Status
)) {
1859 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, &OldInfoSize
, OldFileInfo
);
1861 if (EFI_ERROR (Status
)) {
1865 Status
= gBS
->AllocatePool (
1866 EfiBootServicesData
,
1867 AsciiStrSize (PrivateFile
->FileName
),
1868 (VOID
**)&OldFileName
1871 if (EFI_ERROR (Status
)) {
1875 AsciiStrCpy (OldFileName
, PrivateFile
->FileName
);
1878 // Make full pathname from new filename and rootpath.
1880 if (NewFileInfo
->FileName
[0] == '\\') {
1881 Status
= gBS
->AllocatePool (
1882 EfiBootServicesData
,
1883 AsciiStrLen (PrivateRoot
->FilePath
) + 1 + StrLen (NewFileInfo
->FileName
) + 1,
1884 (VOID
**)&NewFileName
1887 if (EFI_ERROR (Status
)) {
1891 AsciiStrCpy (NewFileName
, PrivateRoot
->FilePath
);
1892 AsciiFilePtr
= NewFileName
+ AsciiStrLen(NewFileName
);
1893 UnicodeFilePtr
= NewFileInfo
->FileName
+ 1;
1894 *AsciiFilePtr
++ ='/';
1896 Status
= gBS
->AllocatePool (
1897 EfiBootServicesData
,
1898 AsciiStrLen (PrivateFile
->FileName
) + 2 + StrLen (NewFileInfo
->FileName
) + 1,
1899 (VOID
**)&NewFileName
1902 if (EFI_ERROR (Status
)) {
1906 AsciiStrCpy (NewFileName
, PrivateRoot
->FilePath
);
1907 AsciiFilePtr
= NewFileName
+ AsciiStrLen(NewFileName
);
1908 if ((AsciiFilePtr
[-1] != '/') && (NewFileInfo
->FileName
[0] != '/')) {
1909 // make sure there is a / between Root FilePath and NewFileInfo Filename
1910 AsciiFilePtr
[0] = '/';
1911 AsciiFilePtr
[1] = '\0';
1914 UnicodeFilePtr
= NewFileInfo
->FileName
;
1916 // Convert to ascii.
1917 while (*UnicodeFilePtr
) {
1918 *AsciiFilePtr
++ = *UnicodeFilePtr
++;
1924 // Is there an attribute change request?
1926 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
1927 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
1928 Status
= EFI_INVALID_PARAMETER
;
1932 AttrChangeFlag
= TRUE
;
1936 // Is there a name change request?
1937 // bugbug: - Need EfiStrCaseCmp()
1939 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
1940 NameChangeFlag
= TRUE
;
1944 // Is there a size change request?
1946 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
1947 SizeChangeFlag
= TRUE
;
1951 // Is there a time stamp change request?
1953 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
1954 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
1956 TimeChangeFlag
= TRUE
;
1957 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
1958 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
1960 TimeChangeFlag
= TRUE
;
1961 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
1962 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
1964 TimeChangeFlag
= TRUE
;
1968 // All done if there are no change requests being made.
1970 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
1971 Status
= EFI_SUCCESS
;
1976 // Set file or directory information.
1978 if (PrivateFile
->UnixThunk
->Stat (OldFileName
, &OldAttr
) != 0) {
1979 Status
= EFI_DEVICE_ERROR
;
1986 if (NameChangeFlag
) {
1988 // Close the handles first
1990 if (PrivateFile
->IsOpenedByRead
) {
1991 Status
= EFI_ACCESS_DENIED
;
1995 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
1998 if (*CharPointer
!= 0) {
1999 Status
= EFI_ACCESS_DENIED
;
2003 UnixStatus
= PrivateFile
->UnixThunk
->Rename (OldFileName
, NewFileName
);
2005 if (UnixStatus
== 0) {
2009 gBS
->FreePool (PrivateFile
->FileName
);
2011 Status
= gBS
->AllocatePool (
2012 EfiBootServicesData
,
2013 AsciiStrSize (NewFileName
),
2014 (VOID
**)&PrivateFile
->FileName
2017 if (EFI_ERROR (Status
)) {
2021 AsciiStrCpy (PrivateFile
->FileName
, NewFileName
);
2023 Status
= EFI_DEVICE_ERROR
;
2031 if (SizeChangeFlag
) {
2032 if (PrivateFile
->IsDirectoryPath
) {
2033 Status
= EFI_UNSUPPORTED
;
2037 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2038 Status
= EFI_ACCESS_DENIED
;
2042 if (PrivateFile
->UnixThunk
->FTruncate (PrivateFile
->fd
, NewFileInfo
->FileSize
) != 0) {
2043 Status
= EFI_DEVICE_ERROR
;
2052 if (TimeChangeFlag
) {
2053 struct utimbuf utime
;
2055 NewLastAccessSystemTime
.tm_year
= NewFileInfo
->LastAccessTime
.Year
;
2056 NewLastAccessSystemTime
.tm_mon
= NewFileInfo
->LastAccessTime
.Month
;
2057 NewLastAccessSystemTime
.tm_mday
= NewFileInfo
->LastAccessTime
.Day
;
2058 NewLastAccessSystemTime
.tm_hour
= NewFileInfo
->LastAccessTime
.Hour
;
2059 NewLastAccessSystemTime
.tm_min
= NewFileInfo
->LastAccessTime
.Minute
;
2060 NewLastAccessSystemTime
.tm_sec
= NewFileInfo
->LastAccessTime
.Second
;
2061 NewLastAccessSystemTime
.tm_isdst
= 0;
2063 utime
.actime
= PrivateFile
->UnixThunk
->MkTime (&NewLastAccessSystemTime
);
2065 NewLastWriteSystemTime
.tm_year
= NewFileInfo
->ModificationTime
.Year
;
2066 NewLastWriteSystemTime
.tm_mon
= NewFileInfo
->ModificationTime
.Month
;
2067 NewLastWriteSystemTime
.tm_mday
= NewFileInfo
->ModificationTime
.Day
;
2068 NewLastWriteSystemTime
.tm_hour
= NewFileInfo
->ModificationTime
.Hour
;
2069 NewLastWriteSystemTime
.tm_min
= NewFileInfo
->ModificationTime
.Minute
;
2070 NewLastWriteSystemTime
.tm_sec
= NewFileInfo
->ModificationTime
.Second
;
2071 NewLastWriteSystemTime
.tm_isdst
= 0;
2073 utime
.modtime
= PrivateFile
->UnixThunk
->MkTime (&NewLastWriteSystemTime
);
2075 if (utime
.actime
== (time_t)-1 || utime
.modtime
== (time_t)-1) {
2079 if (PrivateFile
->UnixThunk
->UTime (PrivateFile
->FileName
, &utime
) == -1) {
2085 // No matter about AttrChangeFlag, Attribute must be set.
2086 // Because operation before may cause attribute change.
2088 NewAttr
= OldAttr
.st_mode
;
2090 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2091 NewAttr
&= ~(S_IRUSR
| S_IRGRP
| S_IROTH
);
2096 UnixStatus
= PrivateFile
->UnixThunk
->Chmod (NewFileName
, NewAttr
);
2097 if (UnixStatus
!= 0) {
2098 Status
= EFI_DEVICE_ERROR
;
2102 if (OldFileInfo
!= NULL
) {
2103 gBS
->FreePool (OldFileInfo
);
2106 if (OldFileName
!= NULL
) {
2107 gBS
->FreePool (OldFileName
);
2110 if (NewFileName
!= NULL
) {
2111 gBS
->FreePool (NewFileName
);
2114 gBS
->RestoreTPL (OldTpl
);
2121 UnixSimpleFileSystemFlush (
2122 IN EFI_FILE_PROTOCOL
*This
2126 Routine Description:
2128 Flush all modified data to the media.
2132 This - Pointer to an opened file handle.
2136 EFI_SUCCESS - The data has been flushed.
2138 EFI_NO_MEDIA - The device has no media.
2140 EFI_DEVICE_ERROR - The device reported an error.
2142 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2144 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2146 EFI_ACCESS_DENIED - The file was opened read-only.
2148 EFI_VOLUME_FULL - The volume is full.
2151 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2153 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
2158 return EFI_INVALID_PARAMETER
;
2161 Status
= EFI_SUCCESS
;
2162 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2164 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2167 if (PrivateFile
->IsDirectoryPath
) {
2171 if (PrivateFile
->IsOpenedByRead
) {
2172 Status
= EFI_ACCESS_DENIED
;
2176 if (PrivateFile
->fd
< 0) {
2177 Status
= EFI_DEVICE_ERROR
;
2181 PrivateFile
->UnixThunk
->FSync (PrivateFile
->fd
) == 0 ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2184 gBS
->RestoreTPL (OldTpl
);
2189 // bugbug: - Use Unix error reporting.