[BACK]Return to zbsdmod.c CVS log [TXT][DIR] Up to [local] / sys / arch / zaurus / stand / zbsdmod

Annotation of sys/arch/zaurus/stand/zbsdmod/zbsdmod.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: zbsdmod.c,v 1.7 2005/05/02 02:45:29 uwe Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  *
                     18:  * Zaurus OpenBSD bootstrap loader.
                     19:  */
                     20:
                     21: #include "compat_linux.h"
                     22:
                     23: #define BOOTARGS_BUFSIZ        256
                     24: #define BOOTARGS_MAGIC 0x4f425344
                     25:
                     26: #define ZBOOTDEV_MAJOR 99
                     27: #define ZBOOTDEV_MODE  0222
                     28: #define ZBOOTDEV_NAME  "zboot"
                     29: #define ZBOOTMOD_NAME  "zbsdmod"
                     30:
                     31: /* Prototypes */
                     32: void   elf32bsdboot(void);
                     33: int    init_module(void);
                     34: void   cleanup_module(void);
                     35:
                     36: ssize_t        zbsdmod_write(struct file *, const char *, size_t, loff_t *);
                     37: int    zbsdmod_open(struct inode *, struct file *);
                     38: int    zbsdmod_close(struct inode *, struct file *);
                     39:
                     40: static struct file_operations fops = {
                     41:        0,                      /* struct module *owner */
                     42:        0,                      /* lseek */
                     43:        0,                      /* read */
                     44:        zbsdmod_write,          /* write */
                     45:        0,                      /* readdir */
                     46:        0,                      /* poll */
                     47:        0,                      /* ioctl */
                     48:        0,                      /* mmap */
                     49:        zbsdmod_open,           /* open */
                     50:        0,                      /* flush */
                     51:        zbsdmod_close,          /* release */
                     52:        0,                      /* sync */
                     53:        0,                      /* async */
                     54:        0,                      /* check media change */
                     55:        0,                      /* revalidate */
                     56:        0,                      /* lock */
                     57: };
                     58:
                     59: static int isopen;
                     60: static loff_t position;
                     61:
                     62: /* Outcast local variables to avoid stack usage in elf32bsdboot(). */
                     63: static int cpsr;
                     64: static unsigned int sz;
                     65: static int i;
                     66: static vaddr_t minv, maxv, posv;
                     67: static vaddr_t elfv, shpv;
                     68: static int *addr;
                     69: static vaddr_t *esymp;
                     70: static Elf_Shdr *shp;
                     71: static Elf_Off off;
                     72: static int havesyms;
                     73:
                     74: /* The maximum size of a kernel image is restricted to 5MB. */
                     75: static int bsdimage[1310720];  /* XXX use kmalloc() */
                     76: static char bootargs[BOOTARGS_BUFSIZ];
                     77:
                     78: /*
                     79:  * Boot the loaded BSD kernel image, or return if an error is found.
                     80:  * Part of this routine is borrowed from sys/lib/libsa/loadfile.c.
                     81:  */
                     82: void
                     83: elf32bsdboot(void)
                     84: {
                     85:
                     86: #define elf    ((Elf32_Ehdr *)bsdimage)
                     87: #define phdr   ((Elf32_Phdr *)((char *)elf + elf->e_phoff))
                     88:
                     89:        if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
                     90:            elf->e_ident[EI_CLASS] != ELFCLASS32)
                     91:                return;
                     92:
                     93:        minv = (vaddr_t)~0;
                     94:        maxv = (vaddr_t)0;
                     95:        posv = (vaddr_t)0;
                     96:        esymp = 0;
                     97:
                     98:        /*
                     99:         * Get min and max addresses used by the loaded kernel.
                    100:         */
                    101:        for (i = 0; i < elf->e_phnum; i++) {
                    102:
                    103:                if (phdr[i].p_type != PT_LOAD ||
                    104:                    (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
                    105:                        continue;
                    106:
                    107: #define IS_TEXT(p)     (p.p_flags & PF_X)
                    108: #define IS_DATA(p)     ((p.p_flags & PF_X) == 0)
                    109: #define IS_BSS(p)      (p.p_filesz < p.p_memsz)
                    110:                /*
                    111:                 * XXX: Assume first address is lowest
                    112:                 */
                    113:                if (IS_TEXT(phdr[i]) || IS_DATA(phdr[i])) {
                    114:                        posv = phdr[i].p_vaddr;
                    115:                        if (minv > posv)
                    116:                                minv = posv;
                    117:                        posv += phdr[i].p_filesz;
                    118:                        if (maxv < posv)
                    119:                                maxv = posv;
                    120:                }
                    121:                if (IS_DATA(phdr[i]) && IS_BSS(phdr[i])) {
                    122:                        posv += phdr[i].p_memsz;
                    123:                        if (maxv < posv)
                    124:                                maxv = posv;
                    125:                }
                    126:                /*
                    127:                 * 'esym' is the first word in the .data section,
                    128:                 * and marks the end of the symbol table.
                    129:                 */
                    130:                if (IS_DATA(phdr[i]) && !IS_BSS(phdr[i]))
                    131:                        esymp = (vaddr_t *)phdr[i].p_vaddr;
                    132:        }
                    133:
                    134:        __asm__ volatile ("mrs %0, cpsr_all" : "=r" (cpsr));
                    135:        cpsr |= 0xc0;  /* set FI */
                    136:        __asm__ volatile ("msr cpsr_all, %0" :: "r" (cpsr));
                    137:
                    138:        /*
                    139:         * Copy the boot arguments.
                    140:         */
                    141:        sz = BOOTARGS_BUFSIZ;
                    142:        while (sz > 0) {
                    143:                sz--;
                    144:                ((char *)minv - BOOTARGS_BUFSIZ)[sz] = bootargs[sz];
                    145:        }
                    146:
                    147:        /*
                    148:         * Set up pointers to copied ELF and section headers.
                    149:         */
                    150: #define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
                    151:        elfv = maxv = roundup(maxv, sizeof(long));
                    152:        maxv += sizeof(Elf_Ehdr);
                    153:
                    154:        sz = elf->e_shnum * sizeof(Elf_Shdr);
                    155:        shp = (Elf_Shdr *)((vaddr_t)elf + elf->e_shoff);
                    156:        shpv = maxv;
                    157:        maxv += roundup(sz, sizeof(long));
                    158:
                    159:        /*
                    160:         * Now load the symbol sections themselves.  Make sure the
                    161:         * sections are aligned, and offsets are relative to the
                    162:         * copied ELF header.  Don't bother with string tables if
                    163:         * there are no symbol sections.
                    164:         */
                    165:        off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(long));
                    166:        for (havesyms = i = 0; i < elf->e_shnum; i++)
                    167:                if (shp[i].sh_type == SHT_SYMTAB)
                    168:                        havesyms = 1;
                    169:        for (i = 0; i < elf->e_shnum; i++) {
                    170:                if (shp[i].sh_type == SHT_SYMTAB ||
                    171:                    shp[i].sh_type == SHT_STRTAB) {
                    172:                        if (havesyms) {
                    173:                                sz = shp[i].sh_size;
                    174:                                while (sz > 0) {
                    175:                                        sz--;
                    176:                                        ((char *)maxv)[sz] =
                    177:                                            ((char *)elf +
                    178:                                                shp[i].sh_offset)[sz];
                    179:                                }
                    180:                        }
                    181:                        maxv += roundup(shp[i].sh_size, sizeof(long));
                    182:                        shp[i].sh_offset = off;
                    183:                        off += roundup(shp[i].sh_size, sizeof(long));
                    184:                }
                    185:        }
                    186:
                    187:        /*
                    188:         * Copy the ELF and section headers.
                    189:         */
                    190:        sz = sizeof(Elf_Ehdr);
                    191:        while (sz > 0) {
                    192:                sz--;
                    193:                ((char *)elfv)[sz] = ((char *)elf)[sz];
                    194:        }
                    195:        sz = elf->e_shnum * sizeof(Elf_Shdr);
                    196:        while (sz > 0) {
                    197:                sz--;
                    198:                ((char *)shpv)[sz] = ((char *)shp)[sz];
                    199:        }
                    200:
                    201:        /*
                    202:         * Frob the copied ELF header to give information relative
                    203:         * to elfv.
                    204:         */
                    205:        ((Elf_Ehdr *)elfv)->e_phoff = 0;
                    206:        ((Elf_Ehdr *)elfv)->e_shoff = sizeof(Elf_Ehdr);
                    207:        ((Elf_Ehdr *)elfv)->e_phentsize = 0;
                    208:        ((Elf_Ehdr *)elfv)->e_phnum = 0;
                    209:
                    210:        /*
                    211:         * Tell locore.S where the symbol table ends, and arrange
                    212:         * to skip esym when loading the data section.
                    213:         */
                    214:        if (esymp != 0)
                    215:                *esymp = (vaddr_t)maxv;
                    216:        for (i = 0; esymp != 0 && i < elf->e_phnum; i++) {
                    217:                if (phdr[i].p_type != PT_LOAD ||
                    218:                    (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
                    219:                        continue;
                    220:                if (phdr[i].p_vaddr == (vaddr_t)esymp) {
                    221:                        phdr[i].p_vaddr = (vaddr_t)((char *)phdr[i].p_vaddr + sizeof(long));
                    222:                        phdr[i].p_offset = (vaddr_t)((char *)phdr[i].p_offset + sizeof(long));
                    223:                        phdr[i].p_filesz -= sizeof(long);
                    224:                        break;
                    225:                }
                    226:        }
                    227:
                    228:        /*
                    229:         * Load text and data.
                    230:         */
                    231:        for (i = 0; i < elf->e_phnum; i++) {
                    232:
                    233:                if (phdr[i].p_type != PT_LOAD ||
                    234:                    (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
                    235:                        continue;
                    236:
                    237:                if (IS_TEXT(phdr[i]) || IS_DATA(phdr[i])) {
                    238:                        sz = phdr[i].p_filesz;
                    239:                        while (sz > 0) {
                    240:                                sz--;
                    241:                                ((char *)phdr[i].p_vaddr)[sz] =
                    242:                                    (((char *)elf) + phdr[i].p_offset)[sz];
                    243:                        }
                    244:                }
                    245:        }
                    246:
                    247:        addr = (int *)(elf->e_entry);
                    248:        __asm__ volatile (
                    249:                "mov  r0, %0;"
                    250:                "mov  r2, #0;"
                    251:                "mov  r1, #(0x00000010 | 0x00000020);"
                    252:                "mcr  15, 0, r1, c1, c0, 0;"
                    253:                "mcr  15, 0, r2, c8, c7, 0    /* nail I+D TLB on ARMv4 and greater */;"
                    254:                "mov  pc, r0" :: "r"(addr) : "r0","r1","r2");
                    255: }
                    256:
                    257: /*
                    258:  * Initialize the LKM.
                    259:  */
                    260: int
                    261: init_module()
                    262: {
                    263:        struct proc_dir_entry *entry;
                    264:        int rc;
                    265:
                    266:        rc = register_chrdev(ZBOOTDEV_MAJOR, ZBOOTDEV_NAME, &fops);
                    267:        if (rc != 0) {
                    268:                printk("%s: register_chrdev(%d, ...): error %d\n",
                    269:                    ZBOOTMOD_NAME, -rc);
                    270:                return 1;
                    271:        }
                    272:
                    273:        entry = proc_mknod(ZBOOTDEV_NAME, ZBOOTDEV_MODE | S_IFCHR,
                    274:            &proc_root, MKDEV(ZBOOTDEV_MAJOR, 0));
                    275:        if (entry == (struct proc_dir_entry *)0) {
                    276:                (void)unregister_chrdev(ZBOOTDEV_MAJOR, ZBOOTDEV_NAME);
                    277:                return 1;
                    278:        }
                    279:
                    280:        printk("%s: OpenBSD/" MACHINE " bootstrap device is %d,0\n",
                    281:            ZBOOTMOD_NAME, ZBOOTDEV_MAJOR);
                    282:
                    283:        return 0;
                    284: }
                    285:
                    286: /*
                    287:  * Cleanup - undo whatever init_module did.
                    288:  */
                    289: void
                    290: cleanup_module()
                    291: {
                    292:
                    293:        (void)unregister_chrdev(ZBOOTDEV_MAJOR, ZBOOTDEV_NAME);
                    294:        remove_proc_entry(ZBOOTDEV_NAME, &proc_root);
                    295:
                    296:        printk("%s: OpenBSD/" MACHINE " bootstrap device unloaded\n",
                    297:            ZBOOTMOD_NAME);
                    298: }
                    299:
                    300:
                    301: ssize_t
                    302: zbsdmod_write(struct file *f, const char *buf, size_t len, loff_t *offp)
                    303: {
                    304:
                    305:        if (len < 1)
                    306:                return 0;
                    307:
                    308:        if (*offp + len >= sizeof(bsdimage))
                    309:                return EFBIG;
                    310:
                    311:        memcpy(((char *)bsdimage) + *offp, buf, len);
                    312:
                    313:        *offp += len;
                    314:        if (*offp > position)
                    315:                position = *offp;
                    316:
                    317:        return len;
                    318: }
                    319:
                    320: int
                    321: zbsdmod_open(struct inode *ino, struct file *f)
                    322: {
                    323:
                    324:        /* XXX superuser check */
                    325:
                    326:        if (isopen)
                    327:                return -EBUSY;
                    328:
                    329:        isopen = 1;
                    330:        position = 0;
                    331:
                    332:        return 0;
                    333: }
                    334:
                    335: int
                    336: zbsdmod_close(struct inode *ino, struct file *f)
                    337: {
                    338:
                    339:        if (isopen) {
                    340:                if (position > 0) {
                    341:                        printk("%s: loaded %d bytes\n", ZBOOTDEV_NAME,
                    342:                            position);
                    343:
                    344:                        if (position < BOOTARGS_BUFSIZ) {
                    345:                                *(int *)bootargs = BOOTARGS_MAGIC;
                    346:                                bootargs[position + sizeof(int)] = '\0';
                    347:                                memcpy(bootargs + sizeof(int), bsdimage,
                    348:                                    position);
                    349:                        } else {
                    350: #ifndef _TEST
                    351:                                elf32bsdboot();
                    352:                                printk("%s: boot failed\n", ZBOOTDEV_NAME);
                    353: #else
                    354:                                printk("/* boot() */\n");
                    355: #endif
                    356:                        }
                    357:                }
                    358:                isopen = 0;
                    359:                return 0;
                    360:        }
                    361:
                    362:        return -EBUSY;
                    363: }

CVSweb