Home | History | Annotate | Line # | Download | only in apps
      1 /*	$NetBSD: drv0.c,v 1.1.1.1 2018/08/16 18:17:47 jmcneill Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2013 David Decotigny <decot (at) googlers.com>
      5  *
      6  * Sample EFI shell session, together with drv0_use.efi:
      7  *
      8  *  # Loading first instance:
      9  *
     10  *    fs0:\> load drv0.efi
     11  *    Driver instance loaded successfully.
     12  *    load: Image fs0:\drv0.efi loaded at 2FD7C000 - Success
     13  *
     14  *  # Testing 1st instance:
     15  *
     16  *    fs0:\> drv0_use.efi
     17  *    Playing with driver instance 0...
     18  *    Hello Sample UEFI Driver!
     19  *    Hello was called 1 time(s).
     20  *
     21  *    fs0:\> drv0_use.efi
     22  *    Playing with driver instance 0...
     23  *    Hello Sample UEFI Driver!
     24  *    Hello was called 2 time(s).
     25  *
     26  *  # Loading another instance:
     27  *
     28  *    fs0:\> load drv0.efi
     29  *    Driver instance loaded successfully.
     30  *    load: Image fs0:\drv0.efi loaded at 2FD6D000 - Success
     31  *
     32  *  # Using both instances:
     33  *
     34  *    fs0:\> drv0_use.efi
     35  *    Playing with driver instance 0...
     36  *    Hello Sample UEFI Driver!
     37  *    Hello was called 3 time(s).
     38  *    Playing with driver instance 1...
     39  *    Hello Sample UEFI Driver!
     40  *    Hello was called 1 time(s).
     41  *
     42  *    fs0:\> drv0_use.efi
     43  *    Playing with driver instance 0...
     44  *    Hello Sample UEFI Driver!
     45  *    Hello was called 4 time(s).
     46  *    Playing with driver instance 1...
     47  *    Hello Sample UEFI Driver!
     48  *    Hello was called 2 time(s).
     49  *
     50  *  # Removing 1st instance:
     51  *
     52  *    fs0:\> dh
     53  *    Handle dump
     54  *      1: Image(DxeCore)
     55  *    [...]
     56  *     79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
     57  *     7A: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
     58  *
     59  *    fs0:\> unload 79
     60  *     79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
     61  *    Unload driver image (y/n)? y
     62  *    Driver instance unloaded.
     63  *    unload: Success
     64  *
     65  *  # Only 2nd instance remaining:
     66  *
     67  *    fs0:\> drv0_use.efi
     68  *    Playing with driver instance 0...
     69  *    Hello Sample UEFI Driver!
     70  *    Hello was called 3 time(s).
     71  *
     72  *  # Removing 2nd/last instance:
     73  *
     74  *    fs0:\> dh
     75  *    Handle dump
     76  *      1: Image(DxeCore)
     77  *    [...]
     78  *     79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
     79  *
     80  *    fs0:\> unload 79
     81  *     79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
     82  *    Unload driver image (y/n)? y
     83  *    Driver instance unloaded.
     84  *    unload: Success
     85  *
     86  *  # Expect error: no other drv0 instance left
     87  *
     88  *    fs0:\> drv0_use.efi
     89  *    Error looking up handles for proto: 14
     90  */
     91 
     92 #include <efi.h>
     93 #include <efilib.h>
     94 #include "drv0.h"
     95 
     96 
     97 static const EFI_GUID GnuEfiAppsDrv0ProtocolGuid
     98   = GNU_EFI_APPS_DRV0_PROTOCOL_GUID;
     99 
    100 static struct {
    101   GNU_EFI_APPS_DRV0_PROTOCOL Proto;
    102   UINTN Counter;
    103 } InternalGnuEfiAppsDrv0ProtocolData;
    104 
    105 
    106 static
    107 EFI_STATUS
    108 EFI_FUNCTION
    109 Drv0SayHello(
    110     IN const CHAR16 *HelloWho
    111     )
    112 {
    113   if (! HelloWho)
    114     return EFI_INVALID_PARAMETER;
    115 
    116   Print(L"Hello %s!\n", HelloWho);
    117   InternalGnuEfiAppsDrv0ProtocolData.Counter ++;
    118   return EFI_SUCCESS;
    119 }
    120 
    121 
    122 static
    123 EFI_STATUS
    124 EFI_FUNCTION
    125 Drv0GetNumberOfHello(
    126     OUT UINTN *NumberOfHello
    127     )
    128 {
    129   if (! NumberOfHello)
    130     return EFI_INVALID_PARAMETER;
    131 
    132   *NumberOfHello = InternalGnuEfiAppsDrv0ProtocolData.Counter;
    133   return EFI_SUCCESS;
    134 }
    135 
    136 
    137 static
    138 EFI_STATUS
    139 EFI_FUNCTION
    140 Drv0Unload(IN EFI_HANDLE ImageHandle)
    141 {
    142   LibUninstallProtocolInterfaces(ImageHandle,
    143                                  &GnuEfiAppsDrv0ProtocolGuid,
    144                                  &InternalGnuEfiAppsDrv0ProtocolData.Proto,
    145                                  NULL);
    146   Print(L"Driver instance unloaded.\n", ImageHandle);
    147   return EFI_SUCCESS;
    148 }
    149 
    150 
    151 EFI_STATUS
    152 efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SysTab)
    153 {
    154   EFI_STATUS Status;
    155   EFI_LOADED_IMAGE *LoadedImage = NULL;
    156 
    157   InitializeLib(ImageHandle, SysTab);
    158 
    159   /* Initialize global protocol definition + data */
    160   InternalGnuEfiAppsDrv0ProtocolData.Proto.SayHello
    161       = (GNU_EFI_APPS_DRV0_SAY_HELLO) Drv0SayHello;
    162   InternalGnuEfiAppsDrv0ProtocolData.Proto.GetNumberOfHello
    163       = (GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO) Drv0GetNumberOfHello;
    164   InternalGnuEfiAppsDrv0ProtocolData.Counter = 0;
    165 
    166   /* Grab handle to this image: we'll attach our proto instance to it */
    167   Status = uefi_call_wrapper(BS->OpenProtocol, 6,
    168                              ImageHandle, &LoadedImageProtocol,
    169                              (void**)&LoadedImage, ImageHandle,
    170                              NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    171   if (EFI_ERROR(Status)) {
    172     Print(L"Could not open loaded image protocol: %d\n", Status);
    173     return Status;
    174   }
    175 
    176   /* Attach our proto to the current driver image */
    177   Status = LibInstallProtocolInterfaces(
    178       &ImageHandle, &GnuEfiAppsDrv0ProtocolGuid,
    179       &InternalGnuEfiAppsDrv0ProtocolData.Proto, NULL);
    180   if (EFI_ERROR(Status)) {
    181     Print(L"Error registering driver instance: %d\n", Status);
    182     return Status;
    183   }
    184 
    185   /* Register Unload callback, used to unregister current protocol
    186    * instance from system */
    187   LoadedImage->Unload = (EFI_IMAGE_UNLOAD)Drv0Unload;
    188 
    189   Print(L"Driver instance loaded successfully.\n");
    190   return EFI_SUCCESS;  /* at this point, this instance stays resident
    191                         * until image is unloaded, eg. with shell's unload,
    192                         * ExitBootServices() */
    193 }
    194