]> git.proxmox.com Git - mirror_edk2.git/blob - UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.c
81065e73558ce0c8d9c5f73ca3e22aa0a2db56e9
[mirror_edk2.git] / UnixPkg / UnixSimpleFileSystemDxe / UnixSimpleFileSystem.c
1 /*++
2
3 Copyright (c) 2006 - 2009, 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
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_PROTOCOL **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 (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_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;
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 *Root = NULL;
571 }
572
573 gBS->RestoreTPL (OldTpl);
574
575 return Status;
576 }
577
578 EFI_STATUS
579 EFIAPI
580 UnixSimpleFileSystemOpen (
581 IN EFI_FILE_PROTOCOL *This,
582 OUT EFI_FILE_PROTOCOL **NewHandle,
583 IN CHAR16 *FileName,
584 IN UINT64 OpenMode,
585 IN UINT64 Attributes
586 )
587 /*++
588
589 Routine Description:
590
591 Open a file relative to the source file location.
592
593 Arguments:
594
595 This - A pointer to the source file location.
596
597 NewHandle - Pointer to storage for the new file handle.
598
599 FileName - Pointer to the file name to be opened.
600
601 OpenMode - File open mode information.
602
603 Attributes - File creation attributes.
604
605 Returns:
606
607 EFI_SUCCESS - The file was opened.
608
609 EFI_NOT_FOUND - The file could not be found in the volume.
610
611 EFI_NO_MEDIA - The device has no media.
612
613 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
614
615 EFI_DEVICE_ERROR - The device reported an error.
616
617 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
618
619 EFI_WRITE_PROTECTED - The volume or file is write protected.
620
621 EFI_ACCESS_DENIED - The service denied access to the file.
622
623 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
624
625 EFI_VOLUME_FULL - There is not enough space left to create the new file.
626
627 --*/
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
632 {
633 EFI_FILE_PROTOCOL *Root;
634 UNIX_EFI_FILE_PRIVATE *PrivateFile;
635 UNIX_EFI_FILE_PRIVATE *NewPrivateFile;
636 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
637 EFI_STATUS Status;
638 CHAR16 *Src;
639 char *Dst;
640 CHAR8 *RealFileName;
641 char *ParseFileName;
642 char *GuardPointer;
643 CHAR8 TempChar;
644 UINTN Count;
645 BOOLEAN TrailingDash;
646 BOOLEAN LoopFinish;
647 UINTN InfoSize;
648 EFI_FILE_INFO *Info;
649
650 TrailingDash = FALSE;
651
652 //
653 // Check for obvious invalid parameters.
654 //
655 if (This == NULL || NewHandle == NULL || FileName == NULL) {
656 return EFI_INVALID_PARAMETER;
657 }
658
659 switch (OpenMode) {
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;
663 }
664
665 if (Attributes & EFI_FILE_READ_ONLY) {
666 return EFI_INVALID_PARAMETER;
667 }
668
669 //
670 // fall through
671 //
672 case EFI_FILE_MODE_READ:
673 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
674 break;
675
676 default:
677 return EFI_INVALID_PARAMETER;
678 }
679
680
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;
684
685 //
686 // BUGBUG: assume an open of root
687 // if current location, return current data
688 //
689 if (StrCmp (FileName, L"\\") == 0
690 || (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) {
691 //
692 // BUGBUG: assume an open root
693 //
694 OpenRoot:
695 Status = UnixSimpleFileSystemOpenVolume (PrivateFile->SimpleFileSystem, &Root);
696 NewPrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root);
697 goto Done;
698 }
699
700 if (FileName[StrLen (FileName) - 1] == L'\\') {
701 TrailingDash = TRUE;
702 FileName[StrLen (FileName) - 1] = 0;
703 }
704
705 //
706 // Attempt to open the file
707 //
708 Status = gBS->AllocatePool (
709 EfiBootServicesData,
710 sizeof (UNIX_EFI_FILE_PRIVATE),
711 (VOID **)&NewPrivateFile
712 );
713
714 if (EFI_ERROR (Status)) {
715 goto Done;
716 }
717
718 CopyMem (NewPrivateFile, PrivateFile, sizeof (UNIX_EFI_FILE_PRIVATE));
719
720 NewPrivateFile->FileName = NULL;
721 Status = gBS->AllocatePool (
722 EfiBootServicesData,
723 AsciiStrSize (PrivateFile->FileName) + 1 + StrLen (FileName) + 1,
724 (VOID **)&NewPrivateFile->FileName
725 );
726
727 if (EFI_ERROR (Status)) {
728 goto Done;
729 }
730
731 if (*FileName == L'\\') {
732 AsciiStrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);
733 // Skip first '\'.
734 Src = FileName + 1;
735 } else {
736 AsciiStrCpy (NewPrivateFile->FileName, PrivateFile->FileName);
737 Src = FileName;
738 }
739 Dst = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName);
740 GuardPointer = NewPrivateFile->FileName + AsciiStrLen(PrivateRoot->FilePath);
741 *Dst++ = '/';
742 // Convert unicode to ascii and '\' to '/'
743 while (*Src) {
744 if (*Src == '\\')
745 *Dst++ = '/';
746 else
747 *Dst++ = *Src;
748 Src++;
749 }
750 *Dst = 0;
751
752
753 //
754 // Get rid of . and .., except leading . or ..
755 //
756
757 //
758 // GuardPointer protect simplefilesystem root path not be destroyed
759 //
760
761 LoopFinish = FALSE;
762
763 while (!LoopFinish) {
764
765 LoopFinish = TRUE;
766
767 for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {
768 if (*ParseFileName == '.' &&
769 (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == '/') &&
770 *(ParseFileName - 1) == '/'
771 ) {
772
773 //
774 // cut /.
775 //
776 CutPrefix (ParseFileName - 1, 2);
777 LoopFinish = FALSE;
778 break;
779 }
780
781 if (*ParseFileName == '.' &&
782 *(ParseFileName + 1) == '.' &&
783 (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == '/') &&
784 *(ParseFileName - 1) == '/'
785 ) {
786
787 ParseFileName--;
788 Count = 3;
789
790 while (ParseFileName != GuardPointer) {
791 ParseFileName--;
792 Count++;
793 if (*ParseFileName == '/') {
794 break;
795 }
796 }
797
798 //
799 // cut /.. and its left directory
800 //
801 CutPrefix (ParseFileName, Count);
802 LoopFinish = FALSE;
803 break;
804 }
805 }
806 }
807
808 if (AsciiStrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {
809 NewPrivateFile->IsRootDirectory = TRUE;
810 gBS->FreePool (NewPrivateFile->FileName);
811 gBS->FreePool (NewPrivateFile);
812 goto OpenRoot;
813 }
814
815 RealFileName = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName) - 1;
816 while (RealFileName > NewPrivateFile->FileName && *RealFileName != '/')
817 RealFileName--;
818
819 TempChar = *(RealFileName - 1);
820 *(RealFileName - 1) = 0;
821
822 *(RealFileName - 1) = TempChar;
823
824
825
826 //
827 // Test whether file or directory
828 //
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;
835 } else {
836 NewPrivateFile->IsDirectoryPath = FALSE;
837 }
838 } else {
839 STAT_FIX finfo;
840 int res = NewPrivateFile->UnixThunk->Stat (NewPrivateFile->FileName, &finfo);
841 if (res == 0 && S_ISDIR(finfo.st_mode))
842 NewPrivateFile->IsDirectoryPath = TRUE;
843 else
844 NewPrivateFile->IsDirectoryPath = FALSE;
845 }
846
847 if (OpenMode & EFI_FILE_MODE_WRITE) {
848 NewPrivateFile->IsOpenedByRead = FALSE;
849 } else {
850 NewPrivateFile->IsOpenedByRead = TRUE;
851 }
852
853 Status = EFI_SUCCESS;
854
855 //
856 // deal with directory
857 //
858 if (NewPrivateFile->IsDirectoryPath) {
859
860 if ((OpenMode & EFI_FILE_MODE_CREATE)) {
861 //
862 // Create a directory
863 //
864 if (NewPrivateFile->UnixThunk->MkDir (NewPrivateFile->FileName, 0777) != 0) {
865 INTN LastError;
866
867 LastError = PrivateFile->UnixThunk->GetErrno ();
868 if (LastError != EEXIST) {
869 //gBS->FreePool (TempFileName);
870 Status = EFI_ACCESS_DENIED;
871 goto Done;
872 }
873 }
874 }
875
876 NewPrivateFile->Dir = NewPrivateFile->UnixThunk->OpenDir
877 (NewPrivateFile->FileName);
878
879 if (NewPrivateFile->Dir == NULL) {
880 if (PrivateFile->UnixThunk->GetErrno () == EACCES) {
881 Status = EFI_ACCESS_DENIED;
882 } else {
883 Status = EFI_NOT_FOUND;
884 }
885
886 goto Done;
887 }
888
889 } else {
890 //
891 // deal with file
892 //
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),
897 0666);
898 if (NewPrivateFile->fd < 0) {
899 if (PrivateFile->UnixThunk->GetErrno () == ENOENT) {
900 Status = EFI_NOT_FOUND;
901 } else {
902 Status = EFI_ACCESS_DENIED;
903 }
904 }
905 }
906
907 if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {
908 //
909 // Set the attribute
910 //
911 InfoSize = 0;
912 Info = NULL;
913
914 Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
915
916 if (Status != EFI_BUFFER_TOO_SMALL) {
917 Status = EFI_DEVICE_ERROR;
918 goto Done;
919 }
920
921 Status = gBS->AllocatePool (
922 EfiBootServicesData,
923 InfoSize,
924 (VOID **)&Info
925 );
926
927 if (EFI_ERROR (Status)) {
928 goto Done;
929 }
930
931 Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
932
933 if (EFI_ERROR (Status)) {
934 goto Done;
935 }
936
937 Info->Attribute = Attributes;
938
939 UnixSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);
940 }
941
942 Done: ;
943 if (TrailingDash) {
944 FileName[StrLen (FileName) + 1] = 0;
945 FileName[StrLen (FileName)] = L'\\';
946 }
947
948 if (EFI_ERROR (Status)) {
949 if (NewPrivateFile) {
950 if (NewPrivateFile->FileName) {
951 gBS->FreePool (NewPrivateFile->FileName);
952 }
953
954 gBS->FreePool (NewPrivateFile);
955 }
956 } else {
957 *NewHandle = &NewPrivateFile->EfiFile;
958 }
959
960 return Status;
961 }
962
963 EFI_STATUS
964 EFIAPI
965 UnixSimpleFileSystemClose (
966 IN EFI_FILE_PROTOCOL *This
967 )
968 /*++
969
970 Routine Description:
971
972 Close the specified file handle.
973
974 Arguments:
975
976 This - Pointer to a returned opened file handle.
977
978 Returns:
979
980 EFI_SUCCESS - The file handle has been closed.
981
982 --*/
983 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
984 {
985 UNIX_EFI_FILE_PRIVATE *PrivateFile;
986 EFI_TPL OldTpl;
987
988 if (This == NULL) {
989 return EFI_INVALID_PARAMETER;
990 }
991
992 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
993
994 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
995
996 if (PrivateFile->fd >= 0) {
997 PrivateFile->UnixThunk->Close (PrivateFile->fd);
998 }
999 if (PrivateFile->Dir != NULL) {
1000 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);
1001 }
1002
1003 PrivateFile->fd = -1;
1004 PrivateFile->Dir = NULL;
1005
1006 if (PrivateFile->FileName) {
1007 gBS->FreePool (PrivateFile->FileName);
1008 }
1009
1010 gBS->FreePool (PrivateFile);
1011
1012 gBS->RestoreTPL (OldTpl);
1013
1014 return EFI_SUCCESS;
1015 }
1016
1017 EFI_STATUS
1018 EFIAPI
1019 UnixSimpleFileSystemDelete (
1020 IN EFI_FILE_PROTOCOL *This
1021 )
1022 /*++
1023
1024 Routine Description:
1025
1026 Close and delete a file.
1027
1028 Arguments:
1029
1030 This - Pointer to a returned opened file handle.
1031
1032 Returns:
1033
1034 EFI_SUCCESS - The file handle was closed and deleted.
1035
1036 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1037
1038 --*/
1039 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1040 {
1041 EFI_STATUS Status;
1042 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1043 EFI_TPL OldTpl;
1044
1045 if (This == NULL) {
1046 return EFI_INVALID_PARAMETER;
1047 }
1048
1049 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1050
1051 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1052
1053 Status = EFI_WARN_DELETE_FAILURE;
1054
1055 if (PrivateFile->IsDirectoryPath) {
1056 if (PrivateFile->Dir != NULL) {
1057 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);
1058 PrivateFile->Dir = NULL;
1059 }
1060
1061 if (PrivateFile->UnixThunk->RmDir (PrivateFile->FileName) == 0) {
1062 Status = EFI_SUCCESS;
1063 }
1064 } else {
1065 PrivateFile->UnixThunk->Close (PrivateFile->fd);
1066 PrivateFile->fd = -1;
1067
1068 if (!PrivateFile->IsOpenedByRead) {
1069 if (!PrivateFile->UnixThunk->UnLink (PrivateFile->FileName)) {
1070 Status = EFI_SUCCESS;
1071 }
1072 }
1073 }
1074
1075 gBS->FreePool (PrivateFile->FileName);
1076 gBS->FreePool (PrivateFile);
1077
1078 gBS->RestoreTPL (OldTpl);
1079
1080 return Status;
1081 }
1082
1083 VOID
1084 UnixSystemTimeToEfiTime (
1085 EFI_UNIX_THUNK_PROTOCOL *UnixThunk,
1086 IN time_t SystemTime,
1087 OUT EFI_TIME *Time
1088 )
1089 /*++
1090
1091 Routine Description:
1092
1093 TODO: Add function description
1094
1095 Arguments:
1096
1097 SystemTime - TODO: add argument description
1098 TimeZone - TODO: add argument description
1099 Time - TODO: add argument description
1100
1101 Returns:
1102
1103 TODO: add return values
1104
1105 --*/
1106 {
1107 struct tm *tm;
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;
1116
1117 Time->TimeZone = UnixThunk->GetTimeZone ();
1118
1119 if (UnixThunk->GetDayLight ()) {
1120 Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;
1121 }
1122 }
1123
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 STAT_FIX 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_PROTOCOL *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) {
1268 return EFI_INVALID_PARAMETER;
1269 }
1270
1271 if ((*BufferSize != 0) && (Buffer == NULL)) {
1272 // Buffer can be NULL if *BufferSize is zero
1273 return EFI_INVALID_PARAMETER;
1274 }
1275
1276 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1277
1278 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1279
1280 if (!PrivateFile->IsDirectoryPath) {
1281
1282 if (PrivateFile->fd < 0) {
1283 Status = EFI_DEVICE_ERROR;
1284 goto Done;
1285 }
1286
1287 Res = PrivateFile->UnixThunk->Read (
1288 PrivateFile->fd,
1289 Buffer,
1290 *BufferSize);
1291 if (Res < 0) {
1292 Status = EFI_DEVICE_ERROR;
1293 goto Done;
1294 }
1295 *BufferSize = Res;
1296 Status = EFI_SUCCESS;
1297 goto Done;
1298 }
1299
1300 //
1301 // Read on a directory.
1302 //
1303 if (PrivateFile->Dir == NULL) {
1304 Status = EFI_DEVICE_ERROR;
1305 goto Done;
1306 }
1307
1308 if (PrivateFile->Dirent == NULL) {
1309 PrivateFile->Dirent = PrivateFile->UnixThunk->ReadDir (PrivateFile->Dir);
1310 if (PrivateFile->Dirent == NULL) {
1311 *BufferSize = 0;
1312 Status = EFI_SUCCESS;
1313 goto Done;
1314 }
1315 }
1316
1317 Size = SIZE_OF_EFI_FILE_INFO;
1318 NameSize = AsciiStrLen (PrivateFile->Dirent->d_name) + 1;
1319 ResultSize = Size + 2 * NameSize;
1320
1321 if (*BufferSize < ResultSize) {
1322 *BufferSize = ResultSize;
1323 Status = EFI_BUFFER_TOO_SMALL;
1324 goto Done;
1325 }
1326 Status = EFI_SUCCESS;
1327
1328 *BufferSize = ResultSize;
1329
1330 Status = gBS->AllocatePool (
1331 EfiBootServicesData,
1332 AsciiStrLen(PrivateFile->FileName) + 1 + NameSize,
1333 (VOID **)&FullFileName
1334 );
1335
1336 if (EFI_ERROR (Status)) {
1337 goto Done;
1338 }
1339
1340 AsciiStrCpy(FullFileName, PrivateFile->FileName);
1341 AsciiStrCat(FullFileName, "/");
1342 AsciiStrCat(FullFileName, PrivateFile->Dirent->d_name);
1343 Status = UnixSimpleFileSystemFileInfo (PrivateFile,
1344 FullFileName,
1345 BufferSize,
1346 Buffer);
1347 gBS->FreePool (FullFileName);
1348
1349 PrivateFile->Dirent = NULL;
1350
1351 Done:
1352 gBS->RestoreTPL (OldTpl);
1353
1354 return Status;
1355 }
1356
1357 EFI_STATUS
1358 EFIAPI
1359 UnixSimpleFileSystemWrite (
1360 IN EFI_FILE_PROTOCOL *This,
1361 IN OUT UINTN *BufferSize,
1362 IN VOID *Buffer
1363 )
1364 /*++
1365
1366 Routine Description:
1367
1368 Write data to a file.
1369
1370 Arguments:
1371
1372 This - Pointer to an opened file handle.
1373
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.
1376
1377 Buffer - Pointer to the first by of data in the buffer to write to the file.
1378
1379 Returns:
1380
1381 EFI_SUCCESS - The data was written to the file.
1382
1383 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1384
1385 EFI_NO_MEDIA - The device has no media.
1386
1387 EFI_DEVICE_ERROR - The device reported an error.
1388
1389 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1390
1391 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1392
1393 EFI_ACCESS_DENIED - The file was opened read-only.
1394
1395 EFI_VOLUME_FULL - The volume is full.
1396
1397 --*/
1398 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1399 {
1400 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1401 UINTN Res;
1402 EFI_STATUS Status;
1403 EFI_TPL OldTpl;
1404
1405 if (This == NULL || BufferSize == NULL || Buffer == NULL) {
1406 return EFI_INVALID_PARAMETER;
1407 }
1408
1409 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1410
1411 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1412
1413 if (PrivateFile->fd < 0) {
1414 return EFI_DEVICE_ERROR;
1415 }
1416
1417 if (PrivateFile->IsDirectoryPath) {
1418 return EFI_UNSUPPORTED;
1419 }
1420
1421 if (PrivateFile->IsOpenedByRead) {
1422 return EFI_ACCESS_DENIED;
1423 }
1424
1425 Res = PrivateFile->UnixThunk->Write (
1426 PrivateFile->fd,
1427 Buffer,
1428 *BufferSize);
1429 if (Res == (UINTN)-1) {
1430 Status = EFI_DEVICE_ERROR;
1431 goto Done;
1432 }
1433 *BufferSize = Res;
1434 Status = EFI_SUCCESS;
1435
1436 Done:
1437 gBS->RestoreTPL (OldTpl);
1438 return Status;
1439
1440 //
1441 // bugbug: need to access unix error reporting
1442 //
1443 }
1444
1445 EFI_STATUS
1446 EFIAPI
1447 UnixSimpleFileSystemSetPosition (
1448 IN EFI_FILE_PROTOCOL *This,
1449 IN UINT64 Position
1450 )
1451 /*++
1452
1453 Routine Description:
1454
1455 Set a file's current position.
1456
1457 Arguments:
1458
1459 This - Pointer to an opened file handle.
1460
1461 Position - The byte position from the start of the file to set.
1462
1463 Returns:
1464
1465 EFI_SUCCESS - The file position has been changed.
1466
1467 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1468
1469 --*/
1470 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1471 {
1472 EFI_STATUS Status;
1473 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1474 UINT64 Pos;
1475 EFI_TPL OldTpl;
1476
1477 if (This == NULL) {
1478 return EFI_INVALID_PARAMETER;
1479 }
1480
1481 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1482
1483 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1484
1485 if (PrivateFile->IsDirectoryPath) {
1486 if (Position != 0) {
1487 Status = EFI_UNSUPPORTED;
1488 goto Done;
1489 }
1490
1491 if (PrivateFile->Dir == NULL) {
1492 Status = EFI_DEVICE_ERROR;
1493 goto Done;
1494 }
1495 PrivateFile->UnixThunk->RewindDir (PrivateFile->Dir);
1496 Status = EFI_SUCCESS;
1497 goto Done;
1498 } else {
1499 if (Position == (UINT64) -1) {
1500 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_END);
1501 } else {
1502 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, Position, SEEK_SET);
1503 }
1504 Status = (Pos == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
1505 }
1506
1507 Done:
1508 gBS->RestoreTPL (OldTpl);
1509 return Status;
1510 }
1511
1512 EFI_STATUS
1513 EFIAPI
1514 UnixSimpleFileSystemGetPosition (
1515 IN EFI_FILE_PROTOCOL *This,
1516 OUT UINT64 *Position
1517 )
1518 /*++
1519
1520 Routine Description:
1521
1522 Get a file's current position.
1523
1524 Arguments:
1525
1526 This - Pointer to an opened file handle.
1527
1528 Position - Pointer to storage for the current position.
1529
1530 Returns:
1531
1532 EFI_SUCCESS - The file position has been reported.
1533
1534 EFI_UNSUPPORTED - Not valid for directories.
1535
1536 --*/
1537 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1538 {
1539 EFI_STATUS Status;
1540 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1541 EFI_TPL OldTpl;
1542
1543 if (This == NULL || Position == NULL) {
1544 return EFI_INVALID_PARAMETER;
1545 }
1546
1547 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1548
1549 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1550
1551 if (PrivateFile->IsDirectoryPath) {
1552 Status = EFI_UNSUPPORTED;
1553 } else {
1554 *Position = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_CUR);
1555 Status = (*Position == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
1556 }
1557
1558 gBS->RestoreTPL (OldTpl);
1559 return Status;
1560 }
1561
1562 EFI_STATUS
1563 EFIAPI
1564 UnixSimpleFileSystemGetInfo (
1565 IN EFI_FILE_PROTOCOL *This,
1566 IN EFI_GUID *InformationType,
1567 IN OUT UINTN *BufferSize,
1568 OUT VOID *Buffer
1569 )
1570 /*++
1571
1572 Routine Description:
1573
1574 Return information about a file or volume.
1575
1576 Arguments:
1577
1578 This - Pointer to an opened file handle.
1579
1580 InformationType - GUID describing the type of information to be returned.
1581
1582 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
1583 information buffer.
1584
1585 Buffer - Pointer to the first byte of the information buffer.
1586
1587 Returns:
1588
1589 EFI_SUCCESS - The requested information has been written into the buffer.
1590
1591 EFI_UNSUPPORTED - The InformationType is not known.
1592
1593 EFI_NO_MEDIA - The device has no media.
1594
1595 EFI_DEVICE_ERROR - The device reported an error.
1596
1597 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1598
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.
1601
1602 --*/
1603 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1604 {
1605 EFI_STATUS Status;
1606 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1607 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;
1608 INTN UnixStatus;
1609 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
1610 struct statfs buf;
1611 EFI_TPL OldTpl;
1612
1613 if (This == NULL || InformationType == NULL || BufferSize == NULL) {
1614 return EFI_INVALID_PARAMETER;
1615 }
1616
1617 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1618
1619 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1620 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
1621
1622 Status = EFI_UNSUPPORTED;
1623
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;
1630 goto Done;
1631 }
1632
1633 UnixStatus = PrivateFile->UnixThunk->StatFs (PrivateFile->FileName, &buf);
1634 if (UnixStatus < 0) {
1635 Status = EFI_DEVICE_ERROR;
1636 goto Done;
1637 }
1638
1639 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;
1640 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
1641 FileSystemInfoBuffer->ReadOnly = FALSE;
1642
1643 //
1644 // Succeeded
1645 //
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;
1649
1650
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;
1658 goto Done;
1659 }
1660
1661 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);
1662 *BufferSize = StrSize (PrivateRoot->VolumeLabel);
1663 Status = EFI_SUCCESS;
1664 }
1665
1666 Done:
1667 gBS->RestoreTPL (OldTpl);
1668 return Status;
1669 }
1670
1671 EFI_STATUS
1672 EFIAPI
1673 UnixSimpleFileSystemSetInfo (
1674 IN EFI_FILE_PROTOCOL*This,
1675 IN EFI_GUID *InformationType,
1676 IN UINTN BufferSize,
1677 IN VOID *Buffer
1678 )
1679 /*++
1680
1681 Routine Description:
1682
1683 Set information about a file or volume.
1684
1685 Arguments:
1686
1687 This - Pointer to an opened file handle.
1688
1689 InformationType - GUID identifying the type of information to set.
1690
1691 BufferSize - Number of bytes of data in the information buffer.
1692
1693 Buffer - Pointer to the first byte of data in the information buffer.
1694
1695 Returns:
1696
1697 EFI_SUCCESS - The file or volume information has been updated.
1698
1699 EFI_UNSUPPORTED - The information identifier is not recognised.
1700
1701 EFI_NO_MEDIA - The device has no media.
1702
1703 EFI_DEVICE_ERROR - The device reported an error.
1704
1705 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1706
1707 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1708
1709 EFI_ACCESS_DENIED - The file was opened read-only.
1710
1711 EFI_VOLUME_FULL - The volume is full.
1712
1713 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
1714
1715 --*/
1716 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1717 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1718 {
1719 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
1720 UNIX_EFI_FILE_PRIVATE *PrivateFile;
1721 EFI_FILE_INFO *OldFileInfo;
1722 EFI_FILE_INFO *NewFileInfo;
1723 EFI_STATUS Status;
1724 UINTN OldInfoSize;
1725 EFI_TPL OldTpl;
1726 mode_t NewAttr;
1727 STAT_FIX OldAttr;
1728 CHAR8 *OldFileName;
1729 CHAR8 *NewFileName;
1730 CHAR8 *CharPointer;
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;
1740 INTN UnixStatus;
1741
1742 //
1743 // Check for invalid parameters.
1744 //
1745 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {
1746 return EFI_INVALID_PARAMETER;
1747 }
1748
1749 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1750
1751 //
1752 // Initialise locals.
1753 //
1754 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1755 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
1756
1757 Status = EFI_UNSUPPORTED;
1758 OldFileInfo = NewFileInfo = NULL;
1759 OldFileName = NewFileName = NULL;
1760 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;
1761
1762 //
1763 // Set file system information.
1764 //
1765 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
1766 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {
1767 Status = EFI_BAD_BUFFER_SIZE;
1768 goto Done;
1769 }
1770
1771 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;
1772
1773 gBS->FreePool (PrivateRoot->VolumeLabel);
1774
1775 PrivateRoot->VolumeLabel = NULL;
1776 Status = gBS->AllocatePool (
1777 EfiBootServicesData,
1778 StrSize (NewFileSystemInfo->VolumeLabel),
1779 (VOID **)&PrivateRoot->VolumeLabel
1780 );
1781
1782 if (EFI_ERROR (Status)) {
1783 goto Done;
1784 }
1785
1786 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);
1787
1788 Status = EFI_SUCCESS;
1789 goto Done;
1790 }
1791
1792 //
1793 // Set volume label information.
1794 //
1795 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
1796 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
1797 Status = EFI_BAD_BUFFER_SIZE;
1798 goto Done;
1799 }
1800
1801 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);
1802
1803 Status = EFI_SUCCESS;
1804 goto Done;
1805 }
1806
1807 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {
1808 Status = EFI_UNSUPPORTED;
1809 goto Done;
1810 }
1811
1812 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {
1813 Status = EFI_BAD_BUFFER_SIZE;
1814 goto Done;
1815 }
1816
1817 //
1818 // Set file/directory information.
1819 //
1820
1821 //
1822 // Check for invalid set file information parameters.
1823 //
1824 NewFileInfo = (EFI_FILE_INFO *) Buffer;
1825
1826 if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) ||
1827 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||
1828 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)
1829 ) {
1830 Status = EFI_INVALID_PARAMETER;
1831 goto Done;
1832 }
1833
1834 //
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.
1839 //
1840 //
1841 // Get current file information so we can determine what kind
1842 // of change request this is.
1843 //
1844 OldInfoSize = 0;
1845 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, NULL);
1846
1847 if (Status != EFI_BUFFER_TOO_SMALL) {
1848 Status = EFI_DEVICE_ERROR;
1849 goto Done;
1850 }
1851
1852 Status = gBS->AllocatePool (EfiBootServicesData, OldInfoSize,
1853 (VOID **)&OldFileInfo);
1854
1855 if (EFI_ERROR (Status)) {
1856 goto Done;
1857 }
1858
1859 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, OldFileInfo);
1860
1861 if (EFI_ERROR (Status)) {
1862 goto Done;
1863 }
1864
1865 Status = gBS->AllocatePool (
1866 EfiBootServicesData,
1867 AsciiStrSize (PrivateFile->FileName),
1868 (VOID **)&OldFileName
1869 );
1870
1871 if (EFI_ERROR (Status)) {
1872 goto Done;
1873 }
1874
1875 AsciiStrCpy (OldFileName, PrivateFile->FileName);
1876
1877 //
1878 // Make full pathname from new filename and rootpath.
1879 //
1880 if (NewFileInfo->FileName[0] == '\\') {
1881 Status = gBS->AllocatePool (
1882 EfiBootServicesData,
1883 AsciiStrLen (PrivateRoot->FilePath) + 1 + StrLen (NewFileInfo->FileName) + 1,
1884 (VOID **)&NewFileName
1885 );
1886
1887 if (EFI_ERROR (Status)) {
1888 goto Done;
1889 }
1890
1891 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);
1892 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);
1893 UnicodeFilePtr = NewFileInfo->FileName + 1;
1894 *AsciiFilePtr++ ='/';
1895 } else {
1896 Status = gBS->AllocatePool (
1897 EfiBootServicesData,
1898 AsciiStrLen (PrivateFile->FileName) + 2 + StrLen (NewFileInfo->FileName) + 1,
1899 (VOID **)&NewFileName
1900 );
1901
1902 if (EFI_ERROR (Status)) {
1903 goto Done;
1904 }
1905
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';
1912 AsciiFilePtr++;
1913 }
1914 UnicodeFilePtr = NewFileInfo->FileName;
1915 }
1916 // Convert to ascii.
1917 while (*UnicodeFilePtr) {
1918 *AsciiFilePtr++ = *UnicodeFilePtr++;
1919 }
1920 *AsciiFilePtr = 0;
1921
1922
1923 //
1924 // Is there an attribute change request?
1925 //
1926 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {
1927 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
1928 Status = EFI_INVALID_PARAMETER;
1929 goto Done;
1930 }
1931
1932 AttrChangeFlag = TRUE;
1933 }
1934
1935 //
1936 // Is there a name change request?
1937 // bugbug: - Need EfiStrCaseCmp()
1938 //
1939 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {
1940 NameChangeFlag = TRUE;
1941 }
1942
1943 //
1944 // Is there a size change request?
1945 //
1946 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {
1947 SizeChangeFlag = TRUE;
1948 }
1949
1950 //
1951 // Is there a time stamp change request?
1952 //
1953 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&
1954 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))
1955 ) {
1956 TimeChangeFlag = TRUE;
1957 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&
1958 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))
1959 ) {
1960 TimeChangeFlag = TRUE;
1961 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&
1962 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))
1963 ) {
1964 TimeChangeFlag = TRUE;
1965 }
1966
1967 //
1968 // All done if there are no change requests being made.
1969 //
1970 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {
1971 Status = EFI_SUCCESS;
1972 goto Done;
1973 }
1974
1975 //
1976 // Set file or directory information.
1977 //
1978 if (PrivateFile->UnixThunk->Stat (OldFileName, &OldAttr) != 0) {
1979 Status = EFI_DEVICE_ERROR;
1980 goto Done;
1981 }
1982
1983 //
1984 // Name change.
1985 //
1986 if (NameChangeFlag) {
1987 //
1988 // Close the handles first
1989 //
1990 if (PrivateFile->IsOpenedByRead) {
1991 Status = EFI_ACCESS_DENIED;
1992 goto Done;
1993 }
1994
1995 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {
1996 }
1997
1998 if (*CharPointer != 0) {
1999 Status = EFI_ACCESS_DENIED;
2000 goto Done;
2001 }
2002
2003 UnixStatus = PrivateFile->UnixThunk->Rename (OldFileName, NewFileName);
2004
2005 if (UnixStatus == 0) {
2006 //
2007 // modify file name
2008 //
2009 gBS->FreePool (PrivateFile->FileName);
2010
2011 Status = gBS->AllocatePool (
2012 EfiBootServicesData,
2013 AsciiStrSize (NewFileName),
2014 (VOID **)&PrivateFile->FileName
2015 );
2016
2017 if (EFI_ERROR (Status)) {
2018 goto Done;
2019 }
2020
2021 AsciiStrCpy (PrivateFile->FileName, NewFileName);
2022 } else {
2023 Status = EFI_DEVICE_ERROR;
2024 goto Done;
2025 }
2026 }
2027
2028 //
2029 // Size change
2030 //
2031 if (SizeChangeFlag) {
2032 if (PrivateFile->IsDirectoryPath) {
2033 Status = EFI_UNSUPPORTED;
2034 goto Done;
2035 }
2036
2037 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {
2038 Status = EFI_ACCESS_DENIED;
2039 goto Done;
2040 }
2041
2042 if (PrivateFile->UnixThunk->FTruncate (PrivateFile->fd, NewFileInfo->FileSize) != 0) {
2043 Status = EFI_DEVICE_ERROR;
2044 goto Done;
2045 }
2046
2047 }
2048
2049 //
2050 // Time change
2051 //
2052 if (TimeChangeFlag) {
2053 struct utimbuf utime;
2054
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;
2062
2063 utime.actime = PrivateFile->UnixThunk->MkTime (&NewLastAccessSystemTime);
2064
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;
2072
2073 utime.modtime = PrivateFile->UnixThunk->MkTime (&NewLastWriteSystemTime);
2074
2075 if (utime.actime == (time_t)-1 || utime.modtime == (time_t)-1) {
2076 goto Done;
2077 }
2078
2079 if (PrivateFile->UnixThunk->UTime (PrivateFile->FileName, &utime) == -1) {
2080 goto Done;
2081 }
2082 }
2083
2084 //
2085 // No matter about AttrChangeFlag, Attribute must be set.
2086 // Because operation before may cause attribute change.
2087 //
2088 NewAttr = OldAttr.st_mode;
2089
2090 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {
2091 NewAttr &= ~(S_IRUSR | S_IRGRP | S_IROTH);
2092 } else {
2093 NewAttr |= S_IRUSR;
2094 }
2095
2096 UnixStatus = PrivateFile->UnixThunk->Chmod (NewFileName, NewAttr);
2097 if (UnixStatus != 0) {
2098 Status = EFI_DEVICE_ERROR;
2099 }
2100
2101 Done:
2102 if (OldFileInfo != NULL) {
2103 gBS->FreePool (OldFileInfo);
2104 }
2105
2106 if (OldFileName != NULL) {
2107 gBS->FreePool (OldFileName);
2108 }
2109
2110 if (NewFileName != NULL) {
2111 gBS->FreePool (NewFileName);
2112 }
2113
2114 gBS->RestoreTPL (OldTpl);
2115
2116 return Status;
2117 }
2118
2119 EFI_STATUS
2120 EFIAPI
2121 UnixSimpleFileSystemFlush (
2122 IN EFI_FILE_PROTOCOL *This
2123 )
2124 /*++
2125
2126 Routine Description:
2127
2128 Flush all modified data to the media.
2129
2130 Arguments:
2131
2132 This - Pointer to an opened file handle.
2133
2134 Returns:
2135
2136 EFI_SUCCESS - The data has been flushed.
2137
2138 EFI_NO_MEDIA - The device has no media.
2139
2140 EFI_DEVICE_ERROR - The device reported an error.
2141
2142 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2143
2144 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2145
2146 EFI_ACCESS_DENIED - The file was opened read-only.
2147
2148 EFI_VOLUME_FULL - The volume is full.
2149
2150 --*/
2151 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2152 {
2153 UNIX_EFI_FILE_PRIVATE *PrivateFile;
2154 EFI_STATUS Status;
2155 EFI_TPL OldTpl;
2156
2157 if (This == NULL) {
2158 return EFI_INVALID_PARAMETER;
2159 }
2160
2161 Status = EFI_SUCCESS;
2162 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
2163
2164 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
2165
2166
2167 if (PrivateFile->IsDirectoryPath) {
2168 goto Done;
2169 }
2170
2171 if (PrivateFile->IsOpenedByRead) {
2172 Status = EFI_ACCESS_DENIED;
2173 goto Done;
2174 }
2175
2176 if (PrivateFile->fd < 0) {
2177 Status = EFI_DEVICE_ERROR;
2178 goto Done;
2179 }
2180
2181 PrivateFile->UnixThunk->FSync (PrivateFile->fd) == 0 ? EFI_SUCCESS : EFI_DEVICE_ERROR;
2182
2183 Done:
2184 gBS->RestoreTPL (OldTpl);
2185
2186 return Status;
2187
2188 //
2189 // bugbug: - Use Unix error reporting.
2190 //
2191 }
2192
2193