|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.