| @@ -1,40 +1,52 @@ | | | @@ -1,40 +1,52 @@ |
1 | /* $NetBSD: zbsdmod.c,v 1.6 2011/05/05 09:07:59 nonaka Exp $ */ | | 1 | /* $NetBSD: zbsdmod.c,v 1.7 2011/12/11 14:05:39 nonaka Exp $ */ |
2 | /* $OpenBSD: zbsdmod.c,v 1.7 2005/05/02 02:45:29 uwe Exp $ */ | | 2 | /* $OpenBSD: zbsdmod.c,v 1.7 2005/05/02 02:45:29 uwe Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> | | 5 | * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> |
6 | * | | 6 | * |
7 | * Permission to use, copy, modify, and distribute this software for any | | 7 | * Permission to use, copy, modify, and distribute this software for any |
8 | * purpose with or without fee is hereby granted, provided that the above | | 8 | * purpose with or without fee is hereby granted, provided that the above |
9 | * copyright notice and this permission notice appear in all copies. | | 9 | * copyright notice and this permission notice appear in all copies. |
10 | * | | 10 | * |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | | 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | | 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | | 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | | 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | | 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | | 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | | 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 | */ | | 18 | */ |
19 | | | 19 | |
20 | /* | | 20 | /* |
21 | * Zaurus NetBSD bootstrap loader. | | 21 | * Zaurus NetBSD bootstrap loader. |
22 | */ | | 22 | */ |
23 | | | 23 | |
24 | #include "compat_linux.h" | | 24 | #include <sys/cdefs.h> |
| | | 25 | #define ELFSIZE 32 |
| | | 26 | #include <sys/exec_elf.h> |
| | | 27 | #include <sys/types.h> |
| | | 28 | #include <sys/errno.h> |
25 | | | 29 | |
26 | #include <machine/bootinfo.h> | | 30 | #include <machine/bootinfo.h> |
27 | | | 31 | |
| | | 32 | #include "compat_linux.h" |
| | | 33 | |
| | | 34 | /* Linux LKM support */ |
| | | 35 | const char __module_kernel_version[] __attribute__((section(".modinfo"))) = |
| | | 36 | "kernel_version=" UTS_RELEASE; |
| | | 37 | const char __module_using_checksums[] __attribute__((section(".modinfo"))) = |
| | | 38 | "using_checksums=1"; |
| | | 39 | |
28 | #define ZBOOTDEV_MAJOR 99 | | 40 | #define ZBOOTDEV_MAJOR 99 |
29 | #define ZBOOTDEV_MODE 0222 | | 41 | #define ZBOOTDEV_MODE 0222 |
30 | #define ZBOOTDEV_NAME "zboot" | | 42 | #define ZBOOTDEV_NAME "zboot" |
31 | #define ZBOOTMOD_NAME "zbsdmod" | | 43 | #define ZBOOTMOD_NAME "zbsdmod" |
32 | | | 44 | |
33 | /* Prototypes */ | | 45 | /* Prototypes */ |
34 | int init_module(void); | | 46 | int init_module(void); |
35 | void cleanup_module(void); | | 47 | void cleanup_module(void); |
36 | | | 48 | |
37 | static ssize_t zbsdmod_write(struct file *, const char *, size_t, loff_t *); | | 49 | static ssize_t zbsdmod_write(struct file *, const char *, size_t, loff_t *); |
38 | static int zbsdmod_open(struct inode *, struct file *); | | 50 | static int zbsdmod_open(struct inode *, struct file *); |
39 | static int zbsdmod_close(struct inode *, struct file *); | | 51 | static int zbsdmod_close(struct inode *, struct file *); |
40 | | | 52 | |
| @@ -47,26 +59,31 @@ static struct file_operations fops = { | | | @@ -47,26 +59,31 @@ static struct file_operations fops = { |
47 | zbsdmod_write, /* write */ | | 59 | zbsdmod_write, /* write */ |
48 | 0, /* readdir */ | | 60 | 0, /* readdir */ |
49 | 0, /* poll */ | | 61 | 0, /* poll */ |
50 | 0, /* ioctl */ | | 62 | 0, /* ioctl */ |
51 | 0, /* mmap */ | | 63 | 0, /* mmap */ |
52 | zbsdmod_open, /* open */ | | 64 | zbsdmod_open, /* open */ |
53 | 0, /* flush */ | | 65 | 0, /* flush */ |
54 | zbsdmod_close, /* release */ | | 66 | zbsdmod_close, /* release */ |
55 | 0, /* sync */ | | 67 | 0, /* sync */ |
56 | 0, /* async */ | | 68 | 0, /* async */ |
57 | 0, /* check media change */ | | 69 | 0, /* check media change */ |
58 | 0, /* revalidate */ | | 70 | 0, /* revalidate */ |
59 | 0, /* lock */ | | 71 | 0, /* lock */ |
| | | 72 | 0, /* sendpage */ |
| | | 73 | 0, /* get_unmapped_area */ |
| | | 74 | #ifdef MAGIC_ROM_PTR |
| | | 75 | 0, /* romptr */ |
| | | 76 | #endif /* MAGIC_ROM_PTR */ |
60 | }; | | 77 | }; |
61 | | | 78 | |
62 | static int isopen; | | 79 | static int isopen; |
63 | static loff_t position; | | 80 | static loff_t position; |
64 | | | 81 | |
65 | /* Outcast local variables to avoid stack usage in elf32bsdboot(). */ | | 82 | /* Outcast local variables to avoid stack usage in elf32bsdboot(). */ |
66 | static int cpsr; | | 83 | static int cpsr; |
67 | static unsigned int sz; | | 84 | static unsigned int sz; |
68 | static int i; | | 85 | static int i; |
69 | static vaddr_t minv, maxv, posv; | | 86 | static vaddr_t minv, maxv, posv; |
70 | static vaddr_t elfv, shpv; | | 87 | static vaddr_t elfv, shpv; |
71 | static int *addr; | | 88 | static int *addr; |
72 | static vaddr_t *esymp; | | 89 | static vaddr_t *esymp; |
| @@ -98,27 +115,27 @@ elf32bsdboot(void) | | | @@ -98,27 +115,27 @@ elf32bsdboot(void) |
98 | posv = (vaddr_t)0; | | 115 | posv = (vaddr_t)0; |
99 | esymp = 0; | | 116 | esymp = 0; |
100 | | | 117 | |
101 | /* | | 118 | /* |
102 | * Get min and max addresses used by the loaded kernel. | | 119 | * Get min and max addresses used by the loaded kernel. |
103 | */ | | 120 | */ |
104 | for (i = 0; i < elf->e_phnum; i++) { | | 121 | for (i = 0; i < elf->e_phnum; i++) { |
105 | | | 122 | |
106 | if (phdr[i].p_type != PT_LOAD || | | 123 | if (phdr[i].p_type != PT_LOAD || |
107 | (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0) | | 124 | (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0) |
108 | continue; | | 125 | continue; |
109 | | | 126 | |
110 | #define IS_TEXT(p) (p.p_flags & PF_X) | | 127 | #define IS_TEXT(p) (p.p_flags & PF_X) |
111 | #define IS_DATA(p) ((p.p_flags & PF_X) == 0) | | 128 | #define IS_DATA(p) (p.p_flags & PF_W) |
112 | #define IS_BSS(p) (p.p_filesz < p.p_memsz) | | 129 | #define IS_BSS(p) (p.p_filesz < p.p_memsz) |
113 | /* | | 130 | /* |
114 | * XXX: Assume first address is lowest | | 131 | * XXX: Assume first address is lowest |
115 | */ | | 132 | */ |
116 | if (IS_TEXT(phdr[i]) || IS_DATA(phdr[i])) { | | 133 | if (IS_TEXT(phdr[i]) || IS_DATA(phdr[i])) { |
117 | posv = phdr[i].p_vaddr; | | 134 | posv = phdr[i].p_vaddr; |
118 | if (minv > posv) | | 135 | if (minv > posv) |
119 | minv = posv; | | 136 | minv = posv; |
120 | posv += phdr[i].p_filesz; | | 137 | posv += phdr[i].p_filesz; |
121 | if (maxv < posv) | | 138 | if (maxv < posv) |
122 | maxv = posv; | | 139 | maxv = posv; |
123 | } | | 140 | } |
124 | if (IS_DATA(phdr[i]) && IS_BSS(phdr[i])) { | | 141 | if (IS_DATA(phdr[i]) && IS_BSS(phdr[i])) { |
| @@ -239,36 +256,36 @@ elf32bsdboot(void) | | | @@ -239,36 +256,36 @@ elf32bsdboot(void) |
239 | if (IS_TEXT(phdr[i]) || IS_DATA(phdr[i])) { | | 256 | if (IS_TEXT(phdr[i]) || IS_DATA(phdr[i])) { |
240 | sz = phdr[i].p_filesz; | | 257 | sz = phdr[i].p_filesz; |
241 | while (sz > 0) { | | 258 | while (sz > 0) { |
242 | sz--; | | 259 | sz--; |
243 | ((char *)phdr[i].p_vaddr)[sz] = | | 260 | ((char *)phdr[i].p_vaddr)[sz] = |
244 | (((char *)elf) + phdr[i].p_offset)[sz]; | | 261 | (((char *)elf) + phdr[i].p_offset)[sz]; |
245 | } | | 262 | } |
246 | } | | 263 | } |
247 | } | | 264 | } |
248 | | | 265 | |
249 | addr = (int *)(elf->e_entry); | | 266 | addr = (int *)(elf->e_entry); |
250 | __asm volatile ( | | 267 | __asm volatile ( |
251 | "mov r0, %0;" | | 268 | "mov r0, %0;" |
252 | "mov r2, #0;" | | 269 | "mcr p15, 0, r1, c7, c7, 0;" |
253 | "mcr p15, 0, r2, c7, c7, 0;" | | 270 | "mrc p15, 0, r1, c2, c0, 0;" |
254 | "mov r2, r2;" | | 271 | "mov r1, r1;" |
255 | "sub pc, pc, #4;" | | 272 | "sub pc, pc, #4;" |
256 | "mov r1, #(0x00000010 | 0x00000020);" | | 273 | "mov r1, #(0x00000010 | 0x00000020);" |
257 | "mcr p15, 0, r1, c1, c0, 0;" | | 274 | "mcr p15, 0, r1, c1, c0, 0;" |
258 | "mcr p15, 0, r2, c8, c7, 0;" | | 275 | "mcr p15, 0, r1, c8, c7, 0;" |
259 | "mov r2, r2;" | | 276 | "mrc p15, 0, r1, c2, c0, 0;" |
260 | "sub pc, pc, #4;" | | 277 | "sub pc, r0, r1, lsr #32;" |
261 | "mov pc, r0" :: "r"(addr) : "r0","r1","r2"); | | 278 | :: "r" (addr) : "r0", "r1"); |
262 | } | | 279 | } |
263 | | | 280 | |
264 | /* | | 281 | /* |
265 | * Initialize the module. | | 282 | * Initialize the module. |
266 | */ | | 283 | */ |
267 | int | | 284 | int |
268 | init_module(void) | | 285 | init_module(void) |
269 | { | | 286 | { |
270 | struct proc_dir_entry *entry; | | 287 | struct proc_dir_entry *entry; |
271 | int rc; | | 288 | int rc; |
272 | | | 289 | |
273 | rc = register_chrdev(ZBOOTDEV_MAJOR, ZBOOTDEV_NAME, &fops); | | 290 | rc = register_chrdev(ZBOOTDEV_MAJOR, ZBOOTDEV_NAME, &fops); |
274 | if (rc != 0) { | | 291 | if (rc != 0) { |
| @@ -336,28 +353,26 @@ zbsdmod_open(struct inode *ino, struct f | | | @@ -336,28 +353,26 @@ zbsdmod_open(struct inode *ino, struct f |
336 | position = 0; | | 353 | position = 0; |
337 | | | 354 | |
338 | return 0; | | 355 | return 0; |
339 | } | | 356 | } |
340 | | | 357 | |
341 | static int | | 358 | static int |
342 | zbsdmod_close(struct inode *ino, struct file *f) | | 359 | zbsdmod_close(struct inode *ino, struct file *f) |
343 | { | | 360 | { |
344 | | | 361 | |
345 | if (!isopen) | | 362 | if (!isopen) |
346 | return -EBUSY; | | 363 | return -EBUSY; |
347 | | | 364 | |
348 | if (position > 0) { | | 365 | if (position > 0) { |
349 | printk("%s: loaded %ld bytes\n", ZBOOTDEV_NAME, | | 366 | printk("%s: loaded %ld bytes\n", ZBOOTDEV_NAME, position); |
350 | position); | | 367 | if (position < (loff_t)BOOTINFO_MAXSIZE) { |
351 | | | | |
352 | if (position < BOOTINFO_MAXSIZE) { | | | |
353 | *(u_int *)bootargs = BOOTARGS_MAGIC; | | 368 | *(u_int *)bootargs = BOOTARGS_MAGIC; |
354 | memcpy(bootargs + sizeof(u_int), bsdimage, position); | | 369 | memcpy(bootargs + sizeof(u_int), bsdimage, position); |
355 | } else { | | 370 | } else { |
356 | elf32bsdboot(); | | 371 | elf32bsdboot(); |
357 | printk("%s: boot failed\n", ZBOOTDEV_NAME); | | 372 | printk("%s: boot failed\n", ZBOOTDEV_NAME); |
358 | } | | 373 | } |
359 | } | | 374 | } |
360 | isopen = 0; | | 375 | isopen = 0; |
361 | | | 376 | |
362 | return 0; | | 377 | return 0; |
363 | } | | 378 | } |