aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
+}