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
7Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
8Portions copyright (c) 2011, Apple Inc. All rights reserved.
9This program and the accompanying materials
10are licensed and made available under the terms and conditions of the BSD License
11which accompanies this distribution.  The full text of the license may be found at
12http://opensource.org/licenses/bsd-license.php
13
14THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15WITHOUT 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**/
44EFI_STATUS
45EFIAPI
46EmuSimpleFileSystemOpen (
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**/
99EFI_STATUS
100EFIAPI
101EmuSimpleFileSystemClose (
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**/
137EFI_STATUS
138EFIAPI
139EmuSimpleFileSystemDelete (
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**/
180EFI_STATUS
181EFIAPI
182EmuSimpleFileSystemRead (
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**/
230EFI_STATUS
231EFIAPI
232EmuSimpleFileSystemWrite (
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**/
267EFI_STATUS
268EFIAPI
269EmuSimpleFileSystemGetPosition (
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**/
304EFI_STATUS
305EFIAPI
306EmuSimpleFileSystemSetPosition (
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**/
348EFI_STATUS
349EFIAPI
350EmuSimpleFileSystemGetInfo (
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**/
393EFI_STATUS
394EFIAPI
395EmuSimpleFileSystemSetInfo (
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**/
439EFI_STATUS
440EFIAPI
441EmuSimpleFileSystemFlush (
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**/
480EFI_STATUS
481EFIAPI
482EmuSimpleFileSystemOpenVolume (
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
547Done:
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**/
603EFI_STATUS
604EFIAPI
605EmuSimpleFileSystemDriverBindingSupported (
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**/
687EFI_STATUS
688EFIAPI
689EmuSimpleFileSystemDriverBindingStart (
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
766Done:
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**/
815EFI_STATUS
816EFIAPI
817EmuSimpleFileSystemDriverBindingStop (
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
875EFI_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**/
897EFI_STATUS
898EFIAPI
899InitializeEmuSimpleFileSystem(
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