1 /** @file
2   The driver entry point for RamDiskDxe driver.
3 
4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "RamDiskImpl.h"
16 
17 //
18 // Handle for the EFI_RAM_DISK_PROTOCOL instance
19 //
20 EFI_HANDLE  mRamDiskHandle = NULL;
21 
22 //
23 // The EFI_RAM_DISK_PROTOCOL instances that is installed onto the driver
24 // handle
25 //
26 EFI_RAM_DISK_PROTOCOL  mRamDiskProtocol = {
27   RamDiskRegister,
28   RamDiskUnregister
29 };
30 
31 //
32 // RamDiskDxe driver maintains a list of registered RAM disks.
33 //
34 LIST_ENTRY  RegisteredRamDisks;
35 
36 //
37 // Pointers to the EFI_ACPI_TABLE_PROTOCOL and EFI_ACPI_SDT_PROTOCOL.
38 //
39 EFI_ACPI_TABLE_PROTOCOL  *mAcpiTableProtocol = NULL;
40 EFI_ACPI_SDT_PROTOCOL    *mAcpiSdtProtocol   = NULL;
41 
42 
43 /**
44   Check whether EFI_ACPI_TABLE_PROTOCOL and EFI_ACPI_SDT_PROTOCOL are produced.
45   If both protocols are produced, publish all the reserved memory type RAM
46   disks to the NVDIMM Firmware Interface Table (NFIT).
47 
48   @param[in] Event      Event whose notification function is being invoked.
49   @param[in] Context    The pointer to the notification function's context,
50                         which is implementation-dependent.
51 
52 **/
53 VOID
54 EFIAPI
RamDiskAcpiCheck(IN EFI_EVENT Event,IN VOID * Context)55 RamDiskAcpiCheck (
56   IN EFI_EVENT    Event,
57   IN VOID         *Context
58   )
59 {
60   EFI_STATUS                 Status;
61   LIST_ENTRY                 *Entry;
62   RAM_DISK_PRIVATE_DATA      *PrivateData;
63 
64   gBS->CloseEvent (Event);
65 
66   //
67   // Locate the EFI_ACPI_TABLE_PROTOCOL.
68   //
69   Status = gBS->LocateProtocol (
70                   &gEfiAcpiTableProtocolGuid,
71                   NULL,
72                   (VOID **)&mAcpiTableProtocol
73                   );
74   if (EFI_ERROR (Status)) {
75     DEBUG ((
76       EFI_D_INFO,
77       "RamDiskAcpiCheck: Cannot locate the EFI ACPI Table Protocol,",
78       "unable to publish RAM disks to NFIT.\n"
79       ));
80     return;
81   }
82 
83   //
84   // Locate the EFI_ACPI_SDT_PROTOCOL.
85   //
86   Status = gBS->LocateProtocol (
87                   &gEfiAcpiSdtProtocolGuid,
88                   NULL,
89                   (VOID **)&mAcpiSdtProtocol
90                   );
91   if (EFI_ERROR (Status)) {
92     DEBUG ((
93       EFI_D_INFO,
94       "RamDiskAcpiCheck: Cannot locate the EFI ACPI Sdt Protocol,",
95       "unable to publish RAM disks to NFIT.\n"
96       ));
97     mAcpiTableProtocol = NULL;
98     return;
99   }
100 
101   EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) {
102     PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
103     RamDiskPublishNfit (PrivateData);
104   }
105 }
106 
107 
108 /**
109   The entry point for RamDiskDxe driver.
110 
111   @param[in] ImageHandle     The image handle of the driver.
112   @param[in] SystemTable     The system table.
113 
114   @retval EFI_ALREADY_STARTED     The driver already exists in system.
115   @retval EFI_OUT_OF_RESOURCES    Fail to execute entry point due to lack of
116                                   resources.
117   @retval EFI_SUCCES              All the related protocols are installed on
118                                   the driver.
119 
120 **/
121 EFI_STATUS
122 EFIAPI
RamDiskDxeEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)123 RamDiskDxeEntryPoint (
124   IN EFI_HANDLE                   ImageHandle,
125   IN EFI_SYSTEM_TABLE             *SystemTable
126   )
127 {
128   EFI_STATUS                      Status;
129   RAM_DISK_CONFIG_PRIVATE_DATA    *ConfigPrivate;
130   VOID                            *DummyInterface;
131   EFI_EVENT                       Event;
132 
133   //
134   // If already started, return.
135   //
136   Status = gBS->LocateProtocol (
137                   &gEfiRamDiskProtocolGuid,
138                   NULL,
139                   &DummyInterface
140                   );
141   if (!EFI_ERROR (Status)) {
142     DEBUG ((EFI_D_INFO, "Driver already started!\n"));
143     return EFI_ALREADY_STARTED;
144   }
145 
146   //
147   // Create a private data structure.
148   //
149   ConfigPrivate = AllocateCopyPool (sizeof (RAM_DISK_CONFIG_PRIVATE_DATA), &mRamDiskConfigPrivateDataTemplate);
150   if (ConfigPrivate == NULL) {
151     return EFI_OUT_OF_RESOURCES;
152   }
153 
154   //
155   // Install RAM disk configuration form
156   //
157   Status = InstallRamDiskConfigForm (ConfigPrivate);
158   if (EFI_ERROR (Status)) {
159     goto ErrorExit;
160   }
161 
162   //
163   // Install the EFI_RAM_DISK_PROTOCOL and RAM disk private data onto a
164   // new handle
165   //
166   Status = gBS->InstallMultipleProtocolInterfaces (
167                   &mRamDiskHandle,
168                   &gEfiRamDiskProtocolGuid,
169                   &mRamDiskProtocol,
170                   &gEfiCallerIdGuid,
171                   ConfigPrivate,
172                   NULL
173                   );
174   if (EFI_ERROR (Status)) {
175     goto ErrorExit;
176   }
177 
178   //
179   // Initialize the list of registered RAM disks maintained by the driver
180   //
181   InitializeListHead (&RegisteredRamDisks);
182 
183   Status = EfiCreateEventReadyToBootEx (
184              TPL_CALLBACK,
185              RamDiskAcpiCheck,
186              NULL,
187              &Event
188              );
189   ASSERT_EFI_ERROR (Status);
190 
191   return EFI_SUCCESS;
192 
193 ErrorExit:
194   if (ConfigPrivate != NULL) {
195     UninstallRamDiskConfigForm (ConfigPrivate);
196   }
197 
198   return Status;
199 }
200 
201 
202 /**
203   Unload the RamDiskDxe driver and its configuration form.
204 
205   @param[in] ImageHandle     The driver's image handle.
206 
207   @retval EFI_SUCCESS             The RamDiskDxe driver and its configuration
208                                   form is unloaded.
209   @retval Others                  Failed to unload the form.
210 
211 **/
212 EFI_STATUS
213 EFIAPI
RamDiskDxeUnload(IN EFI_HANDLE ImageHandle)214 RamDiskDxeUnload (
215   IN EFI_HANDLE                   ImageHandle
216   )
217 {
218   EFI_STATUS                      Status;
219   RAM_DISK_CONFIG_PRIVATE_DATA    *ConfigPrivate;
220 
221   Status = gBS->HandleProtocol (
222                   mRamDiskHandle,
223                   &gEfiCallerIdGuid,
224                   (VOID **) &ConfigPrivate
225                   );
226   if (EFI_ERROR (Status)) {
227     return Status;
228   }
229 
230   ASSERT (ConfigPrivate->Signature == RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE);
231 
232   //
233   // Unregister all registered RAM disks
234   //
235   UnregisterAllRamDisks ();
236 
237   gBS->UninstallMultipleProtocolInterfaces (
238          mRamDiskHandle,
239          &gEfiRamDiskProtocolGuid,
240          &mRamDiskProtocol,
241          &gEfiCallerIdGuid,
242          ConfigPrivate,
243          NULL
244          );
245 
246   UninstallRamDiskConfigForm (ConfigPrivate);
247 
248   return EFI_SUCCESS;
249 }
250