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

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

unix.superglobalmegacorp.com

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