]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/gnu-efi/lib/contrib/apps/drv0.c
update
[l4.git] / l4 / pkg / gnu-efi / lib / contrib / apps / drv0.c
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 }