Annotation of OSKit-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/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.