Annotation of Gnu-Mach/kern/bootstrap.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1992-1989 Carnegie Mellon University.
                      4:  * Copyright (c) 1995-1993 The University of Utah and
                      5:  * the Computer Systems Laboratory (CSL).
                      6:  * All rights reserved.
                      7:  *
                      8:  * Permission to use, copy, modify and distribute this software and its
                      9:  * documentation is hereby granted, provided that both the copyright
                     10:  * notice and this permission notice appear in all copies of the
                     11:  * software, derivative works or modified versions, and any portions
                     12:  * thereof, and that both notices appear in supporting documentation.
                     13:  *
                     14:  * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
                     15:  * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
                     16:  * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
                     17:  * THIS SOFTWARE.
                     18:  *
                     19:  * Carnegie Mellon requests users of this software to return to
                     20:  *
                     21:  *  Software Distribution Coordinator  or  [email protected]
                     22:  *  School of Computer Science
                     23:  *  Carnegie Mellon University
                     24:  *  Pittsburgh PA 15213-3890
                     25:  *
                     26:  * any improvements or extensions that they make and grant Carnegie Mellon
                     27:  * the rights to redistribute these changes.
                     28:  */
                     29: /*
                     30:  * Bootstrap the various built-in servers.
                     31:  */
                     32: #include <mach_kdb.h>
                     33: #include <bootstrap_symbols.h>
                     34: 
                     35: #include <mach/port.h>
                     36: #include <mach/message.h>
                     37: #include "vm_param.h"
                     38: #include <ipc/ipc_port.h>
                     39: #include <kern/host.h>
                     40: #include <kern/strings.h>
                     41: #include <kern/task.h>
                     42: #include <kern/thread.h>
                     43: #include <vm/vm_kern.h>
                     44: #include <device/device_port.h>
                     45: 
                     46: #include <sys/varargs.h>
                     47: 
                     48: #include <mach/machine/multiboot.h>
                     49: #include <mach/exec/exec.h>
                     50: 
                     51: #if    MACH_KDB
                     52: #include <machine/db_machdep.h>
                     53: #include <ddb/db_sym.h>
                     54: #endif
                     55: 
                     56: 
                     57: static mach_port_t     boot_device_port;       /* local name */
                     58: static mach_port_t     boot_host_port;         /* local name */
                     59: 
                     60: extern struct multiboot_info *boot_info;
                     61: extern char *kernel_cmdline;
                     62: 
                     63: static void user_bootstrap();  /* forward */
                     64: static void bootstrap_exec(void *exec_data);
                     65: 
                     66: static mach_port_t
                     67: task_insert_send_right(
                     68:        task_t task,
                     69:        ipc_port_t port)
                     70: {
                     71:        mach_port_t name;
                     72: 
                     73:        for (name = 1;; name++) {
                     74:                kern_return_t kr;
                     75: 
                     76:                kr = mach_port_insert_right(task->itk_space, name,
                     77:                            (ipc_object_t)port, MACH_MSG_TYPE_PORT_SEND);
                     78:                if (kr == KERN_SUCCESS)
                     79:                        break;
                     80:                assert(kr == KERN_NAME_EXISTS);
                     81:        }
                     82: 
                     83:        return name;
                     84: }
                     85: 
                     86: void bootstrap_create()
                     87: {
                     88:        struct multiboot_module *bmod;
                     89: 
                     90:        if (!(boot_info->flags & MULTIBOOT_MODS)
                     91:            || (boot_info->mods_count == 0))
                     92:                panic("No bootstrap code loaded with the kernel!");
                     93:        if (boot_info->mods_count > 1)
                     94:                printf("Warning: only one boot module currently used by Mach\n");
                     95:        bmod = (struct multiboot_module *)phystokv(boot_info->mods_addr);
                     96:        bootstrap_exec((void*)phystokv(bmod->mod_start));
                     97: 
                     98:        /* XXX at this point, we could free all the memory used
                     99:           by the boot modules and the boot loader's descriptors and such.  */
                    100: }
                    101: 
                    102: /* XXX won't work with more than one bootstrap service */
                    103: static void *boot_exec;
                    104: 
                    105: static void
                    106: bootstrap_exec(void *e)
                    107: {
                    108:        task_t          bootstrap_task;
                    109:        thread_t        bootstrap_thread;
                    110: 
                    111:        /*
                    112:         * Create the bootstrap task.
                    113:         */
                    114: 
                    115:        (void) task_create(TASK_NULL, FALSE, &bootstrap_task);
                    116:        (void) thread_create(bootstrap_task, &bootstrap_thread);
                    117: 
                    118:        /*
                    119:         * Insert send rights to the master host and device ports.
                    120:         */
                    121: 
                    122:        boot_host_port =
                    123:                task_insert_send_right(bootstrap_task,
                    124:                        ipc_port_make_send(realhost.host_priv_self));
                    125: 
                    126:        boot_device_port =
                    127:                task_insert_send_right(bootstrap_task,
                    128:                        ipc_port_make_send(master_device_port));
                    129: 
                    130:        /*
                    131:         * Start the bootstrap thread.
                    132:         */
                    133:        boot_exec = e;
                    134:        thread_start(bootstrap_thread, user_bootstrap);
                    135:        (void) thread_resume(bootstrap_thread);
                    136: }
                    137: 
                    138: /*
                    139:  * The following code runs as the kernel mode portion of the
                    140:  * first user thread.
                    141:  */
                    142: 
                    143: /*
                    144:  * Convert an unsigned integer to its decimal representation.
                    145:  */
                    146: static void
                    147: itoa(
                    148:        char            *str,
                    149:        vm_size_t       num)
                    150: {
                    151:        char    buf[sizeof(vm_size_t)*2+3];
                    152:        register char *np;
                    153: 
                    154:        np = buf + sizeof(buf);
                    155:        *--np = 0;
                    156: 
                    157:        do {
                    158:            *--np = '0' + num % 10;
                    159:            num /= 10;
                    160:        } while (num != 0);
                    161: 
                    162:        strcpy(str, np);
                    163: }
                    164: 
                    165: /*
                    166:  * Collect the boot flags into a single argument string,
                    167:  * for compatibility with existing bootstrap and startup code.
                    168:  * Format as a standard flag argument: '-qsdn...'
                    169:  */
                    170: static void get_compat_strings(char *flags_str, char *root_str)
                    171: {
                    172:        register char *ip, *cp;
                    173: 
                    174:        cp = flags_str;
                    175:        *cp++ = '-';
                    176: 
                    177:        for (ip = kernel_cmdline; *ip; )
                    178:        {
                    179:                if (*ip == ' ')
                    180:                {
                    181:                        ip++;
                    182:                }
                    183:                else if (*ip == '-')
                    184:                {
                    185:                        ip++;
                    186:                        while (*ip > ' ')
                    187:                                *cp++ = *ip++;
                    188:                }
                    189:                else if (strncmp(ip, "root=", 5) == 0)
                    190:                {
                    191:                        char *rp = root_str;
                    192: 
                    193:                        ip += 5;
                    194:                        if (strncmp(ip, "/dev/", 5) == 0)
                    195:                                ip += 5;
                    196:                        while (*ip > ' ')
                    197:                                *rp++ = *ip++;
                    198:                        *rp = '\0';
                    199:                }
                    200:                else
                    201:                {
                    202:                        while (*ip > ' ')
                    203:                                ip++;
                    204:                }
                    205:        }
                    206: 
                    207:        if (cp == &flags_str[1])        /* no flags */
                    208:            *cp++ = 'x';
                    209:        *cp = '\0';
                    210: }
                    211: 
                    212: /*
                    213:  * Copy boot_data (executable) to the user portion of this task.
                    214:  */
                    215: static boolean_t       load_protect_text = TRUE;
                    216: #if MACH_KDB
                    217:                /* if set, fault in the text segment */
                    218: static boolean_t       load_fault_in_text = TRUE;
                    219: #endif
                    220: 
                    221: static vm_offset_t
                    222: boot_map(
                    223:        void *          data,   /* private data */
                    224:        vm_offset_t     offset) /* offset to map */
                    225: {
                    226:        vm_offset_t     start_offset = (vm_offset_t) data;
                    227: 
                    228:        return pmap_extract(kernel_pmap, start_offset + offset);
                    229: }
                    230: 
                    231: 
                    232: #if BOOTSTRAP_SYMBOLS
                    233: static boolean_t load_bootstrap_symbols = TRUE;
                    234: #else
                    235: static boolean_t load_bootstrap_symbols = FALSE;
                    236: #endif
                    237: 
                    238: 
                    239: 
                    240: static int boot_read(void *handle, vm_offset_t file_ofs, void *buf, vm_size_t size,
                    241:                     vm_size_t *out_actual)
                    242: {
                    243:        memcpy(buf, handle + file_ofs, size);
                    244:        *out_actual = size;
                    245:        return 0;
                    246: }
                    247: 
                    248: static int read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size,
                    249:                     vm_offset_t mem_addr, vm_size_t mem_size,
                    250:                     exec_sectype_t sec_type)
                    251: {
                    252:        vm_map_t user_map = current_task()->map;
                    253:        vm_offset_t start_page, end_page;
                    254:        vm_prot_t mem_prot = sec_type & EXEC_SECTYPE_PROT_MASK;
                    255:        int err;
                    256: 
                    257:        if (!(sec_type & EXEC_SECTYPE_ALLOC))
                    258:                return 0;
                    259: 
                    260:        assert(mem_size > 0);
                    261:        assert(mem_size >= file_size);
                    262: 
                    263:        start_page = trunc_page(mem_addr);
                    264:        end_page = round_page(mem_addr + mem_size);
                    265: 
                    266:        /*
                    267:        printf("reading bootstrap section %08x-%08x-%08x prot %d pages %08x-%08x\n",
                    268:                mem_addr, mem_addr+file_size, mem_addr+mem_size, mem_prot, start_page, end_page);
                    269:        */
                    270: 
                    271:        err = vm_allocate(user_map, &start_page, end_page - start_page, FALSE);
                    272:        assert(err == 0);
                    273:        assert(start_page == trunc_page(mem_addr));
                    274: 
                    275:        if (file_size > 0)
                    276:        {
                    277:                err = copyout(handle + file_ofs, mem_addr, file_size);
                    278:                assert(err == 0);
                    279:        }
                    280: 
                    281:        if (mem_prot != VM_PROT_ALL)
                    282:        {
                    283:                err = vm_protect(user_map, start_page, end_page - start_page, FALSE, mem_prot);
                    284:                assert(err == 0);
                    285:        }
                    286: }
                    287: 
                    288: static void copy_bootstrap(void *e, struct exec_info *boot_exec_info)
                    289: {
                    290:        register vm_map_t       user_map = current_task()->map;
                    291:        int err;
                    292: 
                    293:        if (err = exec_load(boot_read, read_exec, e, boot_exec_info))
                    294:                panic("Cannot load user-bootstrap image: error code %d", err);
                    295: 
                    296: #if    MACH_KDB
                    297:        /*
                    298:         * Enter the bootstrap symbol table.
                    299:         */
                    300: 
                    301: #if 0 /*XXX*/
                    302:        if (load_bootstrap_symbols)
                    303:        (void) X_db_sym_init(
                    304:                (char*) boot_start+lp->sym_offset,
                    305:                (char*) boot_start+lp->sym_offset+lp->sym_size,
                    306:                "bootstrap",
                    307:                (char *) user_map);
                    308: #endif
                    309: 
                    310: #if 0 /*XXX*/
                    311:        if (load_fault_in_text)
                    312:          {
                    313:            vm_offset_t lenp = round_page(lp->text_start+lp->text_size) -
                    314:                             trunc_page(lp->text_start);
                    315:            vm_offset_t i = 0;
                    316: 
                    317:            while (i < lenp)
                    318:              {
                    319:                vm_fault(user_map, text_page_start +i, 
                    320:                        load_protect_text ?  
                    321:                         VM_PROT_READ|VM_PROT_EXECUTE :
                    322:                         VM_PROT_READ|VM_PROT_EXECUTE | VM_PROT_WRITE,
                    323:                         0,0,0);
                    324:                i = round_page (i+1);
                    325:              }
                    326:          }
                    327: #endif
                    328: #endif MACH_KDB
                    329: }
                    330: 
                    331: /*
                    332:  * Allocate the stack, and build the argument list.
                    333:  */
                    334: extern vm_offset_t     user_stack_low();
                    335: extern vm_offset_t     set_user_regs();
                    336: 
                    337: void
                    338: static build_args_and_stack(boot_exec_info, va_alist)
                    339:        struct exec_info *boot_exec_info;
                    340:        va_dcl
                    341: {
                    342:        vm_offset_t     stack_base;
                    343:        vm_size_t       stack_size;
                    344:        va_list         argv_ptr;
                    345:        register
                    346:        char *          arg_ptr;
                    347:        int             arg_len;
                    348:        int             arg_count;
                    349:        register
                    350:        char *          arg_pos;
                    351:        int             arg_item_len;
                    352:        char *          string_pos;
                    353:        char *          zero = (char *)0;
                    354: 
                    355: #define        STACK_SIZE      (64*1024)
                    356: 
                    357:        /*
                    358:         * Calculate the size of the argument list.
                    359:         */
                    360:        va_start(argv_ptr);
                    361:        arg_len = 0;
                    362:        arg_count = 0;
                    363:        for (;;) {
                    364:            arg_ptr = va_arg(argv_ptr, char *);
                    365:            if (arg_ptr == 0)
                    366:                break;
                    367:            arg_count++;
                    368:            arg_len += strlen(arg_ptr) + 1;
                    369:        }
                    370:        va_end(argv_ptr);
                    371: 
                    372:        /*
                    373:         * Add space for:
                    374:         *      arg count
                    375:         *      pointers to arguments
                    376:         *      trailing 0 pointer
                    377:         *      dummy 0 pointer to environment variables
                    378:         *      and align to integer boundary
                    379:         */
                    380:        arg_len += sizeof(integer_t)
                    381:                 + (2 + arg_count) * sizeof(char *);
                    382:        arg_len = (arg_len + sizeof(integer_t) - 1) & ~(sizeof(integer_t)-1);
                    383: 
                    384:        /*
                    385:         * Allocate the stack.
                    386:         */
                    387:        stack_size = round_page(STACK_SIZE);
                    388:        stack_base = user_stack_low(stack_size);
                    389:        (void) vm_allocate(current_task()->map,
                    390:                        &stack_base,
                    391:                        stack_size,
                    392:                        FALSE);
                    393: 
                    394:        arg_pos = (char *)
                    395:                set_user_regs(stack_base, stack_size, boot_exec_info, arg_len);
                    396: 
                    397:        /*
                    398:         * Start the strings after the arg-count and pointers
                    399:         */
                    400:        string_pos = arg_pos
                    401:                + sizeof(integer_t)
                    402:                + arg_count * sizeof(char *)
                    403:                + 2 * sizeof(char *);
                    404: 
                    405:        /*
                    406:         * first the argument count
                    407:         */
                    408:        (void) copyout((char *)&arg_count,
                    409:                        arg_pos,
                    410:                        sizeof(integer_t));
                    411:        arg_pos += sizeof(integer_t);
                    412: 
                    413:        /*
                    414:         * Then the strings and string pointers for each argument
                    415:         */
                    416:        va_start(argv_ptr);
                    417:        while (--arg_count >= 0) {
                    418:            arg_ptr = va_arg(argv_ptr, char *);
                    419:            arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */
                    420: 
                    421:            /* set string pointer */
                    422:            (void) copyout((char *)&string_pos,
                    423:                        arg_pos,
                    424:                        sizeof (char *));
                    425:            arg_pos += sizeof(char *);
                    426: 
                    427:            /* copy string */
                    428:            (void) copyout(arg_ptr, string_pos, arg_item_len);
                    429:            string_pos += arg_item_len;
                    430:        }
                    431:        va_end(argv_ptr);
                    432: 
                    433:        /*
                    434:         * last, the trailing 0 argument and a null environment pointer.
                    435:         */
                    436:        (void) copyout((char *)&zero, arg_pos, sizeof(char *));
                    437:        arg_pos += sizeof(char *);
                    438:        (void) copyout((char *)&zero, arg_pos, sizeof(char *));
                    439: }
                    440: 
                    441: static void user_bootstrap()
                    442: {
                    443:        struct exec_info boot_exec_info;
                    444: 
                    445:        char    host_string[12];
                    446:        char    device_string[12];
                    447:        char    flag_string[12];
                    448:        char    root_string[12];
                    449: 
                    450:        /*
                    451:         * Copy the bootstrap code from boot_exec into the user task.
                    452:         */
                    453:        copy_bootstrap(boot_exec, &boot_exec_info);
                    454: 
                    455:        /*
                    456:         * Convert the host and device ports to strings,
                    457:         * to put in the argument list.
                    458:         */
                    459:        itoa(host_string, boot_host_port);
                    460:        itoa(device_string, boot_device_port);
                    461: 
                    462:        /*
                    463:         * Get the (compatibility) boot flags and root name strings.
                    464:         */
                    465:        get_compat_strings(flag_string, root_string);
                    466: 
                    467:        /*
                    468:         * Build the argument list and insert in the user task.
                    469:         * Argument list is
                    470:         * "bootstrap -<boothowto> <host_port> <device_port> <root_name>"
                    471:         */
                    472:        build_args_and_stack(&boot_exec_info,
                    473:                        "bootstrap",
                    474:                        flag_string,
                    475:                        host_string,
                    476:                        device_string,
                    477:                        root_string,
                    478:                        (char *)0);
                    479: 
                    480:        /*
                    481:         * Exit to user thread.
                    482:         */
                    483:        thread_bootstrap_return();
                    484:        /*NOTREACHED*/
                    485: }
                    486: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.