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