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