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