no more warnings!
This commit is contained in:
parent
e48c3fc680
commit
15a7f53bc2
19 changed files with 88 additions and 314 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use super::{check_signature, ACPISDTHeader};
|
||||
use core::mem;
|
||||
use io::{Io, Pio};
|
||||
use x86::devices::io::{Io, Pio};
|
||||
|
||||
static mut DSDT: DSDT = DSDT {
|
||||
valid: false,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use super::{ACPISDTHeader, ACPISDTIter};
|
||||
use io::{Io, Pio};
|
||||
use x86::devices::io::{Io, Pio};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
use arch::x86::paging::ActivePageTable;
|
||||
|
||||
pub static mut LOCAL_APIC: LocalApic = LocalApic {
|
||||
address: 0,
|
||||
x2: false,
|
||||
};
|
||||
|
||||
pub unsafe fn init(active_table: &mut ActivePageTable) {
|
||||
LOCAL_APIC.init(active_table);
|
||||
}
|
||||
|
||||
pub struct LocalApic {
|
||||
pub address: usize,
|
||||
pub x2: bool,
|
||||
}
|
||||
|
||||
impl LocalApic {
|
||||
unsafe fn init(&mut self, _active_table: &mut ActivePageTable) {
|
||||
// ???
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
use arch::x86::paging::ActivePageTable;
|
||||
pub mod pic;
|
||||
pub mod local_apic;
|
||||
use x86::devices::pit;
|
||||
use x86::devices::pic;
|
||||
pub mod cpu;
|
||||
|
||||
pub unsafe fn init(active_table: &mut ActivePageTable) {
|
||||
pub unsafe fn init() {
|
||||
pic::init();
|
||||
// local_apic::init(active_table);
|
||||
pit::init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
use io::{Io, Pio};
|
||||
|
||||
pub static mut MASTER: Pic = Pic::new(0x20);
|
||||
pub static mut SLAVE: Pic = Pic::new(0xA0);
|
||||
pub static mut WAIT_PORT: Pio<u8> = Pio::new(0x80);
|
||||
|
||||
pub unsafe fn init() {
|
||||
let wait = || WAIT_PORT.write(0);
|
||||
let master_mask = MASTER.data.read();
|
||||
let slave_mask = SLAVE.data.read();
|
||||
|
||||
// Start initialization
|
||||
MASTER.cmd.write(0x11);
|
||||
wait();
|
||||
SLAVE.cmd.write(0x11);
|
||||
wait();
|
||||
|
||||
// Set offsets
|
||||
MASTER.data.write(0x20);
|
||||
wait();
|
||||
SLAVE.data.write(0x28);
|
||||
wait();
|
||||
|
||||
// Set up cascade
|
||||
MASTER.data.write(4);
|
||||
wait();
|
||||
SLAVE.data.write(2);
|
||||
wait();
|
||||
|
||||
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
|
||||
MASTER.data.write(1);
|
||||
wait();
|
||||
SLAVE.data.write(1);
|
||||
wait();
|
||||
|
||||
// Unmask interrupts
|
||||
MASTER.data.write(0);
|
||||
wait();
|
||||
SLAVE.data.write(0);
|
||||
wait();
|
||||
|
||||
// Ack remaining interrupts
|
||||
MASTER.ack();
|
||||
wait();
|
||||
SLAVE.ack();
|
||||
wait();
|
||||
|
||||
MASTER.data.write(master_mask);
|
||||
wait();
|
||||
SLAVE.data.write(slave_mask);
|
||||
wait();
|
||||
|
||||
// disable all irqs
|
||||
MASTER.data.write(!0);
|
||||
wait();
|
||||
SLAVE.data.write(!0);
|
||||
wait();
|
||||
|
||||
// keyboard active
|
||||
MASTER.mask_clear(1);
|
||||
wait();
|
||||
|
||||
// asm!("sti");
|
||||
::x86::instructions::interrupts::enable();
|
||||
}
|
||||
|
||||
pub struct Pic {
|
||||
cmd: Pio<u8>,
|
||||
data: Pio<u8>,
|
||||
}
|
||||
|
||||
impl Pic {
|
||||
pub const fn new(port: u16) -> Pic {
|
||||
Pic {
|
||||
cmd: Pio::new(port),
|
||||
data: Pio::new(port + 1),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ack(&mut self) {
|
||||
self.cmd.write(0x20);
|
||||
}
|
||||
|
||||
pub fn mask_set(&mut self, irq: u8) {
|
||||
assert!(irq < 8);
|
||||
|
||||
let mut mask = self.data.read();
|
||||
mask |= 1 << irq;
|
||||
self.data.write(mask);
|
||||
}
|
||||
|
||||
pub fn mask_clear(&mut self, irq: u8) {
|
||||
assert!(irq < 8);
|
||||
|
||||
let mut mask = self.data.read();
|
||||
mask &= !(1 << irq);
|
||||
self.data.write(mask);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
use x86::structures::gdt;
|
||||
use x86::structures::tss;
|
||||
use x86::structures::gdt::{Descriptor, SegmentSelector};
|
||||
use x86::structures::gdt::SegmentSelector;
|
||||
use x86::instructions::segmentation::*;
|
||||
use x86::instructions::tables::load_tss;
|
||||
use x86::PrivilegeLevel::{Ring0, Ring3};
|
||||
use x86::*;
|
||||
|
||||
pub static mut GDT: gdt::Gdt = gdt::Gdt::new();
|
||||
pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new();
|
||||
|
|
@ -42,6 +41,7 @@ pub unsafe fn init() {
|
|||
assert_eq!(tss_selector, GDT_TSS);
|
||||
assert_eq!(task_tss_selector, GDT_TASK_TSS);
|
||||
|
||||
// use x86::structures::gdt::Descriptor;
|
||||
// println!(
|
||||
// "tr({:#x}):\n {:#?}",
|
||||
// tss_selector.0,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use x86::structures::idt::*;
|
||||
use arch::x86::device::pic;
|
||||
use x86::devices::pic;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! interrupt {
|
||||
|
|
@ -44,7 +44,9 @@ pub unsafe fn acknowledge(irq: usize) {
|
|||
}
|
||||
}
|
||||
|
||||
interrupt!(0, pit, {});
|
||||
interrupt!(0, pit, {
|
||||
fprintln!("got pit (irq0)");
|
||||
});
|
||||
|
||||
interrupt!(1, keyboard, {
|
||||
::keyboard::kbd_callback();
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
|
|||
::allocator::init(&mut active_table);
|
||||
|
||||
// set up user stack
|
||||
use x86::structures::paging::*;
|
||||
// use x86::structures::paging::*;
|
||||
// for page in ::USER_STACK_RANGE {
|
||||
// active_table.map(page, PageTableFlags::WRITABLE);
|
||||
// }
|
||||
|
||||
// set up pic & apic
|
||||
device::init(&mut active_table);
|
||||
// set up pic, pit
|
||||
device::init();
|
||||
|
||||
// primary CPU entry point
|
||||
::kmain();
|
||||
|
|
@ -63,10 +63,10 @@ pub unsafe fn switch(ip: u32) -> ! {
|
|||
unreachable!();
|
||||
}
|
||||
|
||||
pub unsafe fn usermode(ip: u32, mut sp: u32, arg: u32) -> ! {
|
||||
use x86::structures::gdt::{Descriptor, SegmentSelector};
|
||||
use x86::instructions::segmentation::*;
|
||||
use x86::PrivilegeLevel::{Ring0, Ring3};
|
||||
pub unsafe fn usermode(ip: u32, sp: u32) -> ! {
|
||||
// use x86::structures::gdt::{Descriptor, SegmentSelector};
|
||||
// use x86::instructions::segmentation::*;
|
||||
// use x86::PrivilegeLevel::{Ring0, Ring3};
|
||||
|
||||
x86::instructions::interrupts::disable();
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ pub unsafe fn usermode(ip: u32, mut sp: u32, arg: u32) -> ! {
|
|||
use x86::registers::flags;
|
||||
flags::set_flags(flags::Flags::NT);
|
||||
|
||||
asm!("mov %esp, $0" : "=r" (sp));
|
||||
// asm!("mov %esp, $0" : "=r" (sp));
|
||||
|
||||
println!("{:#x}", gdt::GDT_KERNEL_DATA.0);
|
||||
println!("{:#x}", sp);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ extern crate core;
|
|||
|
||||
use acpi;
|
||||
use keyboard::PS2;
|
||||
use io;
|
||||
use core::char;
|
||||
use vga::*;
|
||||
|
||||
|
|
@ -57,6 +56,7 @@ fn help() -> Result<(), &'static str> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
use x86::instructions::halt;
|
||||
/// Reboot the kernel
|
||||
///
|
||||
/// If reboot failed, will loop on a halt cmd
|
||||
|
|
@ -70,7 +70,7 @@ fn reboot() -> ! {
|
|||
unsafe { PS2.ps2_8042_reset() }; // TODO unsafe
|
||||
println!("Unable to perform 8042 reboot. Kernel will be halted");
|
||||
flush!();
|
||||
io::halt();
|
||||
halt();
|
||||
}
|
||||
|
||||
/// Shutdown the kernel
|
||||
|
|
@ -84,7 +84,7 @@ fn shutdown() -> ! {
|
|||
_ => println!("Unable to perform ACPI shutdown. Kernel will be halted"),
|
||||
}
|
||||
flush!();
|
||||
io::halt();
|
||||
halt();
|
||||
}
|
||||
|
||||
fn hexdump(start: usize, end: usize) {
|
||||
|
|
@ -225,6 +225,7 @@ pub fn int3() -> Result<(), &'static str> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unconditional_recursion)]
|
||||
pub fn overflow() -> Result<(), &'static str> {
|
||||
fn stack_overflow() {
|
||||
stack_overflow();
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
mod pio;
|
||||
|
||||
pub use self::pio::*;
|
||||
|
||||
use core::ops::{BitAnd, BitOr, Not};
|
||||
|
||||
pub trait Io {
|
||||
type Value: Copy
|
||||
+ PartialEq
|
||||
+ BitAnd<Output = Self::Value>
|
||||
+ BitOr<Output = Self::Value>
|
||||
+ Not<Output = Self::Value>;
|
||||
|
||||
fn read(&self) -> Self::Value;
|
||||
fn write(&mut self, value: Self::Value);
|
||||
|
||||
#[inline(always)]
|
||||
fn readf(&self, flags: Self::Value) -> bool {
|
||||
(self.read() & flags) as Self::Value == flags
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn writef(&mut self, flags: Self::Value, value: bool) {
|
||||
let tmp: Self::Value = match value {
|
||||
true => self.read() | flags,
|
||||
false => self.read() & !flags,
|
||||
};
|
||||
self.write(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn cli() {
|
||||
unsafe { asm!("cli" : : : : "volatile") };
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn halt() -> ! {
|
||||
cli();
|
||||
loop {
|
||||
unsafe { asm!("hlt" : : : : "volatile") };
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
use core::marker::PhantomData;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Generic PIO
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Pio<T> {
|
||||
port: u16,
|
||||
value: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Pio<T> {
|
||||
/// Create a PIO from a given port
|
||||
pub const fn new(port: u16) -> Self {
|
||||
Pio::<T> {
|
||||
port: port,
|
||||
value: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read/Write for byte PIO
|
||||
impl Io for Pio<u8> {
|
||||
type Value = u8;
|
||||
|
||||
/// Read
|
||||
#[inline(always)]
|
||||
fn read(&self) -> u8 {
|
||||
let value: u8;
|
||||
unsafe {
|
||||
asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
/// Write
|
||||
#[inline(always)]
|
||||
fn write(&mut self, value: u8) {
|
||||
unsafe {
|
||||
asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read/Write for word PIO
|
||||
impl Io for Pio<u16> {
|
||||
type Value = u16;
|
||||
|
||||
/// Read
|
||||
#[inline(always)]
|
||||
fn read(&self) -> u16 {
|
||||
let value: u16;
|
||||
unsafe {
|
||||
asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
/// Write
|
||||
#[inline(always)]
|
||||
fn write(&mut self, value: u16) {
|
||||
unsafe {
|
||||
asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read/Write for doubleword PIO
|
||||
impl Io for Pio<u32> {
|
||||
type Value = u32;
|
||||
|
||||
/// Read
|
||||
#[inline(always)]
|
||||
fn read(&self) -> u32 {
|
||||
let value: u32;
|
||||
unsafe {
|
||||
asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
/// Write
|
||||
#[inline(always)]
|
||||
fn write(&mut self, value: u32) {
|
||||
unsafe {
|
||||
asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
extern crate core;
|
||||
|
||||
use vga;
|
||||
use io::{self, Io, Pio};
|
||||
use x86::devices::io::{Io, Pio};
|
||||
|
||||
const MAX_KEYS: usize = 59;
|
||||
const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [
|
||||
|
|
@ -90,7 +90,8 @@ impl Ps2 {
|
|||
}
|
||||
|
||||
pub fn ps2_8042_reset(&mut self) {
|
||||
io::cli();
|
||||
use x86::instructions::interrupts;
|
||||
interrupts::disable();
|
||||
self.clear_buffer();
|
||||
self.status.write(0xFE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ pub mod vga;
|
|||
pub mod keyboard;
|
||||
/// simplisitc kernel commands
|
||||
pub mod console;
|
||||
/// rust wrappers around cpu I/O instructions.
|
||||
pub mod io;
|
||||
/// ACPI self contained module
|
||||
pub mod acpi;
|
||||
/// Heap allocators
|
||||
|
|
@ -57,11 +55,6 @@ pub fn kmain() -> ! {
|
|||
// vga is *not* cpu specific
|
||||
vga::init();
|
||||
|
||||
// fn stack_overflow() {
|
||||
// stack_overflow();
|
||||
// }
|
||||
// stack_overflow();
|
||||
|
||||
// unsafe {
|
||||
// *(0xdead as *mut u32) = 42;
|
||||
// };
|
||||
|
|
@ -82,8 +75,7 @@ pub fn kmain() -> ! {
|
|||
// }
|
||||
// unreachable!()
|
||||
|
||||
process::ploop();
|
||||
|
||||
process::schedule();
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
mod bump;
|
||||
mod recycle;
|
||||
mod stack_allocator;
|
||||
// mod stack_allocator;
|
||||
|
||||
use multiboot2;
|
||||
use x86::structures::paging::*;
|
||||
use arch::x86::paging::ActivePageTable;
|
||||
use x86::*;
|
||||
|
||||
use self::bump::BumpFrameAllocator;
|
||||
use self::recycle::RecycleAllocator;
|
||||
use self::stack_allocator::{Stack, StackAllocator};
|
||||
// use self::stack_allocator::{Stack, StackAllocator};
|
||||
|
||||
pub trait FrameAllocator {
|
||||
fn allocate_frames(&mut self, size: usize) -> Option<PhysFrame>;
|
||||
|
|
|
|||
|
|
@ -1,24 +1,26 @@
|
|||
use spin::Mutex;
|
||||
use alloc::VecDeque;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct Fifo {
|
||||
list: VecDeque<Process>,
|
||||
next_pid: i32,
|
||||
}
|
||||
|
||||
impl Fifo {
|
||||
pub fn new() -> Fifo {
|
||||
Fifo {
|
||||
list: VecDeque::new(),
|
||||
next_pid: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Scheduler for Fifo {
|
||||
fn add_process(&mut self, ip: u32) {
|
||||
let p = Process::new(ip);
|
||||
let p = Process::new(self.next_pid, ip);
|
||||
self.list.push_back(p);
|
||||
self.next_pid += 1;
|
||||
}
|
||||
|
||||
fn next(&mut self) -> Option<Process> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
mod fifo;
|
||||
use spin::Mutex;
|
||||
|
||||
lazy_static! {
|
||||
static ref SCHEDULER: fifo::Fifo = fifo::Fifo::new();
|
||||
pub static ref SCHEDULER: Mutex<fifo::Fifo> = Mutex::new({
|
||||
let init_process: u32 = self::init as *const () as u32;
|
||||
let mut f = fifo::Fifo::new();
|
||||
f.add_process(init_process);
|
||||
f
|
||||
});
|
||||
}
|
||||
|
||||
// lazy_static! {
|
||||
|
|
@ -14,16 +20,19 @@ lazy_static! {
|
|||
pub struct Process {
|
||||
// this is eip right now
|
||||
// this will be an elf blob later
|
||||
pid: i32,
|
||||
ip: u32,
|
||||
}
|
||||
|
||||
impl Process {
|
||||
pub fn new(ip: u32) -> Process {
|
||||
Process { ip }
|
||||
pub fn new(pid: i32, ip: u32) -> Process {
|
||||
Process { pid, ip }
|
||||
}
|
||||
|
||||
pub unsafe fn execute(&mut self) {
|
||||
asm!("push $0; ret" :: "r"(self.ip) :: "volatile", "intel");
|
||||
let scheduler_loop = schedule as *const () as u32;
|
||||
asm!("push $0; push $1; ret" :: "r"(scheduler_loop) ,"r"(self.ip) :: "volatile", "intel");
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,33 +41,35 @@ pub trait Scheduler {
|
|||
fn next(&mut self) -> Option<Process>;
|
||||
}
|
||||
|
||||
pub fn ploop() {
|
||||
let ip = self::init as *const () as u32;
|
||||
unsafe {
|
||||
SCHEDULER.add_process(ip);
|
||||
}
|
||||
pub fn schedule() {
|
||||
loop {
|
||||
if let Some(mut p) = unsafe { SCHEDULER.next() } {
|
||||
print!("{:?}", p);
|
||||
if let Some(mut p) = SCHEDULER.lock().next() {
|
||||
println!("executing {:#x}", p.ip);
|
||||
flush!();
|
||||
unsafe {
|
||||
SCHEDULER.force_unlock();
|
||||
p.execute();
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fork() -> i32 {
|
||||
let ip;
|
||||
unsafe {
|
||||
asm!("" : "={eip}"(ip) ::: "volatile");
|
||||
SCHEDULER.add_process(ip);
|
||||
}
|
||||
unsafe { asm!("pop $0" : "=r"(ip) ::: "intel") };
|
||||
println!("ip = {:#x}", ip);
|
||||
flush!();
|
||||
unsafe { asm!("push $0" :: "r"(ip) :: "intel") };
|
||||
SCHEDULER.lock().add_process(ip);
|
||||
0
|
||||
}
|
||||
|
||||
pub fn init() -> ! {
|
||||
let i = self::fork();
|
||||
println!("inside fork_print() function!!!!!, fork={}", i);
|
||||
pub fn init() {
|
||||
println!("init first line");
|
||||
flush!();
|
||||
// let i = self::fork();
|
||||
// println!("fork={}", i);
|
||||
println!("init last line");
|
||||
flush!();
|
||||
loop {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// https://wiki.osdev.org/Text_Mode_Cursor
|
||||
// Protected mode cursor abstraction
|
||||
|
||||
use io::{Io, Pio};
|
||||
use x86::devices::io::{Io, Pio};
|
||||
|
||||
pub static mut CURSOR: Cursor = Cursor::new(0x3D4);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(unused_macros)]
|
||||
|
||||
pub mod color;
|
||||
pub mod cursor;
|
||||
|
||||
|
|
@ -15,19 +17,37 @@ struct ScreenChar {
|
|||
color_code: ColorCode,
|
||||
}
|
||||
|
||||
// print wrapper macro around vga
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ({
|
||||
$crate::vga::print(format_args!($($arg)*));
|
||||
});
|
||||
}
|
||||
|
||||
// flushed print
|
||||
macro_rules! fprint {
|
||||
($($arg:tt)*) => ({
|
||||
print!($($arg)*);
|
||||
flush!();
|
||||
});
|
||||
}
|
||||
|
||||
// print with a line feed
|
||||
macro_rules! println {
|
||||
($fmt:expr) => (print!(concat!($fmt, "\n")));
|
||||
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
|
||||
}
|
||||
|
||||
// flushed println
|
||||
macro_rules! fprintln {
|
||||
($($arg:tt)*) => ({
|
||||
println!($($arg)*);
|
||||
flush!();
|
||||
});
|
||||
}
|
||||
|
||||
macro_rules! flush {
|
||||
() => (unsafe { $crate::vga::VGA.flush() });
|
||||
() => (#[allow(unused_unsafe)] unsafe { $crate::vga::VGA.flush() });
|
||||
}
|
||||
|
||||
macro_rules! set_color {
|
||||
|
|
@ -125,7 +145,7 @@ impl Writer {
|
|||
self.buffer_pos -= 2;
|
||||
let i = self.buffer_pos;
|
||||
self.buffer[i] = b' ';
|
||||
self.buffer[i + 1] = 0;
|
||||
self.buffer[i + 1] = self.color_code.0;
|
||||
self.flush();
|
||||
// flush!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit d81e8a3690f3cd2dc64f0d6ebabceeb8e5583c97
|
||||
Subproject commit 0da7a6b2bfafec479a990bb0dac8f4bd58b9fd79
|
||||
Loading…
Reference in a new issue