aboutsummaryrefslogtreecommitdiff
path: root/external/memboot
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2014-11-14 11:49:07 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-11-14 12:28:31 +1100
commit0ee497d3db5a48252fc3ac4c748de277c7c592a8 (patch)
tree03f98287831585c4677952b09fddcd3c478c9721 /external/memboot
parenta05118a3f2d7d775cfc1f27d0cc53a4d7aba710c (diff)
downloadskiboot-0ee497d3db5a48252fc3ac4c748de277c7c592a8.zip
skiboot-0ee497d3db5a48252fc3ac4c748de277c7c592a8.tar.gz
skiboot-0ee497d3db5a48252fc3ac4c748de277c7c592a8.tar.bz2
external: Add the memboot utility
The memboot tool is a small utility designed to be run on the ASPEED BMC used in some OpenPower systems. It allows you to boot the P8 host from the main system memory of the BMC rather than from the flash memory. Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'external/memboot')
-rw-r--r--external/memboot/Makefile14
-rw-r--r--external/memboot/README24
-rw-r--r--external/memboot/memboot.c133
3 files changed, 171 insertions, 0 deletions
diff --git a/external/memboot/Makefile b/external/memboot/Makefile
new file mode 100644
index 0000000..9b526a3
--- /dev/null
+++ b/external/memboot/Makefile
@@ -0,0 +1,14 @@
+all: memboot
+
+CFLAGS=-O2 -Wall
+
+memboot: memboot.c
+ $(CC) $(CFLAGS) -o $@ $^
+
+.PHONY: clean
+clean:
+ rm -rf memboot
+
+.PHONY: distclean
+distclean: clean
+ rm -rf *.c~ *.h~ *.i *.s Makefile~
diff --git a/external/memboot/README b/external/memboot/README
new file mode 100644
index 0000000..20158ed
--- /dev/null
+++ b/external/memboot/README
@@ -0,0 +1,24 @@
+memboot
+=======
+
+This is a small utility designed to be run on the ASPEED BMC used in
+some OpenPower systems. It allows you to boot the P8 host from the
+main system memory of the BMC rather than from the flash memory.
+
+This is mainly useful for firmware development as it makes it possible
+to try new firmware images without first having to write the new image
+to flash memory which can be a lengthy process.
+
+Building:
+---------
+
+CC=<arm toolchain> make
+
+Usage:
+-----
+
+./memboot <flash image> - Will cause the P8 host to boot from BMC
+ system memory at next power on.
+
+./memboot - Will boot the system from flash memory at next
+ power on.
diff --git a/external/memboot/memboot.c b/external/memboot/memboot.c
new file mode 100644
index 0000000..fa42ea9
--- /dev/null
+++ b/external/memboot/memboot.c
@@ -0,0 +1,133 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+/* Where to put the firmware image if booting from memory */
+#define MEM_IMG_BASE (0x5c000000)
+
+/* Start of flash memory if booting from flash */
+#define FLASH_IMG_BASE (0x30000000)
+
+/* LPC registers */
+#define LPC_BASE 0x1e789000
+#define LPC_HICR6 0x80
+#define LPC_HICR7 0x88
+#define LPC_HICR8 0x8c
+
+uint32_t readl(void *addr)
+{
+ asm volatile("" : : : "memory");
+ return *(volatile uint32_t *)addr;
+}
+
+void writel(uint32_t val, void *addr)
+{
+ asm volatile("" : : : "memory");
+ *(volatile uint32_t *)addr = val;
+}
+
+void copy_flash_img(int mem_fd, int flash_fd, unsigned int size)
+{
+ static void *memimg, *fwimg;
+ size_t pagesize = getpagesize();
+
+ memimg = mmap(NULL, ((size/pagesize)+1)*pagesize,
+ PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, MEM_IMG_BASE);
+ if (memimg == MAP_FAILED) {
+ perror("Unable to map image destination memory");
+ exit(1);
+ }
+
+ fwimg = mmap(NULL,size, PROT_READ, MAP_SHARED, flash_fd, 0);
+ if (fwimg == MAP_FAILED) {
+ perror("Unable to open image source memory");
+ exit(1);
+ }
+
+ /* Copy boot image */
+ memcpy(memimg, fwimg, size);
+}
+
+void boot_firmware_image(int mem_fd, char *filename)
+{
+ int fw_fd;
+ struct stat st;
+
+ fw_fd = open(filename, O_RDONLY);
+ if (fw_fd < 0) {
+ perror("Unable to open flash image\n");
+ exit(1);
+ }
+
+ if (stat(filename, &st)) {
+ perror("Unable to determine size of firmware image");
+ exit(1);
+ }
+
+ if (st.st_size > 32*1024*1024) {
+ fprintf(stderr, "Flash too large (> 32MB)");
+ exit(1);
+ }
+
+ copy_flash_img(mem_fd, fw_fd, st.st_size);
+ close(fw_fd);
+}
+
+int main(int argc, char *argv[])
+{
+ int mem_fd;
+ void *lpcreg;
+ uint32_t lpc_hicr7_val = (FLASH_IMG_BASE | 0xe00);
+
+ if (argc > 2) {
+ printf("Usage: %s <flash image>\n", argv[0]);
+ exit(1);
+ }
+
+ mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
+ if (mem_fd < 0) {
+ perror("Unable to open /dev/mem");
+ exit(1);
+ }
+
+ lpcreg = mmap(NULL, getpagesize(),
+ PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, LPC_BASE);
+ if (lpcreg == MAP_FAILED) {
+ perror("Unable to map LPC register memory");
+ exit(1);
+ }
+
+ if (argc == 2) {
+ boot_firmware_image(mem_fd, argv[1]);
+ lpc_hicr7_val = (MEM_IMG_BASE | 0xe00);
+ printf("Booting from memory after power cycle\n");
+ }
+
+ if (readl(lpcreg + LPC_HICR7) != lpc_hicr7_val) {
+ printf("Resetting LPC_HICR7 to 0x%x\n", lpc_hicr7_val);
+ writel(lpc_hicr7_val, lpcreg+LPC_HICR7);
+ }
+
+ printf("LPC_HICR7 = 0x%x\n", lpc_hicr7_val);
+ return 0;
+}