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

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

unix.superglobalmegacorp.com

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