summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2010-09-13 20:22:07 -0400
committerKevin O'Connor <kevin@koconnor.net>2010-09-15 21:43:34 -0400
commitadaf373bae943b8ab516a4e2c1ddf1e9b58cc050 (patch)
tree181ba6e7b0da156136f6e814640d0511b9be0eb1
parent402fd9cba09e1885f3ee136e279223d2bd83049a (diff)
Try to hard-reboot processor on rerun of post under coreboot.
Add several methods for rebooting a processor. Detect a rerun of POST under coreboot and attempt to reboot the processor.
-rw-r--r--src/ioport.h1
-rw-r--r--src/pci.c10
-rw-r--r--src/pci.h1
-rw-r--r--src/post.c27
-rw-r--r--src/ps2port.c16
-rw-r--r--src/ps2port.h3
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);