Try to hard-reboot processor on rerun of post under coreboot.
authorKevin O'Connor <kevin@koconnor.net>
Tue, 14 Sep 2010 00:22:07 +0000 (20:22 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Thu, 16 Sep 2010 01:43:34 +0000 (21:43 -0400)
Add several methods for rebooting a processor.

Detect a rerun of POST under coreboot and attempt to reboot the
processor.

src/ioport.h
src/pci.c
src/pci.h
src/post.c
src/ps2port.c
src/ps2port.h

index ba099a74835639984023ce746347ee61b6ce9c51..5bd7f28f370a7209da5d44b4e6bd077b003dba39 100644 (file)
@@ -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
index 611d0e223598715774a2e0645ad07bdd0686c6e1..115689d0cee6d94317fa39fcc4e0115f69ea0f80 100644 (file)
--- 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);
+}
index 9c3108c8ac93c73aec51a2c72c96f8aebd0824c8..64bd43b53774a57b611f6d019ed9a94b574c1b4c 100644 (file)
--- 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);
index 6cd94ce3cad78e6fe4305992f63f94c83f538eae..f50312ec2a2cefbe1714b07871acbc95b4cc8df8 100644 (file)
@@ -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();
 
index ccbd2f698b59210057b3be59f16d413129e8b6f3..d1e6d48ab51a10a183a4dce6b610c2cc588ceb03 100644 (file)
@@ -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.
index afb0e786bbfa4fdcccd2071478e6e46d99bf0771..dcae391044fc1a9627cca1b6ac010d293c189870 100644 (file)
@@ -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);