Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,12 @@ Supported commands include:
extended configuration space for the given bus/device/function
* `ecamwr <b/d/f> <offset> <value>` writes a 32-bit word to PCIe
extended configuration space for the given bus/device/function
* `getbits <start>,<end> <value>` returns the given bit range
* `getbits <start>,<end> <value>` returns the given bit range
from `<value>`
* `setbits <start>,<end> <new bits> <value>` sets the given bit
range in `<value>` to `<new bits>`
* `spinner` displays a moving "spinner" on the terminal until a
byte is received on the UART.

## Building bldb

Expand Down
28 changes: 28 additions & 0 deletions src/clock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2021 The Hypatia Authors
// All rights reserved
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

use crate::cpuid;

pub const NANOS_PER_SEC: u128 = 1_000_000_000;

/// Returns the clock frequency of the current CPU in Hertz.
pub fn frequency() -> u128 {
const DEFAULT_HZ: u128 = 2_000_000_000;
if let Some(tsc_info) = cpuid::tscinfo() {
if tsc_info.nominal_frequency() != 0 {
return tsc_info
.tsc_frequency()
.map(|freq| freq.into())
.unwrap_or(DEFAULT_HZ);
}
}
DEFAULT_HZ
}

pub fn rdtsc() -> u64 {
unsafe { core::arch::x86_64::_rdtsc() }
}
13 changes: 10 additions & 3 deletions src/cpuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

pub(crate) fn cpuid(leaf: u32, subleaf: u32) -> x86::cpuid::CpuIdResult {
x86::cpuid::native_cpuid::cpuid_count(leaf, subleaf)
use x86::cpuid;

pub(crate) fn cpuid(leaf: u32, subleaf: u32) -> cpuid::CpuIdResult {
cpuid::native_cpuid::cpuid_count(leaf, subleaf)
}

/// Returns information about the current processor and its
/// package.
pub(crate) fn cpuinfo() -> Option<(u8, u8, u8, Option<u32>)> {
let cpuid = x86::cpuid::CpuId::new();
let cpuid = cpuid::CpuId::new();
let features = cpuid.get_feature_info()?;
let family = features.family_id();
let ext = cpuid.get_extended_processor_and_feature_identifiers()?;
let pkg_type = (family > 0x10).then_some(ext.pkg_type());
Some((family, features.model_id(), features.stepping_id(), pkg_type))
}

pub(crate) fn tscinfo() -> Option<cpuid::TscInfo> {
let cpuid = cpuid::CpuId::new();
cpuid.get_tsc_info()
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern crate alloc;

mod allocator;
mod bldb;
mod clock;
mod cons;
mod cpuid;
mod gpio;
Expand Down
2 changes: 1 addition & 1 deletion src/ramdisk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::ufs;
pub fn mount(
ramdisk: &'static [u8],
) -> Result<Option<ufs::FileSystem<'static>>> {
let fs = ufs::FileSystem::new(ramdisk);
let fs = ufs::FileSystem::new(ramdisk)?;
if let Ok(ufs::State::Clean) = fs.state() {
let flags = fs.flags();
println!("ramdisk mounted successfully (Clean, {flags:?})");
Expand Down
22 changes: 22 additions & 0 deletions src/repl/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,28 @@ use crate::repl::{self, Value};
use crate::result::{Error, Result};
use alloc::vec::Vec;

pub fn loadcpio(
config: &mut bldb::Config,
env: &mut Vec<Value>,
) -> Result<Value> {
let usage = |error| {
println!("usage: loadcpio <src addr>,<len> <path>");
error
};
let cpio = repl::popenv(env)
.as_slice(&config.page_table, 0)
.and_then(|o| o.ok_or(Error::BadArgs))
.map_err(usage)?;
let path = repl::popenv(env).as_string().map_err(usage)?;
let src = cpio_reader::iter_files(cpio)
.find(|entry| entry.name() == path)
.ok_or(Error::CpioNoFile)?
.file();
let entry = loader::load_bytes(&mut config.page_table, src)?;
let entry = entry.try_into().unwrap();
Ok(Value::Pointer(src.as_ptr().with_addr(entry).cast_mut()))
}

pub fn loadmem(
config: &mut bldb::Config,
env: &mut Vec<Value>,
Expand Down
4 changes: 4 additions & 0 deletions src/repl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mod rx;
mod rz;
mod sha;
mod smn;
mod spinner;
mod vm;

#[derive(Clone)]
Expand Down Expand Up @@ -239,6 +240,7 @@ fn evalcmd(
"inw" => pio::inw(config, env),
"jfmt" => jfmt::run(config, env),
"load" => load::run(config, env),
"loadcpio" => load::loadcpio(config, env),
"loadmem" => load::loadmem(config, env),
"ls" | "list" => list::run(config, env),
"map" => vm::map(config, env),
Expand All @@ -251,6 +253,7 @@ fn evalcmd(
"peek" => memory::read(config, env),
"poke" => memory::write(config, env),
"pop" => Ok(pop2(env)),
"pulser" | "throbber" => spinner::pulser(config, env),
"push" => Ok(Value::Nil),
"rdmsr" => msr::read(config, env),
"rdsmn" => smn::read(config, env),
Expand All @@ -259,6 +262,7 @@ fn evalcmd(
"setbits" => bits::set(config, env),
"sha256" => sha::run(config, env),
"sha256mem" => sha::mem(config, env),
"spinner" => spinner::spinner(config, env),
"unmap" => vm::unmap(config, env),
"wrmsr" => msr::write(config, env),
"wrsmn" => smn::write(config, env),
Expand Down
2 changes: 2 additions & 0 deletions src/repl/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@ Supported commands include:
from `<value>`
* `setbits <start>,<end> <new bits> <value>` sets the given bit
range in `<value>` to `<new bits>`
* `spinner` displays a moving "spinner" on the terminal until a
byte is received on the UART.
"#
);
}
36 changes: 36 additions & 0 deletions src/repl/spinner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use crate::bldb;
use crate::repl;
use crate::uart;
use core::time::Duration;

fn run(term: &mut uart::Uart, bs: &[u8], timeout: Duration) {
const BS: u8 = 8;
for &b in bs.iter().cycle() {
term.putb(b);
if term.try_getb_timeout(timeout).is_ok() {
break;
}
term.putb(BS);
}
term.putb(BS);
}

pub(super) fn spinner(
config: &mut bldb::Config,
_env: &mut [repl::Value],
) -> repl::Result<repl::Value> {
run(&mut config.cons, b"|/-\\", Duration::from_millis(100));
Ok(repl::Value::Nil)
}

pub(super) fn pulser(
config: &mut bldb::Config,
_env: &mut [repl::Value],
) -> repl::Result<repl::Value> {
run(&mut config.cons, b"oOo.", Duration::from_millis(500));
Ok(repl::Value::Nil)
}
6 changes: 6 additions & 0 deletions src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ pub(crate) enum Error {
UartParity,
UartFraming,
UartBreak,
Timeout,
FsInvMagic,
FsNoRoot,
FsInvPath,
FsNoFile,
FsOffset,
FsInvState,
FsRead,
CpioNoFile,
ElfTruncatedObj,
ElfParseObject,
ElfParseHeader,
Expand Down Expand Up @@ -57,11 +60,14 @@ impl Error {
Self::UartParity => "UART parity error",
Self::UartFraming => "UART framing error",
Self::UartBreak => "UART BREAK",
Self::Timeout => "Timeout",
Self::FsNoRoot => "No file system currently mounted",
Self::FsInvMagic => "FFS: Bad magic number in superblock",
Self::FsInvPath => "Invalid path",
Self::FsNoFile => "No such file or directory",
Self::FsOffset => "Invalid file offset (exceeds maximum)",
Self::FsRead => "Read error",
Self::CpioNoFile => "File not found in archive",
Self::FsInvState => "Invalid UFS filesystem state",
Self::ElfTruncatedObj => "ELF: Object truncated",
Self::ElfParseObject => "ELF: Failed to parse object",
Expand Down
36 changes: 35 additions & 1 deletion src/uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,8 @@ impl Uart {

pub fn try_getb(&mut self) -> Result<u8> {
while {
let lsr = unsafe { ptr::read_volatile(&self.read_mmio_mut().lsr) };
let lsr: Lsr =
unsafe { ptr::read_volatile(&self.read_mmio_mut().lsr) };
if lsr.break_intr() {
return Err(Error::UartBreak);
}
Expand All @@ -507,6 +508,39 @@ impl Uart {
Ok(data.data())
}

pub fn try_getb_timeout(
&mut self,
timeout: core::time::Duration,
) -> Result<u8> {
use crate::clock;
let ns = timeout.as_nanos();
let cycles = ns * clock::frequency() / clock::NANOS_PER_SEC;
let start = u128::from(clock::rdtsc());
let end = u64::try_from(start.checked_add(cycles).unwrap()).unwrap();
while clock::rdtsc() < end {
let lsr = unsafe { ptr::read_volatile(&self.read_mmio_mut().lsr) };
if lsr.break_intr() {
return Err(Error::UartBreak);
}
if lsr.overrun_err() {
return Err(Error::UartFifoOverrun);
}
if lsr.framing_err() {
return Err(Error::UartFraming);
}
if lsr.parity_err() {
return Err(Error::UartParity);
}
if !lsr.data_ready() {
hint::spin_loop();
continue;
}
let data = unsafe { ptr::read_volatile(&self.read_mmio_mut().rbr) };
return Ok(data.data());
}
Err(Error::Timeout)
}

pub fn getb(&mut self) -> u8 {
loop {
if let Ok(b) = self.try_getb() {
Expand Down
14 changes: 8 additions & 6 deletions src/ufs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,15 @@ const_assert!(core::mem::size_of::<SuperBlock>() <= SUPER_BLOCK_SIZE);

impl SuperBlock {
/// Returns the superblock, as "read" from the given "disk."
pub fn read(disk: &[u8]) -> SuperBlock {
pub fn read(disk: &[u8]) -> Result<SuperBlock> {
let sbb =
&disk[SUPER_BLOCK_OFFSET..SUPER_BLOCK_OFFSET + SUPER_BLOCK_SIZE];
let p = sbb.as_ptr().cast::<SuperBlock>();
let sb = unsafe { ptr::read_unaligned(p) };
assert_eq!(sb.magic, MAGIC);
sb
if sb.magic != MAGIC {
return Err(Error::FsInvMagic);
}
Ok(sb)
}

/// Returns the block address of the given cylinder group, as
Expand Down Expand Up @@ -432,9 +434,9 @@ pub struct FileSystem<'a> {
}

impl<'a> FileSystem<'a> {
pub fn new(sd: &'a [u8]) -> FileSystem<'a> {
let sb = SuperBlock::read(sd);
FileSystem { sd, sb }
pub fn new(sd: &'a [u8]) -> Result<FileSystem<'a>> {
let sb = SuperBlock::read(sd)?;
Ok(FileSystem { sd, sb })
}

pub fn root_inode(&self) -> Inode {
Expand Down