1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4#pragma once
5
6#include "device.h"
7#include "ring.h"
8#include <ddk/io-buffer.h>
9#include <stdlib.h>
10#include <zircon/compiler.h>
11
12namespace virtio {
13
14class Ring;
15
16class RngDevice : public Device {
17public:
18    RngDevice(zx_device_t* bus_device, zx::bti bti, fbl::unique_ptr<Backend> backend);
19    virtual ~RngDevice();
20
21    zx_status_t Init() override;
22
23    void IrqRingUpdate() override;
24    void IrqConfigChange() override;
25    const char* tag() const override { return "virtio-rng"; }
26
27protected:
28private:
29    // TODO(SEC-29): The kernel should trigger entropy requests, instead of relying on this
30    // userspace thread to push entropy whenever it wants to. As a temporary hack, this thread
31    // pushes entropy to the kernel every 300 seconds instead.
32
33    // the entry point for the entropy seeding thread
34    static int SeedThreadEntry(void* arg);
35
36    // the method called by SeedThreadEntry() to actually launch a request
37    zx_status_t Request();
38
39    // the thread that seeds the system CPRNG periodically
40    thrd_t seed_thread_;
41
42    // the virtio ring
43    static constexpr uint16_t kRingIndex = 0;
44    static constexpr uint16_t kRingSize = 1;
45    Ring vring_ = {this};
46
47    // the buffer used to receive entropy
48    static constexpr size_t kBufferSize = ZX_CPRNG_ADD_ENTROPY_MAX_LEN;
49    io_buffer_t buf_;
50};
51
52} // namespace virtio
53