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