import uloader-2.4.17
authorDobrica Pavlinusic <dpavlin@brr.lan>
Wed, 25 Jul 2007 08:10:12 +0000 (03:10 -0500)
committerDobrica Pavlinusic <dpavlin@brr.lan>
Wed, 25 Jul 2007 08:10:12 +0000 (03:10 -0500)
Makefile [new file with mode: 0644]
README.loader [new file with mode: 0644]
u-boot-load-hd.sh [new file with mode: 0755]
uloader.o [new file with mode: 0644]
uloader_boot.S [new file with mode: 0644]
uloader_mod.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e2317de
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,42 @@
+# Makefile for uloader.o
+#
+# Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+# Based on:
+#   Makefile for loader.o by Chih-Chung Chang <jochang@gmail.com>
+#   CFLAGS taken from linux-2.4.17_mvl21-sandpoint
+#
+# To compile this module you will need a fully configured kernel
+# 2.4.17_mvl21-sandpoint and gcc 2.95
+
+# Change INCLUDE to match your environment
+INCLUDE = -nostdinc -I/opt/embedded/ppc/list/linux-2.4.17_mvl21-sandpoint.ref/include -I/opt/embedded/ppc/list/linux-2.4.17_mvl21-sandpoint.ref/arch/ppc -I/opt/embedded/ppc/toolchain/usr/lib/gcc-lib/powerpc-linux/2.95.3/include
+
+CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -fsigned-char -msoft-float -pipe -ffixed-r2 -Wno-uninitialized -mmultiple -mstring -DMODULE
+
+CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
+
+uloader.o: uloader_mod.o uloader_boot.o
+       $(LD) -r uloader_mod.o uloader_boot.o -o uloader.o
+uloader_mod.o: uloader_mod.c
+       $(CC) -c $(INCLUDE) $(CFLAGS) uloader_mod.c
+uloader_boot.o: uloader_boot.S
+       $(CC) -c -mregnames uloader_boot.S
+clean:
+       rm -f uloader.o uloader_mod.o uloader_boot.o
diff --git a/README.loader b/README.loader
new file mode 100644 (file)
index 0000000..9d6e6de
--- /dev/null
@@ -0,0 +1,76 @@
+* Introduction
+
+Here is a small kernel module for booting new kernels on Kuro Box without 
+flashing. It loads a new kernel into memory and jumps to it directly.
+
+You need kernel header files to build the module.
+I put the kernel source came with my Kuro Box in
+
+http://jan.csie.ntu.edu.tw/~jo/kuro/CD2/linux-2.4.17_kuro-box.tar.gz
+
+You also need a configuration file to build the kernel,
+I use the one in
+
+ftp://linkstation.yi.org/pub/linkstation/kernel/config_kurobox.040630
+
+* Building the new kernel
+
+cd /usr/src
+tar xzvf ~/linux-2.4.17_kuro-box.tar.gz
+cd linux-2.4.17_kuro-box
+cp ~/config_kurobox.040630 .config
+make oldconfig
+make dep
+make
+# the loader need the kernel to be in binary format
+objcopy -O binary vmlinux                    
+
+* Building the loader module
+
+tar xzvf loader.tar.gz
+cd loader
+# change Makefile for your kernel source directory
+make
+
+* Loading the new kernel
+
+sync;insmod loader.o kernel=/usr/src/linux-2.4.17_kuro-box/vmlinux
+
+About one minute later or so, you can again telnet in your kuro box
+and verify it is running the new kernel by typing "uname -a".
+
+There are three parameters for this module:
+
+kernel: kernel file name (the kernel must be in binary format)
+initrd: initrd file name (it can be a gzip'ed file)
+cmdline: kernel command line
+
+For example you can use an ramdisk as your root filesystem:
+
+sync;insmod loader.o kernel=/usr/src/linux-2.4.17_kuro-box/vmlinux \
+initrd=/root/initrd.gz cmdline="root=/dev/ram0"
+
+The cmdline parameter doesn't work unless a small patch is applied
+to the kernel:
+
+--- arch/ppc/platforms/sandpoint_setup.c.orig   Mon Mar 15 00:15:01 2004
++++ arch/ppc/platforms/sandpoint_setup.c        Sun Jan  9 20:54:55 2005
+@@ -666,6 +666,12 @@
+        }
+ #endif
++    if ( r6 )
++    {
++        *(char *)(r7+KERNELBASE) = 0;
++        strcpy(cmd_line, (char *)(r6+KERNELBASE));
++    }
++
+ #ifdef NAS_DEBUG
+        printk("initrd_start: %08X\n",initrd_start);
+        printk("initrd_end: %08X\n",initrd_end);
+
+--
+Chih-Chung Chang <jochang@gmail.com>
+
+P.S. This module works for me most of the time, but sometimes it
+just crashes. I'd be glad to hear if you have any idea why :)
diff --git a/u-boot-load-hd.sh b/u-boot-load-hd.sh
new file mode 100755 (executable)
index 0000000..c544503
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+sync;sync;insmod /mnt/share/uloader.o uboot=/mnt/share/u-boot-hd.ram.bin
+init 6
diff --git a/uloader.o b/uloader.o
new file mode 100644 (file)
index 0000000..456d186
Binary files /dev/null and b/uloader.o differ
diff --git a/uloader_boot.S b/uloader_boot.S
new file mode 100644 (file)
index 0000000..538bb63
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * uloader_boot.S
+ *
+ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on: arch/ppc/boot/sandpoint/head.S
+ *           arch/ppc/kernel/head.S
+ *           http://www-106.ibm.com/developerworks/library/pa-ppccache.html
+ */
+
+#define HID0        0x3F0       /* Hardware Implementation Register 0 */
+#define HID0_ICE    (1<<15)     /* Instruction Cache Enable */
+#define HID0_DCE    (1<<14)     /* Data Cache Enable */
+
+.section ".text"
+.globl load_uboot
+
+load_uboot:
+        /* save parameters */
+        mr      r31,r3  /* pa_load_uboot */
+        mr      r30,r4  /* pa_uboot_buf */
+        mr      r29,r5  /* load_address */
+
+        /* disable interrupts */
+        mfmsr   r0
+        rlwinm  r0,r0,0,17,15   /* clear MSR_EE in r0 */
+        sync
+        mtmsr   r0
+        sync
+
+        /* disable cache */
+        bl      disable_cache
+
+        /* jump to after_mmu_off */
+        addi    r4,r31,after_mmu_off-load_uboot
+        li      r3,0
+        mtspr   SRR0,r4
+        mtspr   SRR1,r3
+        isync
+        sync
+        rfi
+
+after_mmu_off:
+
+        /* copy uboot image */
+        mr     r4,r29          /* load address */
+        addi    r30,r30,4       /* skip size */
+
+2:      li      r0,1024
+        lwz     r9,0(r30)
+
+        mtctr   r0
+1:      lwz     r0,0(r9)
+        addi    r9,r9,4
+        stw     r0,0(r4)
+        addi    r4,r4,4
+        bdnz    1b
+
+        addi    r30,r30,4
+        lwz     r0,0(r30)
+        cmpwi   r0,0
+        bne     2b
+
+        /* jump to uboot */
+        lis     r1,0x100        /* put stack at 16M */
+        li      r3,0
+        mr      r9,r29
+        /* u-boot entry point is u-boot base + 0x100 */
+       addi    r9,r9,0x100
+        mtlr    r9
+        blr
+
+disable_cache:
+        li      r2,1024 /* flush 16K cache */
+        mtctr   r2
+        mr      r3,r2
+        lis     r4,0xC000
+loop1:
+        lwz     r6,0(r4)
+        addi    r4,r4,16
+        bdnz    loop1
+
+        lis     r4,0xC000
+        mtctr   r3
+loop2:
+        dcbf    r0,r4
+        addi    r4,r4,16
+        bdnz    loop2
+
+        mfspr   r4,HID0
+        li      r3,0
+        ori     r3,r3,HID0_ICE|HID0_DCE
+        andc    r4,r4,r3
+        mtspr   HID0,r4
+        isync
+        blr
diff --git a/uloader_mod.c b/uloader_mod.c
new file mode 100644 (file)
index 0000000..0a9fa19
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * uloader_mod.c
+ *
+ * Loads a RAM build of u-boot and starts it
+ * The load address is hardcoded to 0x03f00000 (for LS HLAN)
+ *
+ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on:
+ *   loader_mod.c by Chih-Chung Chang <jochang@gmail.com>
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/reboot.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mihai Georgian <u-boot@linuxnotincluded.org.uk>");
+MODULE_PARM(uboot, "s");
+MODULE_PARM(laddr, "l");
+MODULE_PARM_DESC(uboot, "u-boot file name (must be binary)");
+MODULE_PARM_DESC(laddr, "u-boot load address");
+
+static char* uboot = "u-boot.bin";
+static unsigned long laddr = 0x03f00000;
+
+#define LOW_MEM 0x800000  /* no smaller than kernel + 1M (bss) + initrd */
+
+void load_uboot(unsigned long pa_load_uboot,
+                unsigned long pa_uboot_buf,
+                unsigned long laddr);
+
+struct indirect_buffer {
+  int size;
+  unsigned long paddr[1]; /* physical address of each 4K page */
+                          /* terminate with zero */
+};
+static struct indirect_buffer *uboot_buf;
+
+static int uloader_notify_reboot (struct notifier_block *this, \
+                                  unsigned long event, void *x);
+static struct notifier_block uloader_notifier = {
+  uloader_notify_reboot,
+  NULL,
+  0
+};
+
+#define MAX_INDIRECT_BUFFER_SIZE ((PAGE_SIZE/4-1)*PAGE_SIZE)
+
+/*
+ *  Allocate a page with physical address >= LOWMEM
+ */
+static void **save;
+static int saved_pages;
+static void *alloc_high_page(void)
+{
+  void *ptr;
+  if(!save)
+  {
+    save = vmalloc(((LOW_MEM+PAGE_SIZE-1)/PAGE_SIZE)*4);
+    if(!save) return 0;
+  }
+
+  while(1)
+  {
+    ptr = kmalloc(PAGE_SIZE, GFP_KERNEL);
+    if(!ptr) return 0;
+    if(__pa(ptr) >= LOW_MEM) break;
+    save[saved_pages++] = ptr;
+  }
+  return ptr;
+}
+
+static void free_saved_pages(void)
+{
+  if(save)
+  {
+    int i;
+    for(i=0;i<saved_pages;i++)
+      kfree(save[i]);
+    vfree(save);
+  }
+}
+
+static void free_ibuffer(struct indirect_buffer *ibuf);
+
+/*
+ *  Read input file into an indirect buffer
+ */
+static int read_file(char *filename, struct indirect_buffer **indirect_buf)
+{
+  struct file* file;
+  struct inode* inode;
+  struct indirect_buffer *ibuf;
+  size_t size, got, i;
+  mm_segment_t fs;
+  int err;
+
+  file = filp_open(filename, O_RDONLY, 0);
+  if(IS_ERR(file))
+    return PTR_ERR(file);
+
+  err = -EIO;
+  if(!file->f_op || !file->f_op->read)
+    goto out;
+
+  err = -EACCES;
+  inode = file->f_dentry->d_inode;
+  if(!S_ISREG(inode->i_mode))
+    goto out;
+
+  err = -ENOMEM;
+  ibuf = (struct indirect_buffer*)alloc_high_page();
+  if(!ibuf) goto out;
+  memset(ibuf, 0, PAGE_SIZE);
+
+  if(inode->i_size > MAX_INDIRECT_BUFFER_SIZE) goto out2;
+  size = (size_t)inode->i_size;
+  ibuf->size = size;
+
+  for(i=0;i<size;i+=PAGE_SIZE)
+  {
+    size_t todo = min(size-i, (size_t)PAGE_SIZE);
+    void *buf;
+
+    err = -ENOMEM;
+    buf = alloc_high_page();
+    if(!buf) goto out2;
+    ibuf->paddr[i/PAGE_SIZE] = __pa(buf);
+
+    err = -EIO;
+    file->f_pos = i;
+    fs = get_fs();
+    set_fs(KERNEL_DS);
+    got = file->f_op->read(file, buf, todo, &file->f_pos);
+    set_fs(fs);
+    if(got != todo) goto out2;
+  }
+
+  *indirect_buf = ibuf;
+  err = 0;
+
+out:
+  filp_close(file, NULL);
+  return err;
+out2:
+  free_ibuffer(ibuf);
+  goto out;
+}
+
+static void free_ibuffer(struct indirect_buffer *ibuf)
+{
+  int i;
+  for(i=0;ibuf->paddr[i];i++)
+    kfree((void *)__va(ibuf->paddr[i]));
+  kfree(ibuf);
+}
+
+/* convert vmalloc'ed memory to physical address */
+static unsigned long va2pa(void *p)
+{
+  return iopa((unsigned long)p);
+}
+
+static int uloader_notify_reboot (struct notifier_block *this, \
+                                  unsigned long event, void *x)
+{
+  switch (event) {
+    case SYS_RESTART:
+      break;
+    default:
+      return NOTIFY_DONE;
+  }
+
+  printk(KERN_INFO "uloader module booting u-boot\n");
+
+  load_uboot(va2pa(load_uboot), va2pa(uboot_buf), laddr);
+
+  return NOTIFY_DONE;  /* This should never be reached */
+}
+
+int init_module(void)
+{
+  int err;
+
+  printk(KERN_INFO "uloader module loaded\n");
+  printk(KERN_INFO "uboot=%s\n", uboot);
+
+  if((err = read_file(uboot, &uboot_buf)))
+    goto out;
+  register_reboot_notifier(&uloader_notifier);
+  return 0;
+out:
+  free_saved_pages();
+  return err;
+}
+
+void cleanup_module(void)
+{
+  printk(KERN_INFO "uloader module unloaded\n");
+}