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