Annotation of Gnu-Mach/kern/bootstrap.c, revision 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.