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