Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/drivers/virtio/virtio_rng.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 * Copyright (c) 2019, Linaro Limited
4
 */
5
6
#include <dm.h>
7
#include <log.h>
8
#include <rng.h>
9
#include <virtio_types.h>
10
#include <virtio.h>
11
#include <virtio_ring.h>
12
13
#define BUFFER_SIZE 16UL
14
15
struct virtio_rng_priv {
16
  struct virtqueue *rng_vq;
17
};
18
19
static int virtio_rng_read(struct udevice *dev, void *data, size_t len)
20
0
{
21
0
  int ret;
22
0
  unsigned int rsize = 1;
23
0
  unsigned char buf[BUFFER_SIZE] __aligned(4);
24
0
  unsigned char *ptr = data;
25
0
  struct virtio_sg sg;
26
0
  struct virtio_sg *sgs[1];
27
0
  struct virtio_rng_priv *priv = dev_get_priv(dev);
28
29
0
  while (len) {
30
0
    sg.addr = buf;
31
    /*
32
     * Work around implementations which always return 8 bytes
33
     * less than requested, down to 0 bytes, which would
34
     * cause an endless loop otherwise.
35
     */
36
0
    sg.length = min(rsize ? len : len + 8, sizeof(buf));
37
0
    sgs[0] = &sg;
38
39
0
    ret = virtqueue_add(priv->rng_vq, sgs, 0, 1);
40
0
    if (ret)
41
0
      return ret;
42
43
0
    virtqueue_kick(priv->rng_vq);
44
45
0
    while (!virtqueue_get_buf(priv->rng_vq, &rsize))
46
0
      ;
47
48
0
    if (rsize > sg.length)
49
0
      return -EIO;
50
51
0
    memcpy(ptr, buf, rsize);
52
0
    len -= rsize;
53
0
    ptr += rsize;
54
0
  }
55
56
0
  return 0;
57
0
}
58
59
static int virtio_rng_bind(struct udevice *dev)
60
0
{
61
0
  struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent);
62
63
  /* Indicate what driver features we support */
64
0
  virtio_driver_features_init(uc_priv, NULL, 0, NULL, 0);
65
66
0
  return 0;
67
0
}
68
69
static int virtio_rng_probe(struct udevice *dev)
70
0
{
71
0
  struct virtio_rng_priv *priv = dev_get_priv(dev);
72
0
  int ret;
73
74
0
  ret = virtio_find_vqs(dev, 1, &priv->rng_vq);
75
0
  if (ret < 0) {
76
0
    debug("%s: virtio_find_vqs failed\n", __func__);
77
0
    return ret;
78
0
  }
79
80
0
  return 0;
81
0
}
82
83
static const struct dm_rng_ops virtio_rng_ops = {
84
  .read = virtio_rng_read,
85
};
86
87
U_BOOT_DRIVER(virtio_rng) = {
88
  .name = VIRTIO_RNG_DRV_NAME,
89
  .id = UCLASS_RNG,
90
  .bind = virtio_rng_bind,
91
  .probe  = virtio_rng_probe,
92
  .remove = virtio_reset,
93
  .ops  = &virtio_rng_ops,
94
  .priv_auto  = sizeof(struct virtio_rng_priv),
95
  .flags  = DM_FLAG_ACTIVE_DMA,
96
};