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 = 0x07f00000;
48 #define LOW_MEM 0x00800000 /* no smaller than kernel + 1M (bss) + initrd */
50 void load_uboot(unsigned long pa_load_uboot,
51 unsigned long pa_uboot_buf,
54 struct indirect_buffer {
56 unsigned long paddr[1]; /* physical address of each 4K page */
57 /* terminate with zero */
59 static struct indirect_buffer *uboot_buf;
61 static int uloader_notify_reboot (struct notifier_block *this, \
62 unsigned long event, void *x);
63 static struct notifier_block uloader_notifier = {
64 uloader_notify_reboot,
69 #define MAX_INDIRECT_BUFFER_SIZE ((PAGE_SIZE/4-1)*PAGE_SIZE)
71 #define VMALLOC_SIZE ((LOW_MEM+PAGE_SIZE-1)/PAGE_SIZE)*4
74 * Allocate a page with physical address >= LOWMEM
77 static int saved_pages = 0;
78 static void *alloc_high_page(void)
83 save = vmalloc( VMALLOC_SIZE );
85 printk(KERN_INFO "can't vmalloc(%x)\n", VMALLOC_SIZE );
88 printk(KERN_INFO "vmalloc(%x) = %08x\n", VMALLOC_SIZE, save );
94 ptr = kmalloc(PAGE_SIZE, GFP_KERNEL);
96 printk(KERN_INFO "can't kmalloc(%0x)\n", PAGE_SIZE);
99 if( __pa(ptr) >= LOW_MEM ) {
100 printk(KERN_INFO "kmalloc(%x) = %08x __pa: %08x >= %08x skipped\n", PAGE_SIZE, ptr, __pa(ptr), LOW_MEM );
103 printk(KERN_INFO "%d: kmalloc(%x) = %08x __pa: %08x\n", saved_pages, PAGE_SIZE, ptr, __pa(ptr) );
104 save[saved_pages++] = ptr;
106 printk(KERN_INFO "alloc_high_page %08x __pa: %08x\n", ptr, __pa(ptr) );
110 static void free_saved_pages(void)
115 for(i=0;i<saved_pages;i++)
121 static void free_ibuffer(struct indirect_buffer *ibuf);
124 * Read input file into an indirect buffer
126 static int read_file(char *filename, struct indirect_buffer **indirect_buf)
130 struct indirect_buffer *ibuf;
135 file = filp_open(filename, O_RDONLY, 0);
137 printk(KERN_INFO "can't open filename %s\n", filename);
138 return PTR_ERR(file);
140 printk(KERN_INFO "opened file %s at position %x", filename, file->pos);
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 printk(KERN_DEBUG "KERNEL_DS\n");
190 got = file->f_op->read(file, buf, todo, &file->f_pos);
192 printk(KERN_DEBUG "fs\n");
194 printk(KERN_INFO "for block %d got %d expected %8x\n", i, got, todo);
199 *indirect_buf = ibuf;
202 printk(KERN_INFO "loaded %s\n", filename);
204 filp_close(file, NULL);
205 printk(KERN_INFO "return code %d\n", err);
208 printk(KERN_INFO "failed loading %s\n", filename);
213 static void free_ibuffer(struct indirect_buffer *ibuf)
216 for(i=0;ibuf->paddr[i];i++)
217 kfree((void *)__va(ibuf->paddr[i]));
221 /* convert vmalloc'ed memory to physical address */
222 static unsigned long va2pa(void *p)
224 return iopa((unsigned long)p);
227 static int uloader_notify_reboot (struct notifier_block *this, \
228 unsigned long event, void *x)
237 printk(KERN_INFO "uloader module booting u-boot\n");
239 load_uboot(va2pa(load_uboot), va2pa(uboot_buf), laddr);
241 return NOTIFY_DONE; /* This should never be reached */
244 int init_module(void)
248 printk(KERN_INFO "uloader module loaded\n");
249 printk(KERN_INFO "uboot=%s<--\n", uboot);
251 if((err = read_file(uboot, &uboot_buf))) {
252 printk(KERN_INFO "Error loading %s\n", uboot);
255 register_reboot_notifier(&uloader_notifier);
262 void cleanup_module(void)
264 printk(KERN_INFO "uloader module unloaded\n");