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