From 2512b1bc3b2dfa61e39ecfbdb627280ac88f7cea Mon Sep 17 00:00:00 2001
From: Josh Abraham <sinisterpatrician@gmail.com>
Date: Fri, 21 Jun 2019 18:26:23 -0400
Subject: [PATCH 1/4] Add .swp files (vim tmp files) to gitignore.

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index eccd7b4a..a2f4b3c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 /target/
 **/*.rs.bk
+*.swp

From d433419486f80d8da82a9cafb2744a1791248770 Mon Sep 17 00:00:00 2001
From: Josh Abraham <sinisterpatrician@gmail.com>
Date: Sat, 22 Jun 2019 11:10:52 -0400
Subject: [PATCH 2/4] Add VESA initiation code feature (Issue #37)

---
 Cargo.toml                    |  1 +
 src/main.rs                   |  4 +++-
 src/stage_1.s                 |  1 -
 src/video_mode/vesa_800x600.s | 43 +++++++++++++++++++++++++++++++++++
 4 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 src/video_mode/vesa_800x600.s

diff --git a/Cargo.toml b/Cargo.toml
index 26c64252..b9b6624b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,6 +28,7 @@ llvm-tools = "0.1"
 [features]
 default = []
 vga_320x200 = []
+vesa_800x600 = []
 recursive_page_table = []
 map_physical_memory = []
 
diff --git a/src/main.rs b/src/main.rs
index 9d050c46..1ad9078b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -31,9 +31,11 @@ global_asm!(include_str!("stage_2.s"));
 global_asm!(include_str!("e820.s"));
 global_asm!(include_str!("stage_3.s"));
 
+#[cfg(feature = "vesa_800x600")]
+global_asm!(include_str!("video_mode/vesa_800x600.s"));
 #[cfg(feature = "vga_320x200")]
 global_asm!(include_str!("video_mode/vga_320x200.s"));
-#[cfg(not(feature = "vga_320x200"))]
+#[cfg(not(any(feature = "vesa_800x600", feature = "vga_320x200")))]
 global_asm!(include_str!("video_mode/vga_text_80x25.s"));
 
 unsafe fn context_switch(boot_info: VirtAddr, entry_point: VirtAddr, stack_pointer: VirtAddr) -> ! {
diff --git a/src/stage_1.s b/src/stage_1.s
index ebfa1a08..8296fb1c 100644
--- a/src/stage_1.s
+++ b/src/stage_1.s
@@ -35,7 +35,6 @@ enable_a20:
     out 0x92, al
 enable_a20_after:
 
-
 enter_protected_mode:
     # clear interrupts
     cli
diff --git a/src/video_mode/vesa_800x600.s b/src/video_mode/vesa_800x600.s
new file mode 100644
index 00000000..5c2730b5
--- /dev/null
+++ b/src/video_mode/vesa_800x600.s
@@ -0,0 +1,43 @@
+.section .boot, "awx"
+.intel_syntax noprefix
+.code16
+
+# This code is responsible for enabling VESA graphics while in 
+# real mode.
+config_video_mode:
+    # Try VESA
+    mov ax, 0x9000
+    mov es, ax
+    mov di, 0
+    mov ax, 0x4f00
+    int 0x10
+    cmp ax, 0x004f
+    jne vesa_out
+    # Check VESA version 2 or 3
+    mov ax, es:[di+4]
+    cmp ax, 0x0300
+    je init_vesa
+    cmp ax, 0x0200
+    jne vesa_out
+    # Hard coded 800x600x16bit mode; this gets us the PHY-addr of the FB
+init_vesa:
+    mov ax, 0x4f01
+    mov cx, 0x114
+    mov di, VESAInfo
+    int 0x10
+
+    mov ax, 0x4f02
+    mov bx, 0x4114
+    int 0x10
+
+vesa_out:
+    ret
+
+vga_println:
+    ret
+
+vga_map_frame_buffer:
+    ret
+
+VESAInfo:
+    .space 256, 0

From afce4929d8aeaeee67cb12f469bc42148f835223 Mon Sep 17 00:00:00 2001
From: Philipp Oppermann <dev@phil-opp.com>
Date: Fri, 5 Jul 2019 12:15:56 +0200
Subject: [PATCH 3/4] Map VESA framebuffer and print something

---
 src/main.rs                   |  3 ++
 src/printer/mod.rs            | 12 ++++--
 src/printer/vesa_800x600.rs   | 81 +++++++++++++++++++++++++++++++++++
 src/video_mode/vesa_800x600.s | 15 ++++++-
 4 files changed, 106 insertions(+), 5 deletions(-)
 create mode 100644 src/printer/vesa_800x600.rs

diff --git a/src/main.rs b/src/main.rs
index 1ad9078b..4687af3e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -93,6 +93,7 @@ pub unsafe extern "C" fn stage_4() -> ! {
     let bootloader_start = &__bootloader_start as *const _ as u64;
     let bootloader_end = &__bootloader_end as *const _ as u64;
 
+
     load_elf(
         IdentityMappedAddr(PhysAddr::new(kernel_start)),
         kernel_size,
@@ -292,6 +293,8 @@ fn load_elf(
 
     let entry_point = VirtAddr::new(entry_point);
 
+    panic!("Test");
+
     unsafe { context_switch(boot_info_addr, entry_point, stack_end) };
 }
 
diff --git a/src/printer/mod.rs b/src/printer/mod.rs
index b4ecd7b3..fe2f45ac 100644
--- a/src/printer/mod.rs
+++ b/src/printer/mod.rs
@@ -1,8 +1,12 @@
-#[cfg(not(feature = "vga_320x200"))]
-pub use self::vga_text_80x25::*;
-
 #[cfg(feature = "vga_320x200")]
 pub use self::vga_320x200::*;
 
-mod vga_320x200;
+#[cfg(feature = "vesa_800x600")]
+pub use self::vesa_800x600::*;
+
+#[cfg(not(any(feature = "vesa_800x600", feature = "vga_320x200")))]
+pub use self::vga_text_80x25::*;
+
 mod vga_text_80x25;
+mod vga_320x200;
+mod vesa_800x600;
diff --git a/src/printer/vesa_800x600.rs b/src/printer/vesa_800x600.rs
new file mode 100644
index 00000000..10bdb22f
--- /dev/null
+++ b/src/printer/vesa_800x600.rs
@@ -0,0 +1,81 @@
+use core::fmt::{Result, Write};
+use core::slice;
+use core::sync::atomic::{AtomicUsize, Ordering};
+
+const VGA_BUFFER: *mut u16 = (500 * 512 * 4096) as *mut _;
+const SCREEN_WIDTH: usize = 800;
+const SCREEN_HEIGHT: usize = 600;
+
+pub static X_POS: AtomicUsize = AtomicUsize::new(1); // must not be 0 so that we don't have a .bss section
+pub static Y_POS: AtomicUsize = AtomicUsize::new(1); // must not be 0 so that we don't have a .bss section
+
+pub struct Printer;
+
+impl Printer {
+    pub fn clear_screen(&mut self) {
+        let vga_buffer = Self::vga_buffer();
+        for pixel in vga_buffer {
+            *pixel = 0x66;
+        }
+        X_POS.store(0, Ordering::SeqCst);
+        Y_POS.store(0, Ordering::SeqCst);
+    }
+
+    fn vga_buffer() -> &'static mut [u16] {
+        unsafe { slice::from_raw_parts_mut(VGA_BUFFER, SCREEN_WIDTH * SCREEN_HEIGHT) }
+    }
+
+    fn newline(&mut self) {
+        let y_pos = Y_POS.fetch_add(8, Ordering::SeqCst);
+        X_POS.store(0, Ordering::SeqCst);
+        if y_pos >= SCREEN_HEIGHT {
+            self.clear_screen();
+        }
+    }
+
+    fn write_char(&mut self, c: char) {
+        use font8x8::UnicodeFonts;
+
+        if c == '\n' {
+            self.newline();
+            return;
+        }
+
+        let vga_buffer = Self::vga_buffer();
+
+        let x_pos = X_POS.fetch_add(8, Ordering::SeqCst);
+        let y_pos = Y_POS.load(Ordering::SeqCst);
+
+        match c {
+            ' '..='~' => {
+                let rendered = font8x8::BASIC_FONTS
+                    .get(c)
+                    .expect("character not found in basic font");
+                for (y, byte) in rendered.iter().enumerate() {
+                    for (x, bit) in (0..8).enumerate() {
+                        if *byte & (1 << bit) == 0 {
+                            continue;
+                        }
+                        let color = 0xff;
+                        vga_buffer[(y_pos + y) * SCREEN_WIDTH + x_pos + x] = color;
+                    }
+                }
+            }
+            _ => panic!("unprintable character"),
+        }
+
+        if x_pos + 8 >= SCREEN_WIDTH {
+            self.newline();
+        }
+    }
+}
+
+impl Write for Printer {
+    fn write_str(&mut self, s: &str) -> Result {
+        for c in s.chars() {
+            self.write_char(c);
+        }
+
+        Ok(())
+    }
+}
diff --git a/src/video_mode/vesa_800x600.s b/src/video_mode/vesa_800x600.s
index 5c2730b5..eb42e6b2 100644
--- a/src/video_mode/vesa_800x600.s
+++ b/src/video_mode/vesa_800x600.s
@@ -2,7 +2,7 @@
 .intel_syntax noprefix
 .code16
 
-# This code is responsible for enabling VESA graphics while in 
+# This code is responsible for enabling VESA graphics while in
 # real mode.
 config_video_mode:
     # Try VESA
@@ -36,7 +36,20 @@ vesa_out:
 vga_println:
     ret
 
+.code32
+
 vga_map_frame_buffer:
+    mov eax, 0xFD000000
+    or eax, (1 | 2 | (1 << 7))
+    mov ecx, 500
+vga_map_frame_buffer_loop:
+    mov [_p2 + ecx * 8], eax
+
+    add eax, 4096 * 512
+    add ecx, 1
+    cmp eax, 0xFD000000 + 800 * 600
+    jl vga_map_frame_buffer_loop
+
     ret
 
 VESAInfo:

From 8635acd2945f9c53541100dbacee5b1ce932d429 Mon Sep 17 00:00:00 2001
From: Josh Abraham <sinisterpatrician@gmail.com>
Date: Wed, 10 Jul 2019 22:31:31 -0400
Subject: [PATCH 4/4] Get VESA framebuffer address from VESA Info Block

---
 src/video_mode/vesa_800x600.s | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/video_mode/vesa_800x600.s b/src/video_mode/vesa_800x600.s
index eb42e6b2..1a7e2fb8 100644
--- a/src/video_mode/vesa_800x600.s
+++ b/src/video_mode/vesa_800x600.s
@@ -25,6 +25,7 @@ init_vesa:
     mov cx, 0x114
     mov di, VESAInfo
     int 0x10
+    mov VESAfb, [es:di+0x28]
 
     mov ax, 0x4f02
     mov bx, 0x4114
@@ -52,5 +53,8 @@ vga_map_frame_buffer_loop:
 
     ret
 
+VESAfb:
+    .word 0
+
 VESAInfo:
     .space 256, 0