1 /*
2 * Copyright (C) 2013 David Decotigny <decot@googlers.com>
3 *
4 * Sample EFI shell session, together with drv0_use.efi:
5 *
6 * # Loading first instance:
7 *
8 * fs0:\> load drv0.efi
9 * Driver instance loaded successfully.
10 * load: Image fs0:\drv0.efi loaded at 2FD7C000 - Success
11 *
12 * # Testing 1st instance:
13 *
14 * fs0:\> drv0_use.efi
15 * Playing with driver instance 0...
16 * Hello Sample UEFI Driver!
17 * Hello was called 1 time(s).
18 *
19 * fs0:\> drv0_use.efi
20 * Playing with driver instance 0...
21 * Hello Sample UEFI Driver!
22 * Hello was called 2 time(s).
23 *
24 * # Loading another instance:
25 *
26 * fs0:\> load drv0.efi
27 * Driver instance loaded successfully.
28 * load: Image fs0:\drv0.efi loaded at 2FD6D000 - Success
29 *
30 * # Using both instances:
31 *
32 * fs0:\> drv0_use.efi
33 * Playing with driver instance 0...
34 * Hello Sample UEFI Driver!
35 * Hello was called 3 time(s).
36 * Playing with driver instance 1...
37 * Hello Sample UEFI Driver!
38 * Hello was called 1 time(s).
39 *
40 * fs0:\> drv0_use.efi
41 * Playing with driver instance 0...
42 * Hello Sample UEFI Driver!
43 * Hello was called 4 time(s).
44 * Playing with driver instance 1...
45 * Hello Sample UEFI Driver!
46 * Hello was called 2 time(s).
47 *
48 * # Removing 1st instance:
49 *
50 * fs0:\> dh
51 * Handle dump
52 * 1: Image(DxeCore)
53 * [...]
54 * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
55 * 7A: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
56 *
57 * fs0:\> unload 79
58 * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
59 * Unload driver image (y/n)? y
60 * Driver instance unloaded.
61 * unload: Success
62 *
63 * # Only 2nd instance remaining:
64 *
65 * fs0:\> drv0_use.efi
66 * Playing with driver instance 0...
67 * Hello Sample UEFI Driver!
68 * Hello was called 3 time(s).
69 *
70 * # Removing 2nd/last instance:
71 *
72 * fs0:\> dh
73 * Handle dump
74 * 1: Image(DxeCore)
75 * [...]
76 * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
77 *
78 * fs0:\> unload 79
79 * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
80 * Unload driver image (y/n)? y
81 * Driver instance unloaded.
82 * unload: Success
83 *
84 * # Expect error: no other drv0 instance left
85 *
86 * fs0:\> drv0_use.efi
87 * Error looking up handles for proto: 14
88 */
89
90 #include <efi.h>
91 #include <efilib.h>
92 #include "drv0.h"
93
94
95 static const EFI_GUID GnuEfiAppsDrv0ProtocolGuid
96 = GNU_EFI_APPS_DRV0_PROTOCOL_GUID;
97
98 static struct {
99 GNU_EFI_APPS_DRV0_PROTOCOL Proto;
100 UINTN Counter;
101 } InternalGnuEfiAppsDrv0ProtocolData;
102
103
104 static
105 EFI_STATUS
106 EFI_FUNCTION
Drv0SayHello(IN struct _GNU_EFI_APPS_DRV0_PROTOCOL * This,IN const CHAR16 * HelloWho)107 Drv0SayHello(
108 IN struct _GNU_EFI_APPS_DRV0_PROTOCOL *This,
109 IN const CHAR16 *HelloWho
110 )
111 {
112 if (! HelloWho)
113 return EFI_INVALID_PARAMETER;
114
115 Print(L"Hello %s!\n", HelloWho);
116 InternalGnuEfiAppsDrv0ProtocolData.Counter ++;
117 return EFI_SUCCESS;
118 }
119
120
121 static
122 EFI_STATUS
123 EFI_FUNCTION
Drv0GetNumberOfHello(IN struct _GNU_EFI_APPS_DRV0_PROTOCOL * This,OUT UINTN * NumberOfHello)124 Drv0GetNumberOfHello(
125 IN struct _GNU_EFI_APPS_DRV0_PROTOCOL *This,
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 &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