Home | History | Annotate | Download | only in EmuSimpleFileSystemDxe
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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