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

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

unix.superglobalmegacorp.com

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