Add int1589 support.
authorKevin O'Connor <kevin@koconnor.net>
Tue, 5 Jan 2010 01:48:20 +0000 (20:48 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Tue, 5 Jan 2010 01:48:20 +0000 (20:48 -0500)
Int1589 switches into protected mode for the caller.
Also, consistently use BUILD_BIOS_ADDR/SIZE in GDT macros.

TODO
src/misc.c
src/pic.c
src/pic.h
src/system.c

diff --git a/TODO b/TODO
index 8411620756a5b6096a71ff71b3e1f3d2f9b1867c..07bb082e7ca7d2b5b0e165e912b866acd9c1dce5 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,19 +1,15 @@
 If POST is rerun, try to do a machine reboot.
 
-Add int 0x1589 support.
-
 Review changes committed to coreboot, virtualbox, qemu, kvm, and bochs
 cvs tip.
-  * bochs cvs (20091017):
-    -- 32bit pcibios, int1589
+  * bochs cvs (20100104):
+    -- changes synched
   * coreboot (r3348):    (bochs 20060708)
     -- no noteworthy enhancements
-  * qemu (da5ff65d):     (bochs 20090210)
-    -- changes synched
-  * kvm (e5c31442):      (bochs 20090210)
-    -- tpr patching, 16MB rom, acpi-ssdt.dsl, 4K aligned pci mem
+  * qemu - now uses SeaBIOS
+  * kvm - now uses SeaBIOS
   * virtualbox (r13560): (bochs 20061231)
-    -- lots of mouse changes, logo, scsi/etherboot hooks, int 1589,
+    -- lots of mouse changes, logo, scsi/etherboot hooks,
        floppy data rate?, int19 calls post
 
 Possibly move code from entry_post in romlayout.S to C code in
index b33ef6458c2fa993992f625991bd7df06a72fb08..354df87502486215de9cd8e4ae391b7c6b415547 100644 (file)
@@ -153,7 +153,7 @@ u64 rombios32_gdt[] VAR16VISIBLE __aligned(8) = {
     // 32 bit flat data segment (SEG32_MODE32_DS)
     GDT_LIMIT(0xfffff) | GDT_DATA | GDT_B | GDT_G,
     // 16 bit code segment base=0xf0000 limit=0xffff (SEG32_MODE16_CS)
-    GDT_LIMIT(0x0ffff) | GDT_CODE | GDT_BASE(0xf0000),
+    GDT_LIMIT(BUILD_BIOS_SIZE-1) | GDT_CODE | GDT_BASE(BUILD_BIOS_ADDR),
     // 16 bit data segment base=0x0 limit=0xffff (SEG32_MODE16_DS)
     GDT_LIMIT(0x0ffff) | GDT_DATA,
     // 16 bit code segment base=0 limit=0xffffffff (SEG32_MODE16BIG_CS)
index f421bec837569dadc4a1353161cc9ddf0317494d..8992a8b576f79292a469cb63b6bea8b96058ffd5 100644 (file)
--- a/src/pic.c
+++ b/src/pic.c
 #include "config.h" // CONFIG_*
 
 void
-pic_setup(void)
+set_pics(u8 irq0, u8 irq8)
 {
-    dprintf(3, "init pic\n");
     // Send ICW1 (select OCW1 + will send ICW4)
     outb(0x11, PORT_PIC1_CMD);
     outb(0x11, PORT_PIC2_CMD);
     // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15)
-    outb(0x08, PORT_PIC1_DATA);
-    outb(0x70, PORT_PIC2_DATA);
+    outb(irq0, PORT_PIC1_DATA);
+    outb(irq8, PORT_PIC2_DATA);
     // Send ICW3 (cascaded pic ids)
     outb(0x04, PORT_PIC1_DATA);
     outb(0x02, PORT_PIC2_DATA);
@@ -30,6 +29,13 @@ pic_setup(void)
     outb(~0, PORT_PIC2_DATA);
 }
 
+void
+pic_setup(void)
+{
+    dprintf(3, "init pic\n");
+    set_pics(0x08, 0x70);
+}
+
 // Handler for otherwise unused hardware irqs.
 void VISIBLE16
 handle_hwpic1(struct bregs *regs)
index 290fcb075b1fc01e9f931c2758fb3ccc4e94a703..586ef3831f78a04c8961232b52c627f02858252a 100644 (file)
--- a/src/pic.h
+++ b/src/pic.h
@@ -98,6 +98,7 @@ __enable_hwirq(int hwirq, void (*func)(void))
         __enable_hwirq(irq, func);              \
     } while (0)
 
+void set_pics(u8 irq0, u8 irq8);
 void pic_setup(void);
 
 #endif // pic.h
index ffcced9c3b445497565096e2a6ff5750841b9336..f72151b4b4e63c1eb9a992d0f0941206c3b4a44e 100644 (file)
@@ -111,8 +111,8 @@ handle_1587(struct bregs *regs)
     SET_FARVAR(gdt_seg, gdt_far[1], GDT_DATA | GDT_LIMIT((6*sizeof(u64))-1)
                | GDT_BASE(loc));
     // Initialize CS descriptor
-    SET_FARVAR(gdt_seg, gdt_far[4], GDT_CODE | GDT_LIMIT(0x0ffff)
-               | GDT_BASE(0xf0000));
+    SET_FARVAR(gdt_seg, gdt_far[4], GDT_CODE | GDT_LIMIT(BUILD_BIOS_SIZE-1)
+               | GDT_BASE(BUILD_BIOS_ADDR));
     // Initialize SS descriptor
     loc = (u32)MAKE_FLATPTR(GET_SEG(SS), 0);
     SET_FARVAR(gdt_seg, gdt_far[5], GDT_DATA | GDT_LIMIT(0x0ffff)
@@ -182,6 +182,47 @@ handle_1588(struct bregs *regs)
     set_success(regs);
 }
 
+// Switch to protected mode
+static void
+handle_1589(struct bregs *regs)
+{
+    set_a20(1);
+
+    set_pics(regs->bl, regs->bh);
+
+    u64 *gdt_far = (void*)(regs->si + 0);
+    u16 gdt_seg = regs->es;
+    SET_FARVAR(gdt_seg, gdt_far[7], GDT_CODE | GDT_LIMIT(BUILD_BIOS_SIZE-1)
+               | GDT_BASE(BUILD_BIOS_ADDR));
+
+    regs->ds = 3<<3; // 3rd gdt descriptor is %ds
+    regs->es = 4<<3; // 4th gdt descriptor is %es
+    regs->code.seg = 6<<3; // 6th gdt descriptor is %cs
+
+    set_code_success(regs);
+
+    asm volatile(
+        // Load new descriptor tables
+        "  lgdtw %%es:(1<<3)(%%si)\n"
+        "  lidtw %%es:(2<<3)(%%si)\n"
+
+        // Enable protected mode
+        "  movl %%cr0, %%eax\n"
+        "  orl $" __stringify(CR0_PE) ", %%eax\n"
+        "  movl %%eax, %%cr0\n"
+
+        // far jump to flush CPU queue after transition to protected mode
+        "  ljmpw $(7<<3), $1f\n"
+
+        // GDT points to valid descriptor table, now load SS
+        "1:movw $(5<<3), %%ax\n"
+        "  movw %%ax, %%ds\n"
+        "  movw %%ax, %%ss\n"
+        :
+        : "S"(gdt_far)
+        : "eax", "cc");
+}
+
 // Device busy interrupt.  Called by Int 16h when no key available
 static void
 handle_1590(struct bregs *regs)
@@ -309,6 +350,7 @@ handle_15(struct bregs *regs)
     case 0x86: handle_1586(regs); break;
     case 0x87: handle_1587(regs); break;
     case 0x88: handle_1588(regs); break;
+    case 0x89: handle_1589(regs); break;
     case 0x90: handle_1590(regs); break;
     case 0x91: handle_1591(regs); break;
     case 0xc0: handle_15c0(regs); break;