summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2013-06-11 22:02:36 +0200
committerHelge Deller <deller@gmx.de>2013-06-11 22:02:36 +0200
commitfdbef9495401ef71d20d3dd628035deba881f64a (patch)
treea44d346b2261ebd5e4cd9119b258692a2d6301c8
parent570a4f2d72180f72f6637500f9aa2f20900cfb75 (diff)
downloadpalo-fdbef9495401ef71d20d3dd628035deba881f64a.tar.gz
Add boot menu option "x" to reset/reboot the machine.
This was useful for me when I booted a bootloader with an 64bit kernel, while the machine was only capable to run 32bit kernels.
-rw-r--r--ipl/bootloader.h1
-rw-r--r--ipl/ipl.c4
-rw-r--r--ipl/pdc_bootio.c2
-rw-r--r--ipl/pdc_misc.c28
4 files changed, 34 insertions, 1 deletions
diff --git a/ipl/bootloader.h b/ipl/bootloader.h
index 6df180a..1529ba8 100644
--- a/ipl/bootloader.h
+++ b/ipl/bootloader.h
@@ -38,6 +38,7 @@ int pdc_os_bits();
#define OS_64 0x1
int pdc_iodc_bootin(unsigned devaddr, char *memaddr, unsigned size);
int pdc_read_conspath(unsigned char *memaddr);
+int pdc_do_reset(void);
typedef void (*describe_t)(int fd, int *bufalign, int *blocksize);
typedef int (*read_t)(int fd, char *buf, unsigned nbytes, unsigned devaddr);
diff --git a/ipl/ipl.c b/ipl/ipl.c
index f6bc1f8..ff17fe4 100644
--- a/ipl/ipl.c
+++ b/ipl/ipl.c
@@ -331,6 +331,7 @@ interact(char *commandline, int *ok)
"'b' boot with this command line\n"
"'r' restore command line\n"
"'l' list dir\n"
+ "'x' reset and reboot machine\n"
"? ");
numbuf[0] = '0';
numbuf[1] = '\0';
@@ -356,6 +357,9 @@ interact(char *commandline, int *ok)
continue;
}
+ if (numbuf[0] == 'x')
+ pdc_do_reset();
+
editfield = parse_number(numbuf, &p);
if (editfield < argc)
diff --git a/ipl/pdc_bootio.c b/ipl/pdc_bootio.c
index 00055c6..7b6a92a 100644
--- a/ipl/pdc_bootio.c
+++ b/ipl/pdc_bootio.c
@@ -62,7 +62,7 @@ static int pdc_bootdev_read(int fd,
if ((count = pdc_iodc_bootin(devaddr, dest, nseek)) < 0)
{
die("pdc_iodc_bootin() died during seekread\r\n");
- while(1);
+ pdc_do_reset();
}
devaddr += count;
}
diff --git a/ipl/pdc_misc.c b/ipl/pdc_misc.c
index b78ef69..1d6e342 100644
--- a/ipl/pdc_misc.c
+++ b/ipl/pdc_misc.c
@@ -23,6 +23,10 @@
#define HPHW_A_DIRECT 5
#define MUX_SVERSION 0x0d
+#define F_EXTEND(x) ((unsigned long)((x) | (0xffffffff00000000ULL)))
+#define COMMAND_GLOBAL F_EXTEND(0xfffe0030)
+#define CMD_RESET 5 /* reset any module */
+
void die(const char *s)
{
puts(s);
@@ -349,3 +353,27 @@ pdc_read_conspath(unsigned char *memaddr)
}
return r; /* r < 0; error */
}
+
+static inline void gsc_writel(unsigned int val, unsigned long addr)
+{
+ __asm__ __volatile__(
+ " stwas %0,0(%1)\n"
+ : : "r" (val), "r" (addr) );
+}
+
+int
+pdc_do_reset(void)
+{
+ printf("Resetting machine.\n");
+
+ /* reset the machine - this call will most likely not return. */
+ firmware_call(mem_pdc, PDC_BROADCAST_RESET, PDC_DO_RESET);
+
+ /* Nope...box should reset with just CMD_RESET now */
+ gsc_writel(CMD_RESET, COMMAND_GLOBAL);
+
+ /* Wait for RESET to lay us to rest. */
+ while (1) /* wait */;
+
+ return -1;
+}