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