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