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@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
Drv0SayHello(IN const CHAR16 * HelloWho)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
Drv0GetNumberOfHello(OUT UINTN * NumberOfHello)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
Drv0Unload(IN EFI_HANDLE ImageHandle)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
efi_main(EFI_HANDLE ImageHandle,EFI_SYSTEM_TABLE * SysTab)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