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