Add several methods for rebooting a processor.
Detect a rerun of POST under coreboot and attempt to reboot the processor. --- src/ioport.h | 1 + src/pci.c | 10 ++++++++++ src/pci.h | 1 + src/post.c | 27 +++++++++++++++++++++++++++ src/ps2port.c | 16 ++++++++++++++-- src/ps2port.h | 3 +-- 6 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/src/ioport.h b/src/ioport.h index ba099a7..5bd7f28 100644 --- a/src/ioport.h +++ b/src/ioport.h @@ -50,6 +50,7 @@ #define PORT_FD_DIR 0x03f7 #define PORT_SERIAL1 0x03f8 #define PORT_PCI_CMD 0x0cf8 +#define PORT_PCI_REBOOT 0x0cf9 #define PORT_PCI_DATA 0x0cfc #define PORT_BIOS_DEBUG 0x0402 #define PORT_QEMU_CFG_CTL 0x0510 diff --git a/src/pci.c b/src/pci.c index 611d0e2..115689d 100644 --- a/src/pci.c +++ b/src/pci.c @@ -215,3 +215,13 @@ int pci_find_init_device(const struct pci_device_id *ids, void *arg) } return -1; } + +void +pci_reboot(void) +{ + u8 v = inb(PORT_PCI_REBOOT) & ~6; + outb(v|2, PORT_PCI_REBOOT); /* Request hard reset */ + udelay(50); + outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */ + udelay(50); +} diff --git a/src/pci.h b/src/pci.h index 9c3108c..64bd43b 100644 --- a/src/pci.h +++ b/src/pci.h @@ -94,6 +94,7 @@ struct pci_device_id {
int pci_init_device(const struct pci_device_id *table, u16 bdf, void *arg); int pci_find_init_device(const struct pci_device_id *ids, void *arg); +void pci_reboot(void);
// pirtable.c void create_pirtable(void); diff --git a/src/post.c b/src/post.c index 6cd94ce..f50312e 100644 --- a/src/post.c +++ b/src/post.c @@ -244,6 +244,26 @@ post(void) memmap_finalize(); }
+// Attempt to invoke a hard-reboot. +static void +tryReboot(void) +{ + dprintf(1, "Attempting a hard reboot\n"); + + // Try keyboard controller reboot. + i8042_reboot(); + + // Try PCI 0xcf9 reboot + pci_reboot(); + + // Try triple fault + asm volatile("int3"); + + panic("Could not reboot"); +} + +static int HaveRunPost; + // 32-bit entry point. void VISIBLE32FLAT _start(void) @@ -253,9 +273,16 @@ _start(void) debug_serial_setup(); dprintf(1, "Start bios (version %s)\n", VERSION);
+ if (CONFIG_COREBOOT && HaveRunPost) + // This is a soft reboot - invoke a hard reboot. + tryReboot(); + // Allow writes to modify bios area (0xf0000) make_bios_writable();
+ if (CONFIG_COREBOOT) + HaveRunPost = 1; + // Perform main setup code. post();
diff --git a/src/ps2port.c b/src/ps2port.c index ccbd2f6..d1e6d48 100644 --- a/src/ps2port.c +++ b/src/ps2port.c @@ -51,7 +51,7 @@ i8042_wait_write(void) return -1; }
-int +static int i8042_flush(void) { dprintf(7, "i8042_flush\n"); @@ -102,7 +102,7 @@ __i8042_command(int command, u8 *param) return 0; }
-int +static int i8042_command(int command, u8 *param) { dprintf(7, "i8042_command cmd=%x\n", command); @@ -128,6 +128,18 @@ i8042_aux_write(u8 c) return i8042_command(I8042_CMD_AUX_SEND, &c); }
+void +i8042_reboot(void) +{ + int i; + for (i=0; i<10; i++) { + i8042_wait_write(); + udelay(50); + outb(0xfe, PORT_PS2_STATUS); /* pulse reset low */ + udelay(50); + } +} +
/**************************************************************** * Device commands. diff --git a/src/ps2port.h b/src/ps2port.h index afb0e78..dcae391 100644 --- a/src/ps2port.h +++ b/src/ps2port.h @@ -55,8 +55,7 @@ #define I8042_CTR_XLATE 0x40
// functions -int i8042_flush(void); -int i8042_command(int command, u8 *param); +void i8042_reboot(void); int ps2_kbd_command(int command, u8 *param); int ps2_mouse_command(int command, u8 *param); void ps2port_setup(void);