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 |
---|
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 |
---|
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 |
---|
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 | &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 | } |
---|