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