]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioRngDxe/VirtioRng.c
BaseTools/BinToPcd: Fix Python 2.7.x compatibility issue
[mirror_edk2.git] / OvmfPkg / VirtioRngDxe / VirtioRng.c
index d916534aac63f3f27d7ea0ac5c59181971e75826..3c733ea4db6666b8a7e29dfd5be42cd1ee3e7bfb 100644 (file)
@@ -6,6 +6,7 @@
 \r
   Copyright (C) 2012, Red Hat, Inc.\r
   Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>\r
 \r
   This driver:\r
 \r
@@ -139,6 +140,8 @@ VirtioRngGetRNG (
   UINT32                    Len;\r
   UINT32                    BufferSize;\r
   EFI_STATUS                Status;\r
+  EFI_PHYSICAL_ADDRESS      DeviceAddress;\r
+  VOID                      *Mapping;\r
 \r
   if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -158,6 +161,21 @@ VirtioRngGetRNG (
   }\r
 \r
   Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);\r
+  //\r
+  // Map Buffer's system phyiscal address to device address\r
+  //\r
+  Status = VirtioMapAllBytesInSharedBuffer (\r
+             Dev->VirtIo,\r
+             VirtioOperationBusMasterWrite,\r
+             (VOID *)Buffer,\r
+             RNGValueLength,\r
+             &DeviceAddress,\r
+             &Mapping\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto FreeBuffer;\r
+  }\r
 \r
   //\r
   // The Virtio RNG device may return less data than we asked it to, and can\r
@@ -169,7 +187,7 @@ VirtioRngGetRNG (
 \r
     VirtioPrepare (&Dev->Ring, &Indices);\r
     VirtioAppendDesc (&Dev->Ring,\r
-      (UINTN)Buffer + Index,\r
+      DeviceAddress + Index,\r
       BufferSize,\r
       VRING_DESC_F_WRITE,\r
       &Indices);\r
@@ -177,17 +195,35 @@ VirtioRngGetRNG (
     if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=\r
         EFI_SUCCESS) {\r
       Status = EFI_DEVICE_ERROR;\r
-      goto FreeBuffer;\r
+      goto UnmapBuffer;\r
     }\r
     ASSERT (Len > 0);\r
     ASSERT (Len <= BufferSize);\r
   }\r
 \r
+  //\r
+  // Unmap the device buffer before accessing it.\r
+  //\r
+  Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto FreeBuffer;\r
+  }\r
+\r
   for (Index = 0; Index < RNGValueLength; Index++) {\r
     RNGValue[Index] = Buffer[Index];\r
   }\r
   Status = EFI_SUCCESS;\r
 \r
+UnmapBuffer:\r
+  //\r
+  // If we are reached here due to the error then unmap the buffer otherwise\r
+  // the buffer is already unmapped after VirtioFlush().\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);\r
+  }\r
+\r
 FreeBuffer:\r
   FreePool ((VOID *)Buffer);\r
   return Status;\r
@@ -204,6 +240,7 @@ VirtioRngInit (
   EFI_STATUS Status;\r
   UINT16     QueueSize;\r
   UINT64     Features;\r
+  UINT64     RingBaseShift;\r
 \r
   //\r
   // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.\r
@@ -242,6 +279,19 @@ VirtioRngInit (
     goto Failed;\r
   }\r
 \r
+  Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;\r
+\r
+  //\r
+  // In virtio-1.0, feature negotiation is expected to complete before queue\r
+  // discovery, and the device can also reject the selected set of features.\r
+  //\r
+  if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+    Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Failed;\r
+    }\r
+  }\r
+\r
   //\r
   // step 4b -- allocate request virtqueue, just use #0\r
   //\r
@@ -262,42 +312,59 @@ VirtioRngInit (
     goto Failed;\r
   }\r
 \r
-  Status = VirtioRingInit (QueueSize, &Dev->Ring);\r
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
 \r
+  //\r
+  // If anything fails from here on, we must release the ring resources.\r
+  //\r
+  Status = VirtioRingMap (\r
+             Dev->VirtIo,\r
+             &Dev->Ring,\r
+             &RingBaseShift,\r
+             &Dev->RingMap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ReleaseQueue;\r
+  }\r
+\r
   //\r
   // Additional steps for MMIO: align the queue appropriately, and set the\r
-  // size. If anything fails from here on, we must release the ring resources.\r
+  // size. If anything fails from here on, we must unmap the ring resources.\r
   //\r
   Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
   }\r
 \r
   Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
   }\r
 \r
   //\r
   // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
   //\r
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);\r
+  Status = Dev->VirtIo->SetQueueAddress (\r
+                          Dev->VirtIo,\r
+                          &Dev->Ring,\r
+                          RingBaseShift\r
+                          );\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
   }\r
 \r
   //\r
-  // step 5 -- Report understood features and guest-tuneables. None are\r
-  // currently defined for VirtioRng, and no generic features are needed by\r
-  // this driver.\r
+  // step 5 -- Report understood features and guest-tuneables.\r
   //\r
-  Features &= 0;\r
-  Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+  if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+    Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);\r
+    Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
+    if (EFI_ERROR (Status)) {\r
+      goto UnmapQueue;\r
+    }\r
   }\r
 \r
   //\r
@@ -306,7 +373,7 @@ VirtioRngInit (
   NextDevStat |= VSTAT_DRIVER_OK;\r
   Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
   }\r
 \r
   //\r
@@ -317,8 +384,11 @@ VirtioRngInit (
 \r
   return EFI_SUCCESS;\r
 \r
+UnmapQueue:\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);\r
+\r
 ReleaseQueue:\r
-  VirtioRingUninit (&Dev->Ring);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
 \r
 Failed:\r
   //\r
@@ -345,7 +415,10 @@ VirtioRngUninit (
   // the old comms area.\r
   //\r
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
-  VirtioRingUninit (&Dev->Ring);\r
+\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);\r
+\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
 }\r
 \r
 //\r
@@ -362,6 +435,7 @@ VirtioRngExitBoot (
 {\r
   VIRTIO_RNG_DEV *Dev;\r
 \r
+  DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));\r
   //\r
   // Reset the device. This causes the hypervisor to forget about the virtio\r
   // ring.\r