]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioRngDxe/VirtioRng.c
OvmfPkg: VIRTIO_DEVICE_PROTOCOL: pass VRING object to SetQueueAddress()
[mirror_edk2.git] / OvmfPkg / VirtioRngDxe / VirtioRng.c
CommitLineData
5528732a
AB
1/** @file\r
2\r
3 This driver produces EFI_RNG_PROTOCOL instances for virtio-rng devices.\r
4\r
5 The implementation is based on OvmfPkg/VirtioScsiDxe/VirtioScsi.c\r
6\r
7 Copyright (C) 2012, Red Hat, Inc.\r
8 Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>\r
9\r
10 This driver:\r
11\r
12 Copyright (C) 2016, Linaro Ltd.\r
13\r
14 This program and the accompanying materials are licensed and made available\r
15 under the terms and conditions of the BSD License which accompanies this\r
16 distribution. The full text of the license may be found at\r
17 http://opensource.org/licenses/bsd-license.php\r
18\r
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
20 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
21\r
22**/\r
23\r
24#include <Library/BaseMemoryLib.h>\r
25#include <Library/DebugLib.h>\r
26#include <Library/MemoryAllocationLib.h>\r
27#include <Library/UefiBootServicesTableLib.h>\r
28#include <Library/UefiLib.h>\r
29#include <Library/VirtioLib.h>\r
30\r
31#include "VirtioRng.h"\r
32\r
33/**\r
34 Returns information about the random number generation implementation.\r
35\r
36 @param[in] This A pointer to the EFI_RNG_PROTOCOL\r
37 instance.\r
38 @param[in,out] RNGAlgorithmListSize On input, the size in bytes of\r
39 RNGAlgorithmList.\r
40 On output with a return code of\r
41 EFI_SUCCESS, the size in bytes of the\r
42 data returned in RNGAlgorithmList. On\r
43 output with a return code of\r
44 EFI_BUFFER_TOO_SMALL, the size of\r
45 RNGAlgorithmList required to obtain the\r
46 list.\r
47 @param[out] RNGAlgorithmList A caller-allocated memory buffer filled\r
48 by the driver with one EFI_RNG_ALGORITHM\r
49 element for each supported RNG algorithm.\r
50 The list must not change across multiple\r
51 calls to the same driver. The first\r
52 algorithm in the list is the default\r
53 algorithm for the driver.\r
54\r
55 @retval EFI_SUCCESS The RNG algorithm list was returned\r
56 successfully.\r
57 @retval EFI_UNSUPPORTED The services is not supported by this\r
58 driver.\r
59 @retval EFI_DEVICE_ERROR The list of algorithms could not be\r
60 retrieved due to a hardware or firmware\r
61 error.\r
62 @retval EFI_INVALID_PARAMETER One or more of the parameters are\r
63 incorrect.\r
64 @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small\r
65 to hold the result.\r
66\r
67**/\r
68STATIC\r
69EFI_STATUS\r
70EFIAPI\r
71VirtioRngGetInfo (\r
72 IN EFI_RNG_PROTOCOL *This,\r
73 IN OUT UINTN *RNGAlgorithmListSize,\r
74 OUT EFI_RNG_ALGORITHM *RNGAlgorithmList\r
75 )\r
76{\r
77 if (This == NULL || RNGAlgorithmListSize == NULL) {\r
78 return EFI_INVALID_PARAMETER;\r
79 }\r
80\r
81 if (*RNGAlgorithmListSize < sizeof (EFI_RNG_ALGORITHM)) {\r
82 *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);\r
83 return EFI_BUFFER_TOO_SMALL;\r
84 }\r
85\r
86 if (RNGAlgorithmList == NULL) {\r
87 return EFI_INVALID_PARAMETER;\r
88 }\r
89\r
90 *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);\r
91 CopyGuid (RNGAlgorithmList, &gEfiRngAlgorithmRaw);\r
92\r
93 return EFI_SUCCESS;\r
94}\r
95\r
96/**\r
97 Produces and returns an RNG value using either the default or specified RNG\r
98 algorithm.\r
99\r
100 @param[in] This A pointer to the EFI_RNG_PROTOCOL\r
101 instance.\r
102 @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that\r
103 identifies the RNG algorithm to use. May\r
104 be NULL in which case the function will\r
105 use its default RNG algorithm.\r
106 @param[in] RNGValueLength The length in bytes of the memory buffer\r
107 pointed to by RNGValue. The driver shall\r
108 return exactly this numbers of bytes.\r
109 @param[out] RNGValue A caller-allocated memory buffer filled\r
110 by the driver with the resulting RNG\r
111 value.\r
112\r
113 @retval EFI_SUCCESS The RNG value was returned successfully.\r
114 @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm\r
115 is not supported by this driver.\r
116 @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due\r
117 to a hardware or firmware error.\r
118 @retval EFI_NOT_READY There is not enough random data available\r
119 to satisfy the length requested by\r
120 RNGValueLength.\r
121 @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is\r
122 zero.\r
123\r
124**/\r
125STATIC\r
126EFI_STATUS\r
127EFIAPI\r
128VirtioRngGetRNG (\r
129 IN EFI_RNG_PROTOCOL *This,\r
130 IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL\r
131 IN UINTN RNGValueLength,\r
132 OUT UINT8 *RNGValue\r
133 )\r
134{\r
135 VIRTIO_RNG_DEV *Dev;\r
136 DESC_INDICES Indices;\r
137 volatile UINT8 *Buffer;\r
138 UINTN Index;\r
139 UINT32 Len;\r
140 UINT32 BufferSize;\r
141 EFI_STATUS Status;\r
142\r
143 if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {\r
144 return EFI_INVALID_PARAMETER;\r
145 }\r
146\r
147 //\r
148 // We only support the raw algorithm, so reject requests for anything else\r
149 //\r
150 if (RNGAlgorithm != NULL &&\r
151 !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {\r
152 return EFI_UNSUPPORTED;\r
153 }\r
154\r
155 Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength);\r
156 if (Buffer == NULL) {\r
157 return EFI_DEVICE_ERROR;\r
158 }\r
159\r
160 Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);\r
161\r
162 //\r
163 // The Virtio RNG device may return less data than we asked it to, and can\r
164 // only return MAX_UINT32 bytes per invocation. So loop as long as needed to\r
165 // get all the entropy we were asked for.\r
166 //\r
167 for (Index = 0; Index < RNGValueLength; Index += Len) {\r
168 BufferSize = (UINT32)MIN (RNGValueLength - Index, (UINTN)MAX_UINT32);\r
169\r
170 VirtioPrepare (&Dev->Ring, &Indices);\r
171 VirtioAppendDesc (&Dev->Ring,\r
172 (UINTN)Buffer + Index,\r
173 BufferSize,\r
174 VRING_DESC_F_WRITE,\r
175 &Indices);\r
176\r
177 if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=\r
178 EFI_SUCCESS) {\r
179 Status = EFI_DEVICE_ERROR;\r
180 goto FreeBuffer;\r
181 }\r
182 ASSERT (Len > 0);\r
183 ASSERT (Len <= BufferSize);\r
184 }\r
185\r
186 for (Index = 0; Index < RNGValueLength; Index++) {\r
187 RNGValue[Index] = Buffer[Index];\r
188 }\r
189 Status = EFI_SUCCESS;\r
190\r
191FreeBuffer:\r
192 FreePool ((VOID *)Buffer);\r
193 return Status;\r
194}\r
195\r
196STATIC\r
197EFI_STATUS\r
198EFIAPI\r
199VirtioRngInit (\r
200 IN OUT VIRTIO_RNG_DEV *Dev\r
201 )\r
202{\r
203 UINT8 NextDevStat;\r
204 EFI_STATUS Status;\r
205 UINT16 QueueSize;\r
bc8fde6f 206 UINT64 Features;\r
5528732a
AB
207\r
208 //\r
209 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.\r
210 //\r
211 NextDevStat = 0; // step 1 -- reset device\r
212 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
213 if (EFI_ERROR (Status)) {\r
214 goto Failed;\r
215 }\r
216\r
217 NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence\r
218 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
219 if (EFI_ERROR (Status)) {\r
220 goto Failed;\r
221 }\r
222\r
223 NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
224 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
225 if (EFI_ERROR (Status)) {\r
226 goto Failed;\r
227 }\r
228\r
229 //\r
230 // Set Page Size - MMIO VirtIo Specific\r
231 //\r
232 Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);\r
233 if (EFI_ERROR (Status)) {\r
234 goto Failed;\r
235 }\r
236\r
237 //\r
238 // step 4a -- retrieve and validate features\r
239 //\r
240 Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
241 if (EFI_ERROR (Status)) {\r
242 goto Failed;\r
243 }\r
244\r
245 //\r
246 // step 4b -- allocate request virtqueue, just use #0\r
247 //\r
248 Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);\r
249 if (EFI_ERROR (Status)) {\r
250 goto Failed;\r
251 }\r
252 Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
253 if (EFI_ERROR (Status)) {\r
254 goto Failed;\r
255 }\r
256\r
257 //\r
258 // VirtioRngGetRNG() uses one descriptor\r
259 //\r
260 if (QueueSize < 1) {\r
261 Status = EFI_UNSUPPORTED;\r
262 goto Failed;\r
263 }\r
264\r
265 Status = VirtioRingInit (QueueSize, &Dev->Ring);\r
266 if (EFI_ERROR (Status)) {\r
267 goto Failed;\r
268 }\r
269\r
270 //\r
271 // Additional steps for MMIO: align the queue appropriately, and set the\r
272 // size. If anything fails from here on, we must release the ring resources.\r
273 //\r
274 Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
275 if (EFI_ERROR (Status)) {\r
276 goto ReleaseQueue;\r
277 }\r
278\r
279 Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
280 if (EFI_ERROR (Status)) {\r
281 goto ReleaseQueue;\r
282 }\r
283\r
284 //\r
285 // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
286 //\r
07af4eee 287 Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);\r
5528732a
AB
288 if (EFI_ERROR (Status)) {\r
289 goto ReleaseQueue;\r
290 }\r
291\r
292 //\r
293 // step 5 -- Report understood features and guest-tuneables. None are\r
294 // currently defined for VirtioRng, and no generic features are needed by\r
295 // this driver.\r
296 //\r
297 Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, 0);\r
298 if (EFI_ERROR (Status)) {\r
299 goto ReleaseQueue;\r
300 }\r
301\r
302 //\r
303 // step 6 -- initialization complete\r
304 //\r
305 NextDevStat |= VSTAT_DRIVER_OK;\r
306 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
307 if (EFI_ERROR (Status)) {\r
308 goto ReleaseQueue;\r
309 }\r
310\r
311 //\r
312 // populate the exported interface's attributes\r
313 //\r
314 Dev->Rng.GetInfo = VirtioRngGetInfo;\r
315 Dev->Rng.GetRNG = VirtioRngGetRNG;\r
316\r
317 return EFI_SUCCESS;\r
318\r
319ReleaseQueue:\r
320 VirtioRingUninit (&Dev->Ring);\r
321\r
322Failed:\r
323 //\r
324 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device\r
325 // Status. VirtIo access failure here should not mask the original error.\r
326 //\r
327 NextDevStat |= VSTAT_FAILED;\r
328 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
329\r
330 return Status; // reached only via Failed above\r
331}\r
332\r
333\r
334STATIC\r
335VOID\r
336EFIAPI\r
337VirtioRngUninit (\r
338 IN OUT VIRTIO_RNG_DEV *Dev\r
339 )\r
340{\r
341 //\r
342 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When\r
343 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from\r
344 // the old comms area.\r
345 //\r
346 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
347 VirtioRingUninit (&Dev->Ring);\r
348}\r
349\r
350//\r
351// Event notification function enqueued by ExitBootServices().\r
352//\r
353\r
354STATIC\r
355VOID\r
356EFIAPI\r
357VirtioRngExitBoot (\r
358 IN EFI_EVENT Event,\r
359 IN VOID *Context\r
360 )\r
361{\r
362 VIRTIO_RNG_DEV *Dev;\r
363\r
364 //\r
365 // Reset the device. This causes the hypervisor to forget about the virtio\r
366 // ring.\r
367 //\r
368 // We allocated said ring in EfiBootServicesData type memory, and code\r
369 // executing after ExitBootServices() is permitted to overwrite it.\r
370 //\r
371 Dev = Context;\r
372 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
373}\r
374\r
375\r
376//\r
377// Probe, start and stop functions of this driver, called by the DXE core for\r
378// specific devices.\r
379//\r
380// The following specifications document these interfaces:\r
381// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol\r
382// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol\r
383//\r
384// The implementation follows:\r
385// - Driver Writer's Guide for UEFI 2.3.1 v1.01\r
386// - 5.1.3.4 OpenProtocol() and CloseProtocol()\r
387// - UEFI Spec 2.3.1 + Errata C\r
388// - 6.3 Protocol Handler Services\r
389//\r
390\r
391STATIC\r
392EFI_STATUS\r
393EFIAPI\r
394VirtioRngDriverBindingSupported (\r
395 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
396 IN EFI_HANDLE DeviceHandle,\r
397 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
398 )\r
399{\r
400 EFI_STATUS Status;\r
401 VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
402\r
403 //\r
404 // Attempt to open the device with the VirtIo set of interfaces. On success,\r
405 // the protocol is "instantiated" for the VirtIo device. Covers duplicate\r
406 // open attempts (EFI_ALREADY_STARTED).\r
407 //\r
408 Status = gBS->OpenProtocol (\r
409 DeviceHandle, // candidate device\r
410 &gVirtioDeviceProtocolGuid, // for generic VirtIo access\r
411 (VOID **)&VirtIo, // handle to instantiate\r
412 This->DriverBindingHandle, // requestor driver identity\r
413 DeviceHandle, // ControllerHandle, according to\r
414 // the UEFI Driver Model\r
415 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to\r
416 // the device; to be released\r
417 );\r
418 if (EFI_ERROR (Status)) {\r
419 return Status;\r
420 }\r
421\r
422 if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) {\r
423 Status = EFI_UNSUPPORTED;\r
424 }\r
425\r
426 //\r
427 // We needed VirtIo access only transitorily, to see whether we support the\r
428 // device or not.\r
429 //\r
430 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
431 This->DriverBindingHandle, DeviceHandle);\r
432 return Status;\r
433}\r
434\r
435STATIC\r
436EFI_STATUS\r
437EFIAPI\r
438VirtioRngDriverBindingStart (\r
439 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
440 IN EFI_HANDLE DeviceHandle,\r
441 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
442 )\r
443{\r
444 VIRTIO_RNG_DEV *Dev;\r
445 EFI_STATUS Status;\r
446\r
447 Dev = (VIRTIO_RNG_DEV *) AllocateZeroPool (sizeof *Dev);\r
448 if (Dev == NULL) {\r
449 return EFI_OUT_OF_RESOURCES;\r
450 }\r
451\r
452 Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
453 (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
454 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
455 if (EFI_ERROR (Status)) {\r
456 goto FreeVirtioRng;\r
457 }\r
458\r
459 //\r
460 // VirtIo access granted, configure virtio-rng device.\r
461 //\r
462 Status = VirtioRngInit (Dev);\r
463 if (EFI_ERROR (Status)) {\r
464 goto CloseVirtIo;\r
465 }\r
466\r
467 Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,\r
468 &VirtioRngExitBoot, Dev, &Dev->ExitBoot);\r
469 if (EFI_ERROR (Status)) {\r
470 goto UninitDev;\r
471 }\r
472\r
473 //\r
474 // Setup complete, attempt to export the driver instance's EFI_RNG_PROTOCOL\r
475 // interface.\r
476 //\r
477 Dev->Signature = VIRTIO_RNG_SIG;\r
478 Status = gBS->InstallProtocolInterface (&DeviceHandle,\r
479 &gEfiRngProtocolGuid, EFI_NATIVE_INTERFACE,\r
480 &Dev->Rng);\r
481 if (EFI_ERROR (Status)) {\r
482 goto CloseExitBoot;\r
483 }\r
484\r
485 return EFI_SUCCESS;\r
486\r
487CloseExitBoot:\r
488 gBS->CloseEvent (Dev->ExitBoot);\r
489\r
490UninitDev:\r
491 VirtioRngUninit (Dev);\r
492\r
493CloseVirtIo:\r
494 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
495 This->DriverBindingHandle, DeviceHandle);\r
496\r
497FreeVirtioRng:\r
498 FreePool (Dev);\r
499\r
500 return Status;\r
501}\r
502\r
503\r
504STATIC\r
505EFI_STATUS\r
506EFIAPI\r
507VirtioRngDriverBindingStop (\r
508 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
509 IN EFI_HANDLE DeviceHandle,\r
510 IN UINTN NumberOfChildren,\r
511 IN EFI_HANDLE *ChildHandleBuffer\r
512 )\r
513{\r
514 EFI_STATUS Status;\r
515 EFI_RNG_PROTOCOL *Rng;\r
516 VIRTIO_RNG_DEV *Dev;\r
517\r
518 Status = gBS->OpenProtocol (\r
519 DeviceHandle, // candidate device\r
520 &gEfiRngProtocolGuid, // retrieve the RNG iface\r
521 (VOID **)&Rng, // target pointer\r
522 This->DriverBindingHandle, // requestor driver ident.\r
523 DeviceHandle, // lookup req. for dev.\r
524 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no new ref.\r
525 );\r
526 if (EFI_ERROR (Status)) {\r
527 return Status;\r
528 }\r
529\r
530 Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (Rng);\r
531\r
532 //\r
533 // Handle Stop() requests for in-use driver instances gracefully.\r
534 //\r
535 Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
536 &gEfiRngProtocolGuid, &Dev->Rng);\r
537 if (EFI_ERROR (Status)) {\r
538 return Status;\r
539 }\r
540\r
541 gBS->CloseEvent (Dev->ExitBoot);\r
542\r
543 VirtioRngUninit (Dev);\r
544\r
545 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
546 This->DriverBindingHandle, DeviceHandle);\r
547\r
548 FreePool (Dev);\r
549\r
550 return EFI_SUCCESS;\r
551}\r
552\r
553\r
554//\r
555// The static object that groups the Supported() (ie. probe), Start() and\r
556// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata\r
557// C, 10.1 EFI Driver Binding Protocol.\r
558//\r
559STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
560 &VirtioRngDriverBindingSupported,\r
561 &VirtioRngDriverBindingStart,\r
562 &VirtioRngDriverBindingStop,\r
563 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers\r
564 NULL, // ImageHandle, to be overwritten by\r
565 // EfiLibInstallDriverBindingComponentName2() in VirtioRngEntryPoint()\r
566 NULL // DriverBindingHandle, ditto\r
567};\r
568\r
569\r
570//\r
571// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and\r
572// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name\r
573// in English, for display on standard console devices. This is recommended for\r
574// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's\r
575// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.\r
576//\r
577\r
578STATIC\r
579EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
580 { "eng;en", L"Virtio Random Number Generator Driver" },\r
581 { NULL, NULL }\r
582};\r
583\r
584STATIC\r
585EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
586\r
587STATIC\r
588EFI_STATUS\r
589EFIAPI\r
590VirtioRngGetDriverName (\r
591 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
592 IN CHAR8 *Language,\r
593 OUT CHAR16 **DriverName\r
594 )\r
595{\r
596 return LookupUnicodeString2 (\r
597 Language,\r
598 This->SupportedLanguages,\r
599 mDriverNameTable,\r
600 DriverName,\r
601 (BOOLEAN)(This == &gComponentName) // Iso639Language\r
602 );\r
603}\r
604\r
605STATIC\r
606EFI_STATUS\r
607EFIAPI\r
608VirtioRngGetDeviceName (\r
609 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
610 IN EFI_HANDLE DeviceHandle,\r
611 IN EFI_HANDLE ChildHandle,\r
612 IN CHAR8 *Language,\r
613 OUT CHAR16 **ControllerName\r
614 )\r
615{\r
616 return EFI_UNSUPPORTED;\r
617}\r
618\r
619STATIC\r
620EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
621 &VirtioRngGetDriverName,\r
622 &VirtioRngGetDeviceName,\r
623 "eng" // SupportedLanguages, ISO 639-2 language codes\r
624};\r
625\r
626STATIC\r
627EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
628 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioRngGetDriverName,\r
629 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioRngGetDeviceName,\r
630 "en" // SupportedLanguages, RFC 4646 language codes\r
631};\r
632\r
633\r
634//\r
635// Entry point of this driver.\r
636//\r
637EFI_STATUS\r
638EFIAPI\r
639VirtioRngEntryPoint (\r
640 IN EFI_HANDLE ImageHandle,\r
641 IN EFI_SYSTEM_TABLE *SystemTable\r
642 )\r
643{\r
644 return EfiLibInstallDriverBindingComponentName2 (\r
645 ImageHandle,\r
646 SystemTable,\r
647 &gDriverBinding,\r
648 ImageHandle,\r
649 &gComponentName,\r
650 &gComponentName2\r
651 );\r
652}\r