4 * Loads a RAM build of u-boot and starts it
5 * The load address is hardcoded to 0x03f00000 (for LS HLAN)
7 * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * loader_mod.c by Chih-Chung Chang <jochang@gmail.com>
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <asm/uaccess.h>
30 #include <linux/file.h>
32 #include <linux/vmalloc.h>
33 #include <linux/slab.h>
34 #include <linux/reboot.h>
36 MODULE_LICENSE("GPL");
37 MODULE_AUTHOR("Mihai Georgian <u-boot@linuxnotincluded.org.uk>");
38 MODULE_PARM(uboot, "s");
39 MODULE_PARM(laddr, "l");
40 MODULE_PARM_DESC(uboot, "u-boot file name (must be binary)");
41 MODULE_PARM_DESC(laddr, "u-boot load address");
43 static char* uboot = "u-boot.bin";
46 static unsigned long laddr = 0x01f00000;
48 #define LOW_MEM ( 8 * 1024 * 1024 ) /* no smaller than kernel + 1M (bss) + initrd */
49 #define MAX_INDIRECT_BUFFER_SIZE ((PAGE_SIZE/4-1)*PAGE_SIZE)
50 #define VMALLOC_SIZE ((LOW_MEM+PAGE_SIZE-1)/PAGE_SIZE)*4
52 void load_uboot(unsigned long pa_load_uboot,
53 unsigned long pa_uboot_buf,
56 struct indirect_buffer {
58 unsigned long paddr[1]; /* physical address of each 4K page */
59 /* terminate with zero */
61 static struct indirect_buffer *uboot_buf;
63 static int uloader_notify_reboot (struct notifier_block *this, \
64 unsigned long event, void *x);
65 static struct notifier_block uloader_notifier = {
66 uloader_notify_reboot,
71 #define MAX_INDIRECT_BUFFER_SIZE ((PAGE_SIZE/4-1)*PAGE_SIZE)
73 #define VMALLOC_SIZE ((LOW_MEM+PAGE_SIZE-1)/PAGE_SIZE)*4
76 * Allocate a page with physical address >= LOWMEM
79 static int saved_pages = 0;
80 static void *alloc_high_page(void)
85 save = vmalloc( VMALLOC_SIZE );
87 printk(KERN_INFO "can't vmalloc(%lu)\n", VMALLOC_SIZE );
90 //printk(KERN_INFO "vmalloc(%lu) = %08x\n", VMALLOC_SIZE, save );
96 ptr = kmalloc(PAGE_SIZE, GFP_KERNEL);
98 printk(KERN_INFO "can't kmalloc(%lu)\n", PAGE_SIZE);
101 if( __pa(ptr) >= LOW_MEM ) {
102 //printk(KERN_INFO "kmalloc(%lu) = %08x __pa: %08x >= %08x got %d pages before this\n", PAGE_SIZE, ptr, __pa(ptr), LOW_MEM, saved_pages );
105 //printk(KERN_INFO "%d: kmalloc(%lu) = %08x __pa: %08x\n", saved_pages, PAGE_SIZE, ptr, __pa(ptr) );
106 save[saved_pages++] = ptr;
108 printk(KERN_INFO "alloc_high_page %08x __pa: %08x\n", ptr, __pa(ptr) );
112 static void free_saved_pages(void)
117 for(i=0;i<saved_pages;i++)
123 static void free_ibuffer(struct indirect_buffer *ibuf);
126 * Read input file into an indirect buffer
128 static int read_file(char *filename, struct indirect_buffer **indirect_buf)
132 struct indirect_buffer *ibuf;
137 file = filp_open(filename, O_RDONLY, 0);
139 printk(KERN_INFO "can't open filename %s\n", filename);
140 return PTR_ERR(file);
144 if(!file->f_op || !file->f_op->read) {
145 printk(KERN_INFO "EIO\n");
150 inode = file->f_dentry->d_inode;
151 if(!S_ISREG(inode->i_mode)) {
152 printk(KERN_INFO "EACCES\n");
157 ibuf = (struct indirect_buffer*)alloc_high_page();
159 printk(KERN_INFO "ENOMEM\n");
162 memset(ibuf, 0, PAGE_SIZE);
164 if(inode->i_size > MAX_INDIRECT_BUFFER_SIZE) {
165 printk(KERN_INFO "## %8x > %8x\n", inode->i_size, MAX_INDIRECT_BUFFER_SIZE);
168 size = (size_t)inode->i_size;
170 printk(KERN_INFO "loading %s %d bytes\n", filename, size);
172 for(i=0;i<size;i+=PAGE_SIZE)
174 size_t todo = min(size-i, (size_t)PAGE_SIZE);
178 buf = alloc_high_page();
180 printk(KERN_INFO "can't allocate page %d\n", i);
183 ibuf->paddr[i/PAGE_SIZE] = __pa(buf);
189 got = file->f_op->read(file, buf, todo, &file->f_pos);
192 printk(KERN_INFO "for block %d got %d expected %8x\n", i, got, todo);
197 *indirect_buf = ibuf;
200 printk(KERN_INFO "loaded %s\n", filename);
202 filp_close(file, NULL);
203 printk(KERN_INFO "return code %d\n", err);
207 printk(KERN_INFO "failed loading %s\n", filename);
212 static void free_ibuffer(struct indirect_buffer *ibuf)
215 for(i=0;ibuf->paddr[i];i++)
216 kfree((void *)__va(ibuf->paddr[i]));
220 /* convert vmalloc'ed memory to physical address */
221 static unsigned long va2pa(void *p)
223 return iopa((unsigned long)p);
226 static int uloader_notify_reboot (struct notifier_block *this, \
227 unsigned long event, void *x)
236 //printk(KERN_INFO "load_uboot(%8x,%8x,%8x)\n",va2pa(load_uboot), va2pa(uboot_buf), laddr);
237 printk(KERN_INFO "A");
238 load_uboot(va2pa(load_uboot), va2pa(uboot_buf), laddr);
240 return NOTIFY_DONE; /* This should never be reached */
243 int init_module(void)
247 printk(KERN_INFO "uloader module loaded\n");
248 printk(KERN_INFO "uboot=%s<--\n", uboot);
250 if((err = read_file(uboot, &uboot_buf))) {
251 printk(KERN_INFO "Error loading %s\n", uboot);
254 register_reboot_notifier(&uloader_notifier);
261 void cleanup_module(void)
263 printk(KERN_INFO "uloader module unloaded\n");