Annotation of OSKit-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/task.h>
        !            41: #include <kern/thread.h>
        !            42: #include <kern/lock.h>
        !            43: #include <vm/vm_kern.h>
        !            44: #include <device/device_port.h>
        !            45: #include <alloca.h>
        !            46: 
        !            47: #if    MACH_KDB
        !            48: #include <machine/db_machdep.h>
        !            49: #include <ddb/db_sym.h>
        !            50: #endif
        !            51: 
        !            52: #if OSKIT_MACH
        !            53: #include <stddef.h>
        !            54: #include <string.h>
        !            55: #include <oskit/machine/base_multiboot.h>
        !            56: #include <oskit/exec/exec.h>
        !            57: #include <oskit/c/stdio.h>
        !            58: #define safe_gets(s, n) fgets((s),(n),stdin)
        !            59: #else
        !            60: #include <mach/machine/multiboot.h>
        !            61: #include <mach/exec/exec.h>
        !            62: #include <kern/strings.h>
        !            63: extern struct multiboot_info boot_info;        /* XXX put this in a header! */
        !            64: #endif
        !            65: 
        !            66: #include "boot_script.h"
        !            67: 
        !            68: 
        !            69: static mach_port_t     boot_device_port;       /* local name */
        !            70: static mach_port_t     boot_host_port;         /* local name */
        !            71: 
        !            72: extern char *kernel_cmdline;
        !            73: 
        !            74: static void user_bootstrap();  /* forward */
        !            75: static void user_bootstrap_compat();   /* forward */
        !            76: static void bootstrap_exec_compat(void *exec_data); /* forward */
        !            77: static void get_compat_strings(char *flags_str, char *root_str); /* forward */
        !            78: 
        !            79: static mach_port_t
        !            80: task_insert_send_right(
        !            81:        task_t task,
        !            82:        ipc_port_t port)
        !            83: {
        !            84:        mach_port_t name;
        !            85: 
        !            86:        for (name = 1;; name++) {
        !            87:                kern_return_t kr;
        !            88: 
        !            89:                kr = mach_port_insert_right(task->itk_space, name,
        !            90:                            (ipc_object_t)port, MACH_MSG_TYPE_PORT_SEND);
        !            91:                if (kr == KERN_SUCCESS)
        !            92:                        break;
        !            93:                assert(kr == KERN_NAME_EXISTS);
        !            94:        }
        !            95: 
        !            96:        return name;
        !            97: }
        !            98: 
        !            99: void bootstrap_create()
        !           100: {
        !           101:   struct multiboot_module *bmods = ((struct multiboot_module *)
        !           102:                                    phystokv(boot_info.mods_addr));
        !           103:   int compat;
        !           104: 
        !           105:   if (!(boot_info.flags & MULTIBOOT_MODS)
        !           106:       || (boot_info.mods_count == 0))
        !           107:     panic ("No bootstrap code loaded with the kernel!");
        !           108: 
        !           109:   compat = boot_info.mods_count == 1;
        !           110:   if (compat)
        !           111:     {
        !           112:       char *p = strchr((char*)phystokv(bmods[0].string), ' ');
        !           113:       if (p != 0)
        !           114:        do
        !           115:          ++p;
        !           116:        while (*p == ' ' || *p == '\n');
        !           117:       compat = p == 0 || *p == '\0';
        !           118:     }
        !           119: 
        !           120:   if (compat)
        !           121:     {
        !           122:       printf("Loading single multiboot module in compat mode: %s\n",
        !           123:             (char*)phystokv(bmods[0].string));
        !           124:       bootstrap_exec_compat(&bmods[0]);
        !           125:     }
        !           126:   else
        !           127:     {
        !           128:       int i, losers, maxlen;
        !           129: 
        !           130:       /* Initialize boot script variables.  We leak these send rights.  */
        !           131:       losers = boot_script_set_variable
        !           132:        ("host-port", VAL_PORT,
        !           133:         (int)ipc_port_make_send(realhost.host_priv_self));
        !           134:       if (losers)
        !           135:        panic ("cannot set boot-script variable host-port: %s",
        !           136:               boot_script_error_string (losers));
        !           137:       losers = boot_script_set_variable
        !           138:        ("device-port", VAL_PORT,
        !           139:         (int) ipc_port_make_send(master_device_port));
        !           140:       if (losers)
        !           141:        panic ("cannot set boot-script variable device-port: %s",
        !           142:               boot_script_error_string (losers));
        !           143: 
        !           144:       losers = boot_script_set_variable ("kernel-command-line", VAL_STR,
        !           145:                                         (int) kernel_cmdline);
        !           146:       if (losers)
        !           147:        panic ("cannot set boot-script variable %s: %s",
        !           148:               "kernel-command-line", boot_script_error_string (losers));
        !           149: 
        !           150:       {
        !           151:        /* Set the same boot script variables that the old Hurd's
        !           152:           serverboot did, so an old Hurd and boot script previously
        !           153:           used with serverboot can be used directly with this kernel.  */
        !           154: 
        !           155:        char *flag_string = alloca(1024);
        !           156:        char *root_string = alloca(1024);
        !           157: 
        !           158:        /*
        !           159:         * Get the (compatibility) boot flags and root name strings.
        !           160:         */
        !           161:        get_compat_strings(flag_string, root_string);
        !           162: 
        !           163:        losers = boot_script_set_variable ("boot-args", VAL_STR,
        !           164:                                           (int) flag_string);
        !           165:        if (losers)
        !           166:          panic ("cannot set boot-script variable %s: %s",
        !           167:                 "boot-args", boot_script_error_string (losers));
        !           168:        losers = boot_script_set_variable ("root-device", VAL_STR,
        !           169:                                           (int) root_string);
        !           170:        if (losers)
        !           171:          panic ("cannot set boot-script variable %s: %s",
        !           172:                 "root-device", boot_script_error_string (losers));
        !           173:       }
        !           174: 
        !           175: #if OSKIT_MACH
        !           176:       {
        !           177:        /* The oskit's "environ" array contains all the words from
        !           178:           the multiboot command line that looked like VAR=VAL.
        !           179:           We set each of these as boot-script variables, which
        !           180:           can be used for things like ${root}.  */
        !           181: 
        !           182:        extern char **environ;
        !           183:        char **ep;
        !           184:        for (ep = environ; *ep != 0; ++ep)
        !           185:          {
        !           186:            size_t len = strlen (*ep) + 1;
        !           187:            char *var = memcpy (alloca (len), *ep, len);
        !           188:            char *val = strchr (var, '=');
        !           189:            *val++ = '\0';
        !           190:            losers = boot_script_set_variable (var, VAL_STR, (int) val);
        !           191:            if (losers)
        !           192:              panic ("cannot set boot-script variable %s: %s",
        !           193:                     var, boot_script_error_string (losers));
        !           194:          }
        !           195:       }
        !           196: #else  /* GNUmach, not oskit-mach */
        !           197:       {
        !           198:        /* Turn each `FOO=BAR' word in the command line into a boot script
        !           199:           variable ${FOO} with value BAR.  This matches what we get from
        !           200:           oskit's environ in the oskit-mach case (above).  */
        !           201: 
        !           202:        int len = strlen (kernel_cmdline) + 1;
        !           203:        char *s = memcpy (alloca (len), kernel_cmdline, len);
        !           204:        char *word;
        !           205:        while ((word = strsep (&s, " \t")) != 0)
        !           206:          {
        !           207:            char *eq = strchr (word, '=');
        !           208:            if (eq == 0)
        !           209:              continue;
        !           210:            *eq++ = '\0';
        !           211:            losers = boot_script_set_variable (word, VAL_STR, (int) eq);
        !           212:            if (losers)
        !           213:              panic ("cannot set boot-script variable %s: %s",
        !           214:                     word, boot_script_error_string (losers));
        !           215:          }
        !           216:       }
        !           217: #endif
        !           218: 
        !           219:       maxlen = 0;
        !           220:       for (i = 0; i < boot_info.mods_count; ++i)
        !           221:        {
        !           222:          int err;
        !           223:          char *line = (char*)phystokv(bmods[i].string);
        !           224:          int len = strlen (line) + 1;
        !           225:          if (len > maxlen)
        !           226:            maxlen = len;
        !           227:          printf ("\rmodule %d: %*s", i, -maxlen, line);
        !           228:          err = boot_script_parse_line (&bmods[i], line);
        !           229:          if (err)
        !           230:            {
        !           231:              printf ("\n\tERROR: %s", boot_script_error_string (err));
        !           232:              ++losers;
        !           233:            }
        !           234:        }
        !           235:       printf ("\r%d multiboot modules %*s", i, -maxlen, "");
        !           236:       if (losers)
        !           237:        panic ("%d of %d boot script commands could not be parsed",
        !           238:               losers, boot_info.mods_count);
        !           239:       losers = boot_script_exec ();
        !           240:       if (losers)
        !           241:        panic ("ERROR in executing boot script: %s",
        !           242:               boot_script_error_string (losers));
        !           243:     }
        !           244:   /* XXX at this point, we could free all the memory used
        !           245:      by the boot modules and the boot loader's descriptors and such.  */
        !           246: }
        !           247: 
        !           248: static void
        !           249: bootstrap_exec_compat(void *e)
        !           250: {
        !           251:        task_t          bootstrap_task;
        !           252:        thread_t        bootstrap_thread;
        !           253: 
        !           254:        /*
        !           255:         * Create the bootstrap task.
        !           256:         */
        !           257: 
        !           258:        (void) task_create(TASK_NULL, FALSE, &bootstrap_task);
        !           259:        (void) thread_create(bootstrap_task, &bootstrap_thread);
        !           260: 
        !           261:        /*
        !           262:         * Insert send rights to the master host and device ports.
        !           263:         */
        !           264: 
        !           265:        boot_host_port =
        !           266:                task_insert_send_right(bootstrap_task,
        !           267:                        ipc_port_make_send(realhost.host_priv_self));
        !           268: 
        !           269:        boot_device_port =
        !           270:                task_insert_send_right(bootstrap_task,
        !           271:                        ipc_port_make_send(master_device_port));
        !           272: 
        !           273:        /*
        !           274:         * Start the bootstrap thread.
        !           275:         */
        !           276:        bootstrap_thread->saved.other = e;
        !           277:        thread_start(bootstrap_thread, user_bootstrap_compat);
        !           278:        (void) thread_resume(bootstrap_thread);
        !           279: }
        !           280: 
        !           281: /*
        !           282:  * The following code runs as the kernel mode portion of the
        !           283:  * first user thread.
        !           284:  */
        !           285: 
        !           286: /*
        !           287:  * Convert an unsigned integer to its decimal representation.
        !           288:  */
        !           289: static void
        !           290: itoa(
        !           291:        char            *str,
        !           292:        vm_size_t       num)
        !           293: {
        !           294:        char    buf[sizeof(vm_size_t)*2+3];
        !           295:        register char *np;
        !           296: 
        !           297:        np = buf + sizeof(buf);
        !           298:        *--np = 0;
        !           299: 
        !           300:        do {
        !           301:            *--np = '0' + num % 10;
        !           302:            num /= 10;
        !           303:        } while (num != 0);
        !           304: 
        !           305:        strcpy(str, np);
        !           306: }
        !           307: 
        !           308: /*
        !           309:  * Collect the boot flags into a single argument string,
        !           310:  * for compatibility with existing bootstrap and startup code.
        !           311:  * Format as a standard flag argument: '-qsdn...'
        !           312:  */
        !           313: static void get_compat_strings(char *flags_str, char *root_str)
        !           314: {
        !           315:        register char *ip, *cp;
        !           316: 
        !           317:        strcpy (root_str, "UNKNOWN");
        !           318: 
        !           319:        cp = flags_str;
        !           320:        *cp++ = '-';
        !           321: 
        !           322:        for (ip = kernel_cmdline; *ip; )
        !           323:        {
        !           324:                if (*ip == ' ')
        !           325:                {
        !           326:                        ip++;
        !           327:                }
        !           328:                else if (*ip == '-')
        !           329:                {
        !           330:                        ip++;
        !           331:                        while (*ip > ' ')
        !           332:                                *cp++ = *ip++;
        !           333:                }
        !           334:                else if (strncmp(ip, "root=", 5) == 0)
        !           335:                {
        !           336:                        char *rp = root_str;
        !           337: 
        !           338:                        ip += 5;
        !           339:                        if (strncmp(ip, "/dev/", 5) == 0)
        !           340:                                ip += 5;
        !           341:                        while (*ip > ' ')
        !           342:                                *rp++ = *ip++;
        !           343:                        *rp = '\0';
        !           344:                }
        !           345:                else
        !           346:                {
        !           347:                        while (*ip > ' ')
        !           348:                                ip++;
        !           349:                }
        !           350:        }
        !           351: 
        !           352:        if (cp == &flags_str[1])        /* no flags */
        !           353:            *cp++ = 'x';
        !           354:        *cp = '\0';
        !           355: }
        !           356: 
        !           357: /*
        !           358:  * Copy boot_data (executable) to the user portion of this task.
        !           359:  */
        !           360: static boolean_t       load_protect_text = TRUE;
        !           361: #if MACH_KDB
        !           362:                /* if set, fault in the text segment */
        !           363: static boolean_t       load_fault_in_text = TRUE;
        !           364: #endif
        !           365: 
        !           366: static vm_offset_t
        !           367: boot_map(
        !           368:        void *          data,   /* private data */
        !           369:        vm_offset_t     offset) /* offset to map */
        !           370: {
        !           371:        vm_offset_t     start_offset = (vm_offset_t) data;
        !           372: 
        !           373:        return pmap_extract(kernel_pmap, start_offset + offset);
        !           374: }
        !           375: 
        !           376: 
        !           377: #if BOOTSTRAP_SYMBOLS
        !           378: static boolean_t load_bootstrap_symbols = TRUE;
        !           379: #else
        !           380: static boolean_t load_bootstrap_symbols = FALSE;
        !           381: #endif
        !           382: 
        !           383: 
        !           384: 
        !           385: static int
        !           386: boot_read(void *handle, vm_offset_t file_ofs, void *buf, vm_size_t size,
        !           387:          vm_size_t *out_actual)
        !           388: {
        !           389:   struct multiboot_module *mod = handle;
        !           390: 
        !           391:   if (mod->mod_start + file_ofs + size > mod->mod_end)
        !           392:     return -1;
        !           393: 
        !           394:   memcpy(buf, (const char*) phystokv (mod->mod_start) + file_ofs, size);
        !           395:   *out_actual = size;
        !           396:   return 0;
        !           397: }
        !           398: 
        !           399: static int
        !           400: read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size,
        !           401:                     vm_offset_t mem_addr, vm_size_t mem_size,
        !           402:                     exec_sectype_t sec_type)
        !           403: {
        !           404:   struct multiboot_module *mod = handle;
        !           405: 
        !           406:        vm_map_t user_map = current_task()->map;
        !           407:        vm_offset_t start_page, end_page;
        !           408:        vm_prot_t mem_prot = sec_type & EXEC_SECTYPE_PROT_MASK;
        !           409:        int err;
        !           410: 
        !           411:        if (mod->mod_start + file_ofs + file_size > mod->mod_end)
        !           412:          return -1;
        !           413: 
        !           414:        if (!(sec_type & EXEC_SECTYPE_ALLOC))
        !           415:                return 0;
        !           416: 
        !           417:        assert(mem_size > 0);
        !           418:        assert(mem_size >= file_size);
        !           419: 
        !           420:        start_page = trunc_page(mem_addr);
        !           421:        end_page = round_page(mem_addr + mem_size);
        !           422: 
        !           423: #if 0
        !           424:        printf("reading bootstrap section %08x-%08x-%08x prot %d pages %08x-%08x\n",
        !           425:                mem_addr, mem_addr+file_size, mem_addr+mem_size, mem_prot, start_page, end_page);
        !           426: #endif
        !           427: 
        !           428:        err = vm_allocate(user_map, &start_page, end_page - start_page, FALSE);
        !           429:        assert(err == 0);
        !           430:        assert(start_page == trunc_page(mem_addr));
        !           431: 
        !           432:        if (file_size > 0)
        !           433:        {
        !           434:                err = copyout((char *)phystokv (mod->mod_start) + file_ofs,
        !           435:                              mem_addr, file_size);
        !           436:                assert(err == 0);
        !           437:        }
        !           438: 
        !           439:        if (mem_prot != VM_PROT_ALL)
        !           440:        {
        !           441:                err = vm_protect(user_map, start_page, end_page - start_page, FALSE, mem_prot);
        !           442:                assert(err == 0);
        !           443:        }
        !           444: 
        !           445:        return 0;
        !           446: }
        !           447: 
        !           448: static void copy_bootstrap(void *e, exec_info_t *boot_exec_info)
        !           449: {
        !           450:        register vm_map_t       user_map = current_task()->map;
        !           451:        int err;
        !           452: 
        !           453:        if (err = exec_load(boot_read, read_exec, e, boot_exec_info))
        !           454:                panic("Cannot load user-bootstrap image: error code %d", err);
        !           455: 
        !           456: #if    MACH_KDB
        !           457:        /*
        !           458:         * Enter the bootstrap symbol table.
        !           459:         */
        !           460: 
        !           461: #if 0 /*XXX*/
        !           462:        if (load_bootstrap_symbols)
        !           463:        (void) X_db_sym_init(
        !           464:                (char*) boot_start+lp->sym_offset,
        !           465:                (char*) boot_start+lp->sym_offset+lp->sym_size,
        !           466:                "bootstrap",
        !           467:                (char *) user_map);
        !           468: #endif
        !           469: 
        !           470: #if 0 /*XXX*/
        !           471:        if (load_fault_in_text)
        !           472:          {
        !           473:            vm_offset_t lenp = round_page(lp->text_start+lp->text_size) -
        !           474:                             trunc_page(lp->text_start);
        !           475:            vm_offset_t i = 0;
        !           476: 
        !           477:            while (i < lenp)
        !           478:              {
        !           479:                vm_fault(user_map, text_page_start +i,
        !           480:                        load_protect_text ?
        !           481:                         VM_PROT_READ|VM_PROT_EXECUTE :
        !           482:                         VM_PROT_READ|VM_PROT_EXECUTE | VM_PROT_WRITE,
        !           483:                         0,0,0);
        !           484:                i = round_page (i+1);
        !           485:              }
        !           486:          }
        !           487: #endif
        !           488: #endif /* MACH_KDB */
        !           489: }
        !           490: 
        !           491: /*
        !           492:  * Allocate the stack, and build the argument list.
        !           493:  */
        !           494: extern vm_offset_t     user_stack_low();
        !           495: extern vm_offset_t     set_user_regs();
        !           496: 
        !           497: static void
        !           498: build_args_and_stack(struct exec_info *boot_exec_info,
        !           499:                     char **argv, char **envp)
        !           500: {
        !           501:        vm_offset_t     stack_base;
        !           502:        vm_size_t       stack_size;
        !           503:        register
        !           504:        char *          arg_ptr;
        !           505:        int             arg_count, envc;
        !           506:        int             arg_len;
        !           507:        char *          arg_pos;
        !           508:        int             arg_item_len;
        !           509:        char *          string_pos;
        !           510:        char *          zero = (char *)0;
        !           511:        int i;
        !           512: 
        !           513: #define        STACK_SIZE      (64*1024)
        !           514: 
        !           515:        /*
        !           516:         * Calculate the size of the argument list.
        !           517:         */
        !           518:        arg_len = 0;
        !           519:        arg_count = 0;
        !           520:        while (argv[arg_count] != 0) {
        !           521:            arg_ptr = argv[arg_count++];
        !           522:            arg_len += strlen(arg_ptr) + 1;
        !           523:        }
        !           524:        envc = 0;
        !           525:        if (envp != 0)
        !           526:          while (envp[envc] != 0)
        !           527:            arg_len += strlen (envp[envc++]) + 1;
        !           528: 
        !           529:        /*
        !           530:         * Add space for:
        !           531:         *      arg count
        !           532:         *      pointers to arguments
        !           533:         *      trailing 0 pointer
        !           534:         *      pointers to environment variables
        !           535:         *      trailing 0 pointer
        !           536:         *      and align to integer boundary
        !           537:         */
        !           538:        arg_len += (sizeof(integer_t)
        !           539:                    + (arg_count + 1 + envc + 1) * sizeof(char *));
        !           540:        arg_len = (arg_len + sizeof(integer_t) - 1) & ~(sizeof(integer_t)-1);
        !           541: 
        !           542:        /*
        !           543:         * Allocate the stack.
        !           544:         */
        !           545:        stack_size = round_page(STACK_SIZE);
        !           546:        stack_base = user_stack_low(stack_size);
        !           547:        (void) vm_allocate(current_task()->map,
        !           548:                        &stack_base,
        !           549:                        stack_size,
        !           550:                        FALSE);
        !           551: 
        !           552:        arg_pos = (char *)
        !           553:                set_user_regs(stack_base, stack_size, boot_exec_info, arg_len);
        !           554: 
        !           555:        /*
        !           556:         * Start the strings after the arg-count and pointers
        !           557:         */
        !           558:        string_pos = (arg_pos
        !           559:                      + sizeof(integer_t)
        !           560:                      + (arg_count + 1 + envc + 1) * sizeof(char *));
        !           561: 
        !           562:        /*
        !           563:         * first the argument count
        !           564:         */
        !           565:        (void) copyout((char *)&arg_count,
        !           566:                        arg_pos,
        !           567:                        sizeof(integer_t));
        !           568:        arg_pos += sizeof(integer_t);
        !           569: 
        !           570:        /*
        !           571:         * Then the strings and string pointers for each argument
        !           572:         */
        !           573:        for (i = 0; i < arg_count; ++i) {
        !           574:            arg_ptr = argv[i];
        !           575:            arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */
        !           576: 
        !           577:            /* set string pointer */
        !           578:            (void) copyout((char *)&string_pos,
        !           579:                        arg_pos,
        !           580:                        sizeof (char *));
        !           581:            arg_pos += sizeof(char *);
        !           582: 
        !           583:            /* copy string */
        !           584:            (void) copyout(arg_ptr, string_pos, arg_item_len);
        !           585:            string_pos += arg_item_len;
        !           586:        }
        !           587: 
        !           588:        /*
        !           589:         * Null terminator for argv.
        !           590:         */
        !           591:        (void) copyout((char *)&zero, arg_pos, sizeof(char *));
        !           592:        arg_pos += sizeof(char *);
        !           593: 
        !           594:        /*
        !           595:         * Then the strings and string pointers for each environment variable
        !           596:         */
        !           597:        for (i = 0; i < envc; ++i) {
        !           598:            arg_ptr = envp[i];
        !           599:            arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */
        !           600: 
        !           601:            /* set string pointer */
        !           602:            (void) copyout((char *)&string_pos,
        !           603:                        arg_pos,
        !           604:                        sizeof (char *));
        !           605:            arg_pos += sizeof(char *);
        !           606: 
        !           607:            /* copy string */
        !           608:            (void) copyout(arg_ptr, string_pos, arg_item_len);
        !           609:            string_pos += arg_item_len;
        !           610:        }
        !           611: 
        !           612:        /*
        !           613:         * Null terminator for envp.
        !           614:         */
        !           615:        (void) copyout((char *)&zero, arg_pos, sizeof(char *));
        !           616: }
        !           617: 
        !           618: 
        !           619: static void
        !           620: user_bootstrap_compat()
        !           621: {
        !           622:        exec_info_t boot_exec_info;
        !           623: 
        !           624:        char    host_string[12];
        !           625:        char    device_string[12];
        !           626:        char    flag_string[1024];
        !           627:        char    root_string[1024];
        !           628: 
        !           629:        /*
        !           630:         * Copy the bootstrap code from boot_exec into the user task.
        !           631:         */
        !           632:        copy_bootstrap(current_thread()->saved.other, &boot_exec_info);
        !           633: 
        !           634:        /*
        !           635:         * Convert the host and device ports to strings,
        !           636:         * to put in the argument list.
        !           637:         */
        !           638:        itoa(host_string, boot_host_port);
        !           639:        itoa(device_string, boot_device_port);
        !           640: 
        !           641:        /*
        !           642:         * Get the (compatibility) boot flags and root name strings.
        !           643:         */
        !           644:        get_compat_strings(flag_string, root_string);
        !           645: 
        !           646:        /*
        !           647:         * Build the argument list and insert in the user task.
        !           648:         * Argument list is
        !           649:         * "bootstrap -<boothowto> <host_port> <device_port> <root_name>"
        !           650: 
        !           651: $0 ${boot-args} ${host-port} ${device-port} ${root-device} $(task-create) $(task-resume)
        !           652: 
        !           653:         */
        !           654:        {
        !           655:          char *argv[] = { "bootstrap",
        !           656:                           flag_string,
        !           657:                           host_string,
        !           658:                           device_string,
        !           659:                           root_string,
        !           660:                           0 };
        !           661:          char *envp[] = { 0, 0 };
        !           662:          if (kernel_cmdline[0] != '\0')
        !           663:            {
        !           664:              static const char cmdline_var[] = "MULTIBOOT_CMDLINE=";
        !           665:              envp[0] = alloca (sizeof cmdline_var + strlen (kernel_cmdline));
        !           666:              memcpy (envp[0], cmdline_var, sizeof cmdline_var - 1);
        !           667:              strcpy (envp[0] + sizeof cmdline_var - 1, kernel_cmdline);
        !           668:            }
        !           669:          build_args_and_stack(&boot_exec_info, argv, envp);
        !           670:        }
        !           671: 
        !           672:        /*
        !           673:         * Exit to user thread.
        !           674:         */
        !           675:        thread_bootstrap_return();
        !           676:        /*NOTREACHED*/
        !           677: }
        !           678: 
        !           679: 
        !           680: struct user_bootstrap_info
        !           681: {
        !           682:   struct multiboot_module *mod;
        !           683:   char **argv;
        !           684:   int done;
        !           685:   decl_simple_lock_data(,lock)
        !           686: };
        !           687: 
        !           688: int
        !           689: boot_script_exec_cmd (void *hook, task_t task, char *path, int argc,
        !           690:                      char **argv, char *strings, int stringlen)
        !           691: {
        !           692:   struct multiboot_module *mod = hook;
        !           693:   exec_info_t boot_exec_info;
        !           694: 
        !           695:   register vm_map_t    user_map = current_task()->map;
        !           696:   int err;
        !           697: 
        !           698:   if (task != MACH_PORT_NULL)
        !           699:     {
        !           700:       thread_t thread;
        !           701:       struct user_bootstrap_info info = { mod, argv, 0, };
        !           702:       simple_lock_init (&info.lock);
        !           703:       simple_lock (&info.lock);
        !           704: 
        !           705:       err = thread_create ((task_t)task, &thread);
        !           706:       assert(err == 0);
        !           707:       thread->saved.other = &info;
        !           708:       thread_start (thread, user_bootstrap);
        !           709:       thread_resume (thread);
        !           710: 
        !           711:       /* We need to synchronize with the new thread and block this
        !           712:         main thread until it has finished referring to our local state.  */
        !           713:       while (! info.done)
        !           714:        {
        !           715:          thread_sleep ((event_t) &info, simple_lock_addr(info.lock), FALSE);
        !           716:          simple_lock (&info.lock);
        !           717:        }
        !           718:       printf ("\n");
        !           719:     }
        !           720: 
        !           721:   return 0;
        !           722: }
        !           723: 
        !           724: static void user_bootstrap()
        !           725: {
        !           726:   struct user_bootstrap_info *info = current_thread()->saved.other;
        !           727:   exec_info_t boot_exec_info;
        !           728:   int err;
        !           729:   char **av;
        !           730: 
        !           731:   /* Load this task up from the executable file in the module.  */
        !           732:   err = exec_load(boot_read, read_exec, info->mod, &boot_exec_info);
        !           733:   if (err)
        !           734:     panic ("Cannot load user executable module (error code %d): %s",
        !           735:           err, info->argv[0]);
        !           736: 
        !           737:   printf ("task loaded:");
        !           738: 
        !           739:   /* Set up the stack with arguments.  */
        !           740:   build_args_and_stack(&boot_exec_info, info->argv, 0);
        !           741: 
        !           742:   for (av = info->argv; *av != 0; ++av)
        !           743:     printf (" %s", *av);
        !           744: 
        !           745:   task_suspend (current_task());
        !           746: 
        !           747:   /* Tell the bootstrap thread running boot_script_exec_cmd
        !           748:      that we are done looking at INFO.  */
        !           749:   simple_lock (&info->lock);
        !           750:   assert (!info->done);
        !           751:   info->done = 1;
        !           752:   thread_wakeup ((event_t) info);
        !           753: 
        !           754:   /*
        !           755:    * Exit to user thread.
        !           756:    */
        !           757:   thread_bootstrap_return();
        !           758:   /*NOTREACHED*/
        !           759: }
        !           760: 
        !           761: 
        !           762: 
        !           763: void *
        !           764: boot_script_malloc (unsigned int size)
        !           765: {
        !           766:   return (void *) kalloc (size);
        !           767: }
        !           768: 
        !           769: void
        !           770: boot_script_free (void *ptr, unsigned int size)
        !           771: {
        !           772:   kfree ((vm_offset_t)ptr, size);
        !           773: }
        !           774: 
        !           775: int
        !           776: boot_script_task_create (struct cmd *cmd)
        !           777: {
        !           778:   kern_return_t rc = task_create(TASK_NULL, FALSE, &cmd->task);
        !           779:   if (rc)
        !           780:     {
        !           781:       printf("boot_script_task_create failed with %x\n", rc);
        !           782:       return BOOT_SCRIPT_MACH_ERROR;
        !           783:     }
        !           784:   return 0;
        !           785: }
        !           786: 
        !           787: int
        !           788: boot_script_task_resume (struct cmd *cmd)
        !           789: {
        !           790:   kern_return_t rc = task_resume (cmd->task);
        !           791:   if (rc)
        !           792:     {
        !           793:       printf("boot_script_task_resume failed with %x\n", rc);
        !           794:       return BOOT_SCRIPT_MACH_ERROR;
        !           795:     }
        !           796:   printf ("\nstart %s: ", cmd->path);
        !           797:   return 0;
        !           798: }
        !           799: 
        !           800: int
        !           801: boot_script_prompt_task_resume (struct cmd *cmd)
        !           802: {
        !           803:   char xx[5];
        !           804: 
        !           805:   printf ("Hit return to resume %s...", cmd->path);
        !           806:   safe_gets (xx, sizeof xx);
        !           807: 
        !           808:   return boot_script_task_resume (cmd);
        !           809: }
        !           810: 
        !           811: void
        !           812: boot_script_free_task (task_t task, int aborting)
        !           813: {
        !           814:   if (aborting)
        !           815:     task_terminate (task);
        !           816: }
        !           817: 
        !           818: int
        !           819: boot_script_insert_right (struct cmd *cmd, mach_port_t port, mach_port_t *name)
        !           820: {
        !           821:   *name = task_insert_send_right (cmd->task, (ipc_port_t)port);
        !           822:   return 0;
        !           823: }
        !           824: 
        !           825: int
        !           826: boot_script_insert_task_port (struct cmd *cmd, task_t task, mach_port_t *name)
        !           827: {
        !           828:   *name = task_insert_send_right (cmd->task, task->itk_sself);
        !           829:   return 0;
        !           830: }

unix.superglobalmegacorp.com

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