Skip to content

Commit

Permalink
[feat] replace deprecated sbi_rt legacy console operations in riscv (#…
Browse files Browse the repository at this point in the history
…195)

* [feat] replace deprecated sbi_rt legacy console operations in riscv platform

* [refactor] use ax_console_read_bytes to replace ax_console_read_byte

* [fix] do not expose putchar and getchar, set MAX_READ_SIZE in riscv console read

* [fix] set MAX_RW_SIZE in riscv console read and write

* [fix] use while in riscv console write_bytes

* [feat] add try_write_bytes in riscv console
  • Loading branch information
hky1999 authored Oct 29, 2024
1 parent f03dcbb commit cfe25df
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 37 deletions.
10 changes: 8 additions & 2 deletions api/arceos_api/src/imp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@ cfg_display! {
mod stdio {
use core::fmt;

pub fn ax_console_read_byte() -> Option<u8> {
axhal::console::getchar().map(|c| if c == b'\r' { b'\n' } else { c })
pub fn ax_console_read_bytes(buf: &mut [u8]) -> crate::AxResult<usize> {
let len = axhal::console::read_bytes(buf);
for c in &mut buf[..len] {
if *c == b'\r' {
*c = b'\n';
}
}
Ok(len)
}

pub fn ax_console_write_bytes(buf: &[u8]) -> crate::AxResult<usize> {
Expand Down
4 changes: 2 additions & 2 deletions api/arceos_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ pub mod mem {
pub mod stdio {
use core::fmt;
define_api! {
/// Reads a byte from the console, or returns [`None`] if no input is available.
pub fn ax_console_read_byte() -> Option<u8>;
/// Reads a slice of bytes from the console, returns the number of bytes written.
pub fn ax_console_read_bytes(buf: &mut [u8]) -> crate::AxResult<usize>;
/// Writes a slice of bytes to the console, returns the number of bytes written.
pub fn ax_console_write_bytes(buf: &[u8]) -> crate::AxResult<usize>;
/// Writes a formatted string to the console.
Expand Down
17 changes: 11 additions & 6 deletions api/arceos_posix_api/src/imp/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ use axsync::Mutex;
#[cfg(feature = "fd")]
use {alloc::sync::Arc, axerrno::LinuxError, axerrno::LinuxResult, axio::PollState};

fn console_read_bytes() -> Option<u8> {
axhal::console::getchar().map(|c| if c == b'\r' { b'\n' } else { c })
fn console_read_bytes(buf: &mut [u8]) -> AxResult<usize> {
let len = axhal::console::read_bytes(buf);
for c in &mut buf[..len] {
if *c == b'\r' {
*c = b'\n';
}
}
Ok(len)
}

fn console_write_bytes(buf: &[u8]) -> AxResult<usize> {
Expand All @@ -22,12 +28,11 @@ impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> AxResult<usize> {
let mut read_len = 0;
while read_len < buf.len() {
if let Some(c) = console_read_bytes() {
buf[read_len] = c;
read_len += 1;
} else {
let len = console_read_bytes(buf[read_len..].as_mut())?;
if len == 0 {
break;
}
read_len += len;
}
Ok(read_len)
}
Expand Down
7 changes: 0 additions & 7 deletions modules/axhal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,6 @@ pub mod paging;
/// Console input and output.
pub mod console {
pub use super::platform::console::*;

/// Write a slice of bytes to the console.
pub fn write_bytes(bytes: &[u8]) {
for c in bytes {
putchar(*c);
}
}
}

/// Miscellaneous operation, e.g. terminate the system.
Expand Down
24 changes: 23 additions & 1 deletion modules/axhal/src/platform/aarch64_bsta1000b/dw_apb_uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,32 @@ pub fn putchar(c: u8) {
}

/// Reads a byte from the console, or returns [`None`] if no input is available.
pub fn getchar() -> Option<u8> {
fn getchar() -> Option<u8> {
UART.lock().getchar()
}

/// Write a slice of bytes to the console.
pub fn write_bytes(bytes: &[u8]) {
for c in bytes {
putchar(*c);
}
}

/// Reads bytes from the console into the given mutable slice.
/// Returns the number of bytes read.
pub fn read_bytes(bytes: &mut [u8]) -> usize {
let mut read_len = 0;
while read_len < bytes.len() {
if let Some(c) = getchar() {
bytes[read_len] = c;
} else {
break;
}
read_len += 1;
}
read_len
}

/// UART simply initialize
pub fn init_early() {
UART.lock().init();
Expand Down
24 changes: 23 additions & 1 deletion modules/axhal/src/platform/aarch64_common/pl011.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,32 @@ pub fn putchar(c: u8) {
}

/// Reads a byte from the console, or returns [`None`] if no input is available.
pub fn getchar() -> Option<u8> {
fn getchar() -> Option<u8> {
UART.lock().getchar()
}

/// Write a slice of bytes to the console.
pub fn write_bytes(bytes: &[u8]) {
for c in bytes {
putchar(*c);
}
}

/// Reads bytes from the console into the given mutable slice.
/// Returns the number of bytes read.
pub fn read_bytes(bytes: &mut [u8]) -> usize {
let mut read_len = 0;
while read_len < bytes.len() {
if let Some(c) = getchar() {
bytes[read_len] = c;
} else {
break;
}
read_len += 1;
}
read_len
}

/// Initialize the UART
pub fn init_early() {
UART.lock().init();
Expand Down
9 changes: 5 additions & 4 deletions modules/axhal/src/platform/dummy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
#![allow(dead_code)]

pub mod console {
/// Writes a byte to the console.
pub fn putchar(c: u8) {
/// Writes bytes to the console from input u8 slice.
pub fn write_bytes(_bytes: &[u8]) {
unimplemented!()
}

/// Reads a byte from the console, or returns [`None`] if no input is available.
pub fn getchar() -> Option<u8> {
/// Reads bytes from the console into the given mutable slice.
/// Returns the number of bytes read.
pub fn read_bytes(_bytes: &mut [u8]) -> usize {
unimplemented!()
}
}
Expand Down
49 changes: 41 additions & 8 deletions modules/axhal/src/platform/riscv64_qemu_virt/console.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,47 @@
use memory_addr::VirtAddr;

use crate::mem::virt_to_phys;

/// The maximum number of bytes that can be read at once.
const MAX_RW_SIZE: usize = 256;

/// Writes a byte to the console.
pub fn putchar(c: u8) {
#[allow(deprecated)]
sbi_rt::legacy::console_putchar(c as usize);
sbi_rt::console_write_byte(c);
}

/// Reads a byte from the console, or returns [`None`] if no input is available.
pub fn getchar() -> Option<u8> {
#[allow(deprecated)]
match sbi_rt::legacy::console_getchar() as isize {
-1 => None,
c => Some(c as u8),
/// Tries to write bytes to the console from input u8 slice.
/// Returns the number of bytes written.
fn try_write_bytes(bytes: &[u8]) -> usize {
sbi_rt::console_write(sbi_rt::Physical::new(
// A maximum of 256 bytes can be written at a time
// to prevent SBI from disabling IRQs for too long.
bytes.len().min(MAX_RW_SIZE),
virt_to_phys(VirtAddr::from_ptr_of(bytes.as_ptr())).as_usize(),
0,
))
.value
}

/// Writes bytes to the console from input u8 slice.
pub fn write_bytes(bytes: &[u8]) {
let mut write_len = 0;
while write_len < bytes.len() {
let len = try_write_bytes(&bytes[write_len..]);
if len == 0 {
break;
}
write_len += len;
}
}

/// Reads bytes from the console into the given mutable slice.
/// Returns the number of bytes read.
pub fn read_bytes(bytes: &mut [u8]) -> usize {
sbi_rt::console_read(sbi_rt::Physical::new(
bytes.len().min(MAX_RW_SIZE),
virt_to_phys(VirtAddr::from_mut_ptr_of(bytes.as_mut_ptr())).as_usize(),
0,
))
.value
}
26 changes: 24 additions & 2 deletions modules/axhal/src/platform/x86_pc/uart16550.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Uart16550 {
}

/// Writes a byte to the console.
pub fn putchar(c: u8) {
fn putchar(c: u8) {
let mut uart = COM1.lock();
match c {
b'\n' => {
Expand All @@ -96,10 +96,32 @@ pub fn putchar(c: u8) {
}

/// Reads a byte from the console, or returns [`None`] if no input is available.
pub fn getchar() -> Option<u8> {
fn getchar() -> Option<u8> {
COM1.lock().getchar()
}

/// Write a slice of bytes to the console.
pub fn write_bytes(bytes: &[u8]) {
for c in bytes {
putchar(*c);
}
}

/// Reads bytes from the console into the given mutable slice.
/// Returns the number of bytes read.
pub fn read_bytes(bytes: &mut [u8]) -> usize {
let mut read_len = 0;
while read_len < bytes.len() {
if let Some(c) = getchar() {
bytes[read_len] = c;
} else {
break;
}
read_len += 1;
}
read_len
}

pub(super) fn init() {
COM1.lock().init(115200);
}
7 changes: 3 additions & 4 deletions ulib/axstd/src/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut read_len = 0;
while read_len < buf.len() {
if let Some(c) = arceos_api::stdio::ax_console_read_byte() {
buf[read_len] = c;
read_len += 1;
} else {
let len = arceos_api::stdio::ax_console_read_bytes(buf[read_len..].as_mut())?;
if len == 0 {
break;
}
read_len += len;
}
Ok(read_len)
}
Expand Down

0 comments on commit cfe25df

Please sign in to comment.