Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VGA console output implementation. #65

Merged
merged 1 commit into from
Jun 21, 2020

Conversation

barkera
Copy link
Contributor

@barkera barkera commented Jun 12, 2020

  • Add VgaWriter struct to handle text output to the VGA.
  • Add vga_logger module containing VGA text mode helper functions.
  • mirror console output to VGA.

fixes #43

Copy link
Collaborator

@ALSchwalm ALSchwalm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this! Being able to run on actual hardware (without serial) will be pretty cool

@@ -29,6 +29,7 @@ mod registers;
pub mod time;
pub mod tsc;
pub mod vcpu;
pub mod vga_logger;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I don't think I want another top level module for this. We should probably ultimately make a 'logger' module that has a 'serial_logger' and 'vga_logger' under it. But that may be too much for this PR. For now, just put it in the existing 'logger' file, I think.


pub fn write_console(s: impl AsRef<str>) {
pub fn write_console(s: &str) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change this from AsRef?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accidentally left this in here, meant to change it back to impl AsRef

pub unsafe fn raw_write_console(s: impl AsRef<str>) {
pub unsafe fn raw_write_console(s: &str) {
// mirror console output to VGA
let mut vga_writer = VGA_LOCK.lock();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the issue here is that if we panic while we hold the VGA lock, then the panic handler will try to acquire the lock again and we will deadlock

}

pub unsafe fn raw_write_vga(s: &str, x: usize, y: usize) -> (usize, usize) {
let mut x = x;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could just put the mut in the signature as mut x: usize

}

fn write_fmt(&mut self, args: fmt::Arguments) -> Result<(), fmt::Error> {
let ret = fmt::write(self, args);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can just be fmt::write(self, args) (rather than storing then returning ret)

let mut y = y;

for byte in s.bytes() {
// move cursor on newlines (0x0A) and carriage-returns (0x0D)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the expected behavior? That newline does a newline and carriage return, while carriage return just goes to the start of the line? Is this from an existing implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the rust toolchain uses linux-style line returns for writeln!, we need to both do a newline and a carriage return so that the lines don't start going off diagonally on the screen. I've added in the check for just carriage returns as well just in case this was built on windows or if a log statement used a carriage return for something like a loading bar.

const VGA_HEIGHT: usize = 25;
const VGA_ATTRIB: u16 = 0x0F00; // black background, white text

fn get_vga_addr(x: usize, y: usize) -> usize {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than doing this, I think we should probably have the writer store a &[[u16; VGA_WIDTH]; VGA_HEIGHT] (I may have that backwards). And index in to that. Then we just need to do one unsafe conversion from 0xB8000 to that array ref, rather than using raw pointers everywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to create a direct reference in the VgaWriter struct itself due to this issue: rust-lang/rust#57349

Instead, i've made it so that the only raw pointer deref occurs in the write method which then passes the reference to the vga functions.

@barkera barkera force-pushed the vga_output branch 2 times, most recently from 6f0b037 to 93aa009 Compare June 16, 2020 00:45
- Add VgaWriter struct to handle text output to the VGA text buffer.
- Add raw_write_vga function and support functions for writing directly to the VGA text buffer.
- Add VGA_WRITER static variable to logger module for handling outputting logs to the vGA text buffer.
@ALSchwalm
Copy link
Collaborator

Sorry for the slow review of this. Looks good to me, thanks!

@ALSchwalm ALSchwalm merged commit a1c9bd6 into mythril-hypervisor:master Jun 21, 2020
@barkera barkera deleted the vga_output branch July 22, 2020 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support VGA text mode output
2 participants