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

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

unix.superglobalmegacorp.com

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