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