diff --git a/Cargo.toml b/Cargo.toml index 2493066b8..02e3328d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ acpi = ["vmm/acpi"] pci = ["vmm/pci_support"] mmio = ["vmm/mmio_support"] cmos = ["vmm/cmos"] +fwdebug = ["vmm/fwdebug"] # Integration tests require a special environment to run in integration_tests = [] diff --git a/devices/Cargo.toml b/devices/Cargo.toml index 966c0a3a1..a74ad0cba 100644 --- a/devices/Cargo.toml +++ b/devices/Cargo.toml @@ -26,3 +26,4 @@ tempfile = "3.1.0" default = [] acpi = ["acpi_tables"] cmos = [] +fwdebug = [] diff --git a/devices/src/legacy/fwdebug.rs b/devices/src/legacy/fwdebug.rs new file mode 100644 index 000000000..557bcb5a9 --- /dev/null +++ b/devices/src/legacy/fwdebug.rs @@ -0,0 +1,40 @@ +// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE-BSD-3-Clause file. +// +// Copyright © 2020 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause +// + +use BusDevice; + +/// Provides firmware debug output via I/O port controls +#[derive(Default)] +pub struct FwDebugDevice {} + +impl FwDebugDevice { + pub fn new() -> Self { + Self {} + } +} + +/// FwDebugDevice sits on the I/O bus as 0x402 and receives ASCII characters +impl BusDevice for FwDebugDevice { + /// Upon read return the magic value to indicate that there is a debug port + fn read(&mut self, _base: u64, _offset: u64, data: &mut [u8]) { + if data.len() == 1 { + data[0] = 0xe9 + } else { + error!("Invalid read size on debug port: {}", data.len()) + } + } + + fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) { + if data.len() == 1 { + print!("{}", data[0] as char); + } else { + error!("Invalid write size on debug port: {}", data.len()) + } + } +} diff --git a/devices/src/legacy/mod.rs b/devices/src/legacy/mod.rs index 9f1c96686..8bc7c542a 100644 --- a/devices/src/legacy/mod.rs +++ b/devices/src/legacy/mod.rs @@ -7,10 +7,14 @@ #[cfg(feature = "cmos")] mod cmos; +#[cfg(feature = "fwdebug")] +mod fwdebug; mod i8042; mod serial; #[cfg(feature = "cmos")] pub use self::cmos::Cmos; +#[cfg(feature = "fwdebug")] +pub use self::fwdebug::FwDebugDevice; pub use self::i8042::I8042Device; pub use self::serial::Serial; diff --git a/vmm/Cargo.toml b/vmm/Cargo.toml index 6b43814fb..cc38e643b 100644 --- a/vmm/Cargo.toml +++ b/vmm/Cargo.toml @@ -10,6 +10,7 @@ acpi = ["acpi_tables","devices/acpi"] pci_support = ["pci", "vfio", "vm-virtio/pci_support"] mmio_support = ["vm-virtio/mmio_support"] cmos = ["devices/cmos"] +fwdebug = ["devices/fwdebug"] [dependencies] arc-swap = ">=0.4.4" diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 19eef0fe2..a71d2dc3d 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -947,6 +947,18 @@ impl DeviceManager { .insert(cmos, 0x70, 0x2) .map_err(DeviceManagerError::BusError)?; } + #[cfg(feature = "fwdebug")] + { + let fwdebug = Arc::new(Mutex::new(devices::legacy::FwDebugDevice::new())); + + self.bus_devices + .push(Arc::clone(&fwdebug) as Arc>); + + self.address_manager + .io_bus + .insert(fwdebug, 0x402, 0x1) + .map_err(DeviceManagerError::BusError)?; + } Ok(()) }