xref: /netbsd-src/sys/external/bsd/gnu-efi/dist/apps/drv0.c (revision d1b935f8e85510a16a1b49122bd2ccf5ad7e104c)
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