3#include "pedigree/kernel/Log.h"
4#include "pedigree/kernel/machine/Device.h"
5#include "pedigree/kernel/machine/Pci.h"
6#include "pedigree/kernel/panic.h"
7#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
8#include "pedigree/kernel/processor/VirtualAddressSpace.h"
9#include "pedigree/kernel/time/Time.h"
10#include "pedigree/kernel/utilities/SecureRandom.h"
11#include "pedigree/kernel/utilities/lib.h"
13VirtioRng::VirtioRng(
Device* pci)
14 : m_Pci(pci), m_Transport(pci), m_Queue(), m_Data(
"virtio-rng data"), m_Shutdown(false) {}
16VirtioRng::~VirtioRng() {
23bool VirtioRng::seedKernel() {
26 !m_Transport.initialise() || !m_Transport.negotiate(0) ||
27 !m_Transport.setupQueue(0, m_Queue)) {
38 if (!m_Transport.ready() || !PciBus::instance().updateCommand(m_Pci, 0, 0x400U)) {
42 uint8_t seed[32] = {};
44 const auto deadline = Time::getTicks() + 5 * Time::Multiplier::Second;
45 while (received <
sizeof(seed) && Time::getTicks() < deadline) {
46 const size_t requested =
sizeof(seed) - received;
48 if (!m_Queue.submit(&buffer, 1,
this)) {
51 m_Transport.notify(0);
54 bool completed =
false;
55 while (Time::getTicks() < deadline) {
56 if (m_Queue.pop(completion)) {
60 Time::delay(Time::Multiplier::Millisecond);
63 ERROR(
"virtio-rng: seed request timed out");
66 if (completion.cookie !=
this || !completion.length || completion.length > requested) {
67 ERROR(
"virtio-rng: malformed completion");
71 MemoryCopy(seed + received, m_Data.
virtualAddress(), completion.length);
72 received += completion.length;
75 const bool seeded = received ==
sizeof(seed) && secure_random_seed(seed,
sizeof(seed));
77 pedigree_random::erase(seed,
sizeof(seed));
79 NOTICE(
"virtio-rng: seeded secure random generator");
84void VirtioRng::shutdown() {
88 if (!m_Transport.reset()) {
89 panic(
"virtio-rng: device did not stop DMA");
uint16_t getPciDeviceId()
uint16_t getPciVendorId()
void * virtualAddress() const
physical_uintptr_t physicalAddress() const
static const size_t continuous
static PhysicalMemoryManager & instance()
static constexpr size_t getPageSize() PURE
static const size_t KernelMode
static const size_t Write
void EXPORTED_PUBLIC panic(const char *msg) NORETURN