Int1589 switches into protected mode for the caller.
Also, consistently use BUILD_BIOS_ADDR/SIZE in GDT macros.
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
// 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)
#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);
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)
__enable_hwirq(irq, func); \
} while (0)
+void set_pics(u8 irq0, u8 irq8);
void pic_setup(void);
#endif // pic.h
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)
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)
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;