1 /*++ @file
2   Produce Simple File System abstractions for directories on your PC using Posix APIs.
3   The configuration of what devices to mount or emulate comes from UNIX
4   environment variables. The variables must be visible to the Microsoft*
5   Developer Studio for them to work.
6 
7 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
8 Portions copyright (c) 2011, Apple Inc. All rights reserved.
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution.  The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13 
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 
17 **/
18 
19 #include "EmuSimpleFileSystem.h"
20 
21 
22 
23 
24 /**
25   Opens a new file relative to the source file's location.
26 
27   @param  This       The protocol instance pointer.
28   @param  NewHandle  Returns File Handle for FileName.
29   @param  FileName   Null terminated string. "\", ".", and ".." are supported.
30   @param  OpenMode   Open mode for file.
31   @param  Attributes Only used for EFI_FILE_MODE_CREATE.
32 
33   @retval EFI_SUCCESS          The device was opened.
34   @retval EFI_NOT_FOUND        The specified file could not be found on the device.
35   @retval EFI_NO_MEDIA         The device has no media.
36   @retval EFI_MEDIA_CHANGED    The media has changed.
37   @retval EFI_DEVICE_ERROR     The device reported an error.
38   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
39   @retval EFI_ACCESS_DENIED    The service denied access to the file.
40   @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
41   @retval EFI_VOLUME_FULL      The volume is full.
42 
43 **/
44 EFI_STATUS
45 EFIAPI
EmuSimpleFileSystemOpen(IN EFI_FILE_PROTOCOL * This,OUT EFI_FILE_PROTOCOL ** NewHandle,IN CHAR16 * FileName,IN UINT64 OpenMode,IN UINT64 Attributes)46 EmuSimpleFileSystemOpen (
47   IN  EFI_FILE_PROTOCOL   *This,
48   OUT EFI_FILE_PROTOCOL   **NewHandle,
49   IN  CHAR16              *FileName,
50   IN  UINT64              OpenMode,
51   IN  UINT64              Attributes
52   )
53 {
54   EMU_EFI_FILE_PRIVATE              *PrivateFile;
55 
56   //
57   // Check for obvious invalid parameters.
58   //
59   if (This == NULL || NewHandle == NULL || FileName == NULL) {
60     return EFI_INVALID_PARAMETER;
61   }
62 
63   switch (OpenMode) {
64   case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
65     if (Attributes &~EFI_FILE_VALID_ATTR) {
66       return EFI_INVALID_PARAMETER;
67     }
68 
69     if (Attributes & EFI_FILE_READ_ONLY) {
70       return EFI_INVALID_PARAMETER;
71     }
72 
73   //
74   // fall through
75   //
76   case EFI_FILE_MODE_READ:
77   case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
78     break;
79 
80   default:
81     return EFI_INVALID_PARAMETER;
82   }
83 
84   PrivateFile     = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
85 
86   return PrivateFile->Io->Open (PrivateFile->Io, NewHandle, FileName, OpenMode, Attributes);
87 }
88 
89 
90 
91 /**
92   Close the file handle
93 
94   @param  This          Protocol instance pointer.
95 
96   @retval EFI_SUCCESS   The file was closed.
97 
98 **/
99 EFI_STATUS
100 EFIAPI
EmuSimpleFileSystemClose(IN EFI_FILE_PROTOCOL * This)101 EmuSimpleFileSystemClose (
102   IN EFI_FILE_PROTOCOL  *This
103   )
104 {
105   EFI_STATUS              Status;
106   EMU_EFI_FILE_PRIVATE    *PrivateFile;
107   EFI_TPL                 OldTpl;
108 
109   if (This == NULL) {
110     return EFI_INVALID_PARAMETER;
111   }
112 
113   PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
114 
115   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
116 
117   Status = PrivateFile->Io->Close (PrivateFile->Io);
118   if (!EFI_ERROR (Status)) {
119     gBS->FreePool (PrivateFile);
120   }
121 
122   gBS->RestoreTPL (OldTpl);
123 
124   return Status;
125 }
126 
127 
128 /**
129   Close and delete the file handle.
130 
131   @param  This                     Protocol instance pointer.
132 
133   @retval EFI_SUCCESS              The file was closed and deleted.
134   @retval EFI_WARN_DELETE_FAILURE  The handle was closed but the file was not deleted.
135 
136 **/
137 EFI_STATUS
138 EFIAPI
EmuSimpleFileSystemDelete(IN EFI_FILE_PROTOCOL * This)139 EmuSimpleFileSystemDelete (
140   IN EFI_FILE_PROTOCOL  *This
141   )
142 {
143   EFI_STATUS              Status;
144   EMU_EFI_FILE_PRIVATE    *PrivateFile;
145   EFI_TPL                 OldTpl;
146 
147   if (This == NULL) {
148     return EFI_INVALID_PARAMETER;
149   }
150 
151   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
152 
153   PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
154 
155   Status = PrivateFile->Io->Delete (PrivateFile->Io);
156   if (!EFI_ERROR (Status)) {
157     gBS->FreePool (PrivateFile);
158   }
159 
160   gBS->RestoreTPL (OldTpl);
161 
162   return Status;
163 }
164 
165 
166 /**
167   Read data from the file.
168 
169   @param  This       Protocol instance pointer.
170   @param  BufferSize On input size of buffer, on output amount of data in buffer.
171   @param  Buffer     The buffer in which data is read.
172 
173   @retval EFI_SUCCESS          Data was read.
174   @retval EFI_NO_MEDIA         The device has no media.
175   @retval EFI_DEVICE_ERROR     The device reported an error.
176   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
177   @retval EFI_BUFFER_TO_SMALL  BufferSize is too small. BufferSize contains required size.
178 
179 **/
180 EFI_STATUS
181 EFIAPI
EmuSimpleFileSystemRead(IN EFI_FILE_PROTOCOL * This,IN OUT UINTN * BufferSize,OUT VOID * Buffer)182 EmuSimpleFileSystemRead (
183   IN     EFI_FILE_PROTOCOL  *This,
184   IN OUT UINTN              *BufferSize,
185   OUT    VOID               *Buffer
186   )
187 {
188   EFI_STATUS              Status;
189   EMU_EFI_FILE_PRIVATE    *PrivateFile;
190   EFI_TPL                 OldTpl;
191 
192   if (This == NULL || BufferSize == NULL) {
193     return EFI_INVALID_PARAMETER;
194   }
195 
196   if ((*BufferSize != 0) && (Buffer == NULL)) {
197     // Buffer can be NULL  if *BufferSize is zero
198     return EFI_INVALID_PARAMETER;
199   }
200 
201   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
202 
203   PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
204 
205   Status = PrivateFile->Io->Read (PrivateFile->Io, BufferSize, Buffer);
206 
207   gBS->RestoreTPL (OldTpl);
208   return Status;
209 }
210 
211 
212 /**
213   Write data to a file.
214 
215   @param  This       Protocol instance pointer.
216   @param  BufferSize On input size of buffer, on output amount of data in buffer.
217   @param  Buffer     The buffer in which data to write.
218 
219   @retval EFI_SUCCESS          Data was written.
220   @retval EFI_UNSUPPORTED      Writes to Open directory are not supported.
221   @retval EFI_NO_MEDIA         The device has no media.
222   @retval EFI_DEVICE_ERROR     The device reported an error.
223   @retval EFI_DEVICE_ERROR     An attempt was made to write to a deleted file.
224   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
225   @retval EFI_WRITE_PROTECTED  The device is write protected.
226   @retval EFI_ACCESS_DENIED    The file was open for read only.
227   @retval EFI_VOLUME_FULL      The volume is full.
228 
229 **/
230 EFI_STATUS
231 EFIAPI
EmuSimpleFileSystemWrite(IN EFI_FILE_PROTOCOL * This,IN OUT UINTN * BufferSize,IN VOID * Buffer)232 EmuSimpleFileSystemWrite (
233   IN     EFI_FILE_PROTOCOL  *This,
234   IN OUT UINTN              *BufferSize,
235   IN     VOID               *Buffer
236   )
237 {
238   EFI_STATUS            Status;
239   EMU_EFI_FILE_PRIVATE *PrivateFile;
240   EFI_TPL               OldTpl;
241 
242   if (This == NULL || BufferSize == NULL || Buffer == NULL) {
243     return EFI_INVALID_PARAMETER;
244   }
245 
246   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
247 
248   PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
249 
250   Status = PrivateFile->Io->Write (PrivateFile->Io, BufferSize, Buffer);
251 
252   gBS->RestoreTPL (OldTpl);
253   return Status;
254 }
255 
256 
257 /**
258   Get a file's current position
259 
260   @param  This            Protocol instance pointer.
261   @param  Position        Byte position from the start of the file.
262 
263   @retval EFI_SUCCESS     Position was updated.
264   @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
265 
266 **/
267 EFI_STATUS
268 EFIAPI
EmuSimpleFileSystemGetPosition(IN EFI_FILE_PROTOCOL * This,OUT UINT64 * Position)269 EmuSimpleFileSystemGetPosition (
270   IN  EFI_FILE_PROTOCOL   *This,
271   OUT UINT64              *Position
272   )
273 {
274   EFI_STATUS            Status;
275   EMU_EFI_FILE_PRIVATE *PrivateFile;
276   EFI_TPL               OldTpl;
277 
278   if (This == NULL || Position == NULL) {
279     return EFI_INVALID_PARAMETER;
280   }
281 
282   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
283 
284   PrivateFile   = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
285 
286   Status = PrivateFile->Io->GetPosition (PrivateFile->Io, Position);
287 
288   gBS->RestoreTPL (OldTpl);
289   return Status;
290 }
291 
292 
293 
294 /**
295   Set file's current position
296 
297   @param  This            Protocol instance pointer.
298   @param  Position        Byte position from the start of the file.
299 
300   @retval EFI_SUCCESS     Position was updated.
301   @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
302 
303 **/
304 EFI_STATUS
305 EFIAPI
EmuSimpleFileSystemSetPosition(IN EFI_FILE_PROTOCOL * This,IN UINT64 Position)306 EmuSimpleFileSystemSetPosition (
307   IN EFI_FILE_PROTOCOL  *This,
308   IN UINT64             Position
309   )
310 {
311   EFI_STATUS              Status;
312   EMU_EFI_FILE_PRIVATE    *PrivateFile;
313   EFI_TPL                 OldTpl;
314 
315   if (This == NULL) {
316     return EFI_INVALID_PARAMETER;
317   }
318 
319   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
320 
321   PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
322 
323   Status = PrivateFile->Io->SetPosition (PrivateFile->Io, Position);
324 
325   gBS->RestoreTPL (OldTpl);
326   return Status;
327 }
328 
329 
330 /**
331   Get information about a file.
332 
333   @param  This            Protocol instance pointer.
334   @param  InformationType Type of information to return in Buffer.
335   @param  BufferSize      On input size of buffer, on output amount of data in buffer.
336   @param  Buffer          The buffer to return data.
337 
338   @retval EFI_SUCCESS          Data was returned.
339   @retval EFI_UNSUPPORTED      InformationType is not supported.
340   @retval EFI_NO_MEDIA         The device has no media.
341   @retval EFI_DEVICE_ERROR     The device reported an error.
342   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
343   @retval EFI_WRITE_PROTECTED  The device is write protected.
344   @retval EFI_ACCESS_DENIED    The file was open for read only.
345   @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
346 
347 **/
348 EFI_STATUS
349 EFIAPI
EmuSimpleFileSystemGetInfo(IN EFI_FILE_PROTOCOL * This,IN EFI_GUID * InformationType,IN OUT UINTN * BufferSize,OUT VOID * Buffer)350 EmuSimpleFileSystemGetInfo (
351   IN     EFI_FILE_PROTOCOL  *This,
352   IN     EFI_GUID           *InformationType,
353   IN OUT UINTN              *BufferSize,
354   OUT    VOID               *Buffer
355   )
356 {
357   EFI_STATUS                        Status;
358   EMU_EFI_FILE_PRIVATE              *PrivateFile;
359   EFI_TPL                           OldTpl;
360 
361   if (This == NULL || InformationType == NULL || BufferSize == NULL) {
362     return EFI_INVALID_PARAMETER;
363   }
364 
365   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
366 
367   PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
368 
369   Status = PrivateFile->Io->GetInfo (PrivateFile->Io, InformationType, BufferSize, Buffer);
370 
371   gBS->RestoreTPL (OldTpl);
372   return Status;
373 }
374 
375 
376 /**
377   Set information about a file
378 
379   @param  File            Protocol instance pointer.
380   @param  InformationType Type of information in Buffer.
381   @param  BufferSize      Size of buffer.
382   @param  Buffer          The data to write.
383 
384   @retval EFI_SUCCESS          Data was set.
385   @retval EFI_UNSUPPORTED      InformationType is not supported.
386   @retval EFI_NO_MEDIA         The device has no media.
387   @retval EFI_DEVICE_ERROR     The device reported an error.
388   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
389   @retval EFI_WRITE_PROTECTED  The device is write protected.
390   @retval EFI_ACCESS_DENIED    The file was open for read only.
391 
392 **/
393 EFI_STATUS
394 EFIAPI
EmuSimpleFileSystemSetInfo(IN EFI_FILE_PROTOCOL * This,IN EFI_GUID * InformationType,IN UINTN BufferSize,IN VOID * Buffer)395 EmuSimpleFileSystemSetInfo (
396   IN EFI_FILE_PROTOCOL*This,
397   IN EFI_GUID         *InformationType,
398   IN UINTN            BufferSize,
399   IN VOID             *Buffer
400   )
401 {
402   EFI_STATUS                        Status;
403   EMU_EFI_FILE_PRIVATE              *PrivateFile;
404   EFI_TPL                           OldTpl;
405 
406   //
407   // Check for invalid parameters.
408   //
409   if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {
410     return EFI_INVALID_PARAMETER;
411   }
412 
413   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
414 
415   PrivateFile               = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
416 
417   Status = PrivateFile->Io->SetInfo (PrivateFile->Io, InformationType, BufferSize, Buffer);
418 
419   gBS->RestoreTPL (OldTpl);
420   return Status;
421 }
422 
423 
424 /**
425   Flush data back for the file handle.
426 
427   @param  This Protocol instance pointer.
428 
429   @retval EFI_SUCCESS          Data was flushed.
430   @retval EFI_UNSUPPORTED      Writes to Open directory are not supported.
431   @retval EFI_NO_MEDIA         The device has no media.
432   @retval EFI_DEVICE_ERROR     The device reported an error.
433   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
434   @retval EFI_WRITE_PROTECTED  The device is write protected.
435   @retval EFI_ACCESS_DENIED    The file was open for read only.
436   @retval EFI_VOLUME_FULL      The volume is full.
437 
438 **/
439 EFI_STATUS
440 EFIAPI
EmuSimpleFileSystemFlush(IN EFI_FILE_PROTOCOL * This)441 EmuSimpleFileSystemFlush (
442   IN EFI_FILE_PROTOCOL  *This
443   )
444 {
445   EFI_STATUS                Status;
446   EMU_EFI_FILE_PRIVATE      *PrivateFile;
447   EFI_TPL                   OldTpl;
448 
449   if (This == NULL) {
450     return EFI_INVALID_PARAMETER;
451   }
452 
453   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
454 
455   PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
456 
457   Status = PrivateFile->Io->Flush (PrivateFile->Io);
458 
459   gBS->RestoreTPL (OldTpl);
460   return Status;
461 }
462 
463 
464 
465 /**
466   Open the root directory on a volume.
467 
468   @param  This Protocol instance pointer.
469   @param  Root Returns an Open file handle for the root directory
470 
471   @retval EFI_SUCCESS          The device was opened.
472   @retval EFI_UNSUPPORTED      This volume does not support the file system.
473   @retval EFI_NO_MEDIA         The device has no media.
474   @retval EFI_DEVICE_ERROR     The device reported an error.
475   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
476   @retval EFI_ACCESS_DENIED    The service denied access to the file.
477   @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
478 
479 **/
480 EFI_STATUS
481 EFIAPI
EmuSimpleFileSystemOpenVolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * This,OUT EFI_FILE_PROTOCOL ** Root)482 EmuSimpleFileSystemOpenVolume (
483   IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *This,
484   OUT EFI_FILE_PROTOCOL               **Root
485   )
486 {
487   EFI_STATUS                        Status;
488   EMU_SIMPLE_FILE_SYSTEM_PRIVATE    *Private;
489   EMU_EFI_FILE_PRIVATE              *PrivateFile;
490   EFI_TPL                           OldTpl;
491 
492   Status = EFI_UNSUPPORTED;
493 
494   if (This == NULL || Root == NULL) {
495     return EFI_INVALID_PARAMETER;
496   }
497 
498   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
499 
500   Private = EMU_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);
501 
502   PrivateFile = AllocatePool (sizeof (EMU_EFI_FILE_PRIVATE));
503   if (PrivateFile == NULL) {
504     Status = EFI_OUT_OF_RESOURCES;
505     goto Done;
506   }
507 
508   PrivateFile->Signature            = EMU_EFI_FILE_PRIVATE_SIGNATURE;
509   PrivateFile->IoThunk              = Private->IoThunk;
510   PrivateFile->SimpleFileSystem     = This;
511   PrivateFile->EfiFile.Revision     = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
512   PrivateFile->EfiFile.Open         = EmuSimpleFileSystemOpen;
513   PrivateFile->EfiFile.Close        = EmuSimpleFileSystemClose;
514   PrivateFile->EfiFile.Delete       = EmuSimpleFileSystemDelete;
515   PrivateFile->EfiFile.Read         = EmuSimpleFileSystemRead;
516   PrivateFile->EfiFile.Write        = EmuSimpleFileSystemWrite;
517   PrivateFile->EfiFile.GetPosition  = EmuSimpleFileSystemGetPosition;
518   PrivateFile->EfiFile.SetPosition  = EmuSimpleFileSystemSetPosition;
519   PrivateFile->EfiFile.GetInfo      = EmuSimpleFileSystemGetInfo;
520   PrivateFile->EfiFile.SetInfo      = EmuSimpleFileSystemSetInfo;
521   PrivateFile->EfiFile.Flush        = EmuSimpleFileSystemFlush;
522 
523   *Root = &PrivateFile->EfiFile;
524 
525   Status = Private->Io->OpenVolume (Private->Io, &PrivateFile->Io);
526   if (EFI_ERROR (Status)) {
527     goto Done;
528   }
529 
530   AddUnicodeString2 (
531     "eng",
532     gEmuSimpleFileSystemComponentName.SupportedLanguages,
533     &Private->ControllerNameTable,
534     Private->IoThunk->ConfigString,
535     TRUE
536     );
537 
538   AddUnicodeString2 (
539     "en",
540     gEmuSimpleFileSystemComponentName.SupportedLanguages,
541     &Private->ControllerNameTable,
542     Private->IoThunk->ConfigString,
543     FALSE
544     );
545 
546 
547 Done:
548   if (EFI_ERROR (Status)) {
549     if (PrivateFile) {
550       gBS->FreePool (PrivateFile);
551     }
552 
553     *Root = NULL;
554   }
555 
556   gBS->RestoreTPL (OldTpl);
557 
558   return Status;
559 }
560 
561 /**
562   Tests to see if this driver supports a given controller. If a child device is provided,
563   it further tests to see if this driver supports creating a handle for the specified child device.
564 
565   This function checks to see if the driver specified by This supports the device specified by
566   ControllerHandle. Drivers will typically use the device path attached to
567   ControllerHandle and/or the services from the bus I/O abstraction attached to
568   ControllerHandle to determine if the driver supports ControllerHandle. This function
569   may be called many times during platform initialization. In order to reduce boot times, the tests
570   performed by this function must be very small, and take as little time as possible to execute. This
571   function must not change the state of any hardware devices, and this function must be aware that the
572   device specified by ControllerHandle may already be managed by the same driver or a
573   different driver. This function must match its calls to AllocatePages() with FreePages(),
574   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
575   Because ControllerHandle may have been previously started by the same driver, if a protocol is
576   already in the opened state, then it must not be closed with CloseProtocol(). This is required
577   to guarantee the state of ControllerHandle is not modified by this function.
578 
579   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
580   @param[in]  ControllerHandle     The handle of the controller to test. This handle
581                                    must support a protocol interface that supplies
582                                    an I/O abstraction to the driver.
583   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
584                                    parameter is ignored by device drivers, and is optional for bus
585                                    drivers. For bus drivers, if this parameter is not NULL, then
586                                    the bus driver must determine if the bus controller specified
587                                    by ControllerHandle and the child controller specified
588                                    by RemainingDevicePath are both supported by this
589                                    bus driver.
590 
591   @retval EFI_SUCCESS              The device specified by ControllerHandle and
592                                    RemainingDevicePath is supported by the driver specified by This.
593   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
594                                    RemainingDevicePath is already being managed by the driver
595                                    specified by This.
596   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
597                                    RemainingDevicePath is already being managed by a different
598                                    driver or an application that requires exclusive access.
599                                    Currently not implemented.
600   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
601                                    RemainingDevicePath is not supported by the driver specified by This.
602 **/
603 EFI_STATUS
604 EFIAPI
EmuSimpleFileSystemDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)605 EmuSimpleFileSystemDriverBindingSupported (
606   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
607   IN  EFI_HANDLE                   ControllerHandle,
608   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
609   )
610 {
611   EFI_STATUS              Status;
612   EMU_IO_THUNK_PROTOCOL  *EmuIoThunk;
613 
614   //
615   // Open the IO Abstraction(s) needed to perform the supported test
616   //
617   Status = gBS->OpenProtocol (
618                   ControllerHandle,
619                   &gEmuIoThunkProtocolGuid,
620                   (VOID **)&EmuIoThunk,
621                   This->DriverBindingHandle,
622                   ControllerHandle,
623                   EFI_OPEN_PROTOCOL_BY_DRIVER
624                   );
625   if (EFI_ERROR (Status)) {
626     return Status;
627   }
628 
629   //
630   // Make sure GUID is for a File System handle.
631   //
632   Status = EFI_UNSUPPORTED;
633   if (CompareGuid (EmuIoThunk->Protocol, &gEfiSimpleFileSystemProtocolGuid)) {
634     Status = EFI_SUCCESS;
635   }
636 
637   //
638   // Close the I/O Abstraction(s) used to perform the supported test
639   //
640   gBS->CloseProtocol (
641         ControllerHandle,
642         &gEmuIoThunkProtocolGuid,
643         This->DriverBindingHandle,
644         ControllerHandle
645         );
646 
647   return Status;
648 }
649 
650 
651 
652 /**
653   Starts a device controller or a bus controller.
654 
655   The Start() function is designed to be invoked from the EFI boot service ConnectController().
656   As a result, much of the error checking on the parameters to Start() has been moved into this
657   common boot service. It is legal to call Start() from other locations,
658   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
659   1. ControllerHandle must be a valid EFI_HANDLE.
660   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
661      EFI_DEVICE_PATH_PROTOCOL.
662   3. Prior to calling Start(), the Supported() function for the driver specified by This must
663      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
664 
665   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
666   @param[in]  ControllerHandle     The handle of the controller to start. This handle
667                                    must support a protocol interface that supplies
668                                    an I/O abstraction to the driver.
669   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
670                                    parameter is ignored by device drivers, and is optional for bus
671                                    drivers. For a bus driver, if this parameter is NULL, then handles
672                                    for all the children of Controller are created by this driver.
673                                    If this parameter is not NULL and the first Device Path Node is
674                                    not the End of Device Path Node, then only the handle for the
675                                    child device specified by the first Device Path Node of
676                                    RemainingDevicePath is created by this driver.
677                                    If the first Device Path Node of RemainingDevicePath is
678                                    the End of Device Path Node, no child handle is created by this
679                                    driver.
680 
681   @retval EFI_SUCCESS              The device was started.
682   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
683   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
684   @retval Others                   The driver failded to start the device.
685 
686 **/
687 EFI_STATUS
688 EFIAPI
EmuSimpleFileSystemDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)689 EmuSimpleFileSystemDriverBindingStart (
690   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
691   IN  EFI_HANDLE                    ControllerHandle,
692   IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
693   )
694 {
695   EFI_STATUS                        Status;
696   EMU_IO_THUNK_PROTOCOL             *EmuIoThunk;
697   EMU_SIMPLE_FILE_SYSTEM_PRIVATE    *Private;
698 
699   Private = NULL;
700 
701   //
702   // Open the IO Abstraction(s) needed
703   //
704   Status = gBS->OpenProtocol (
705                   ControllerHandle,
706                   &gEmuIoThunkProtocolGuid,
707                   (VOID **)&EmuIoThunk,
708                   This->DriverBindingHandle,
709                   ControllerHandle,
710                   EFI_OPEN_PROTOCOL_BY_DRIVER
711                   );
712   if (EFI_ERROR (Status)) {
713     return Status;
714   }
715 
716   //
717   // Validate GUID
718   //
719   if (!CompareGuid (EmuIoThunk->Protocol, &gEfiSimpleFileSystemProtocolGuid)) {
720     Status = EFI_UNSUPPORTED;
721     goto Done;
722   }
723 
724   Private = AllocateZeroPool (sizeof (EMU_SIMPLE_FILE_SYSTEM_PRIVATE));
725   if (Private == NULL) {
726     Status = EFI_OUT_OF_RESOURCES;
727     goto Done;
728   }
729 
730   Status = EmuIoThunk->Open (EmuIoThunk);
731   if (EFI_ERROR (Status)) {
732     goto Done;
733   }
734 
735   Private->Signature = EMU_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;
736   Private->IoThunk   = EmuIoThunk;
737   Private->Io        = EmuIoThunk->Interface;
738 
739   Private->SimpleFileSystem.Revision    = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
740   Private->SimpleFileSystem.OpenVolume  = EmuSimpleFileSystemOpenVolume;
741 
742   Private->ControllerNameTable = NULL;
743 
744   AddUnicodeString2 (
745     "eng",
746     gEmuSimpleFileSystemComponentName.SupportedLanguages,
747     &Private->ControllerNameTable,
748     EmuIoThunk->ConfigString,
749     TRUE
750     );
751 
752   AddUnicodeString2 (
753     "en",
754     gEmuSimpleFileSystemComponentName2.SupportedLanguages,
755     &Private->ControllerNameTable,
756     EmuIoThunk->ConfigString,
757     FALSE
758     );
759 
760   Status = gBS->InstallMultipleProtocolInterfaces (
761                   &ControllerHandle,
762                   &gEfiSimpleFileSystemProtocolGuid,  &Private->SimpleFileSystem,
763                   NULL
764                   );
765 
766 Done:
767   if (EFI_ERROR (Status)) {
768     if (Private != NULL) {
769       if (Private->ControllerNameTable != NULL) {
770         FreeUnicodeStringTable (Private->ControllerNameTable);
771       }
772 
773       gBS->FreePool (Private);
774 
775     }
776 
777     gBS->CloseProtocol (
778           ControllerHandle,
779           &gEmuIoThunkProtocolGuid,
780           This->DriverBindingHandle,
781           ControllerHandle
782           );
783   }
784 
785   return Status;
786 }
787 
788 
789 /**
790   Stops a device controller or a bus controller.
791 
792   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
793   As a result, much of the error checking on the parameters to Stop() has been moved
794   into this common boot service. It is legal to call Stop() from other locations,
795   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
796   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
797      same driver's Start() function.
798   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
799      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
800      Start() function, and the Start() function must have called OpenProtocol() on
801      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
802 
803   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
804   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
805                                 support a bus specific I/O protocol for the driver
806                                 to use to stop the device.
807   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
808   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
809                                 if NumberOfChildren is 0.
810 
811   @retval EFI_SUCCESS           The device was stopped.
812   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
813 
814 **/
815 EFI_STATUS
816 EFIAPI
EmuSimpleFileSystemDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)817 EmuSimpleFileSystemDriverBindingStop (
818   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
819   IN  EFI_HANDLE                   ControllerHandle,
820   IN  UINTN                        NumberOfChildren,
821   IN  EFI_HANDLE                   *ChildHandleBuffer
822   )
823 {
824   EFI_STATUS                        Status;
825   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *SimpleFileSystem;
826   EMU_SIMPLE_FILE_SYSTEM_PRIVATE    *Private;
827 
828   //
829   // Get our context back
830   //
831   Status = gBS->OpenProtocol (
832                   ControllerHandle,
833                   &gEfiSimpleFileSystemProtocolGuid,
834                   (VOID **)&SimpleFileSystem,
835                   This->DriverBindingHandle,
836                   ControllerHandle,
837                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
838                   );
839   if (EFI_ERROR (Status)) {
840     return EFI_UNSUPPORTED;
841   }
842 
843   Private = EMU_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem);
844   Status = Private->IoThunk->Close (Private->IoThunk);
845 
846   //
847   // Uninstall the Simple File System Protocol from ControllerHandle
848   //
849   Status = gBS->UninstallMultipleProtocolInterfaces (
850                   ControllerHandle,
851                   &gEfiSimpleFileSystemProtocolGuid,  &Private->SimpleFileSystem,
852                   NULL
853                   );
854   if (!EFI_ERROR (Status)) {
855     Status = gBS->CloseProtocol (
856                     ControllerHandle,
857                     &gEmuIoThunkProtocolGuid,
858                     This->DriverBindingHandle,
859                     ControllerHandle
860                     );
861   }
862 
863   if (!EFI_ERROR (Status)) {
864     //
865     // Free our instance data
866     //
867     FreeUnicodeStringTable (Private->ControllerNameTable);
868     gBS->FreePool (Private);
869   }
870 
871   return Status;
872 }
873 
874 
875 EFI_DRIVER_BINDING_PROTOCOL gEmuSimpleFileSystemDriverBinding = {
876   EmuSimpleFileSystemDriverBindingSupported,
877   EmuSimpleFileSystemDriverBindingStart,
878   EmuSimpleFileSystemDriverBindingStop,
879   0xa,
880   NULL,
881   NULL
882 };
883 
884 
885 
886 
887 /**
888   The user Entry Point for module EmuSimpleFileSystem. The user code starts with this function.
889 
890   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
891   @param[in] SystemTable    A pointer to the EFI System Table.
892 
893   @retval EFI_SUCCESS       The entry point is executed successfully.
894   @retval other             Some error occurs when executing this entry point.
895 
896 **/
897 EFI_STATUS
898 EFIAPI
InitializeEmuSimpleFileSystem(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)899 InitializeEmuSimpleFileSystem(
900   IN EFI_HANDLE           ImageHandle,
901   IN EFI_SYSTEM_TABLE     *SystemTable
902   )
903 {
904   EFI_STATUS              Status;
905 
906   Status = EfiLibInstallDriverBindingComponentName2 (
907              ImageHandle,
908              SystemTable,
909              &gEmuSimpleFileSystemDriverBinding,
910              ImageHandle,
911              &gEmuSimpleFileSystemComponentName,
912              &gEmuSimpleFileSystemComponentName2
913              );
914   ASSERT_EFI_ERROR (Status);
915 
916   return Status;
917 }
918