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