1 1.1 jmcneill /* $NetBSD: drv0.c,v 1.1.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