|
|
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> ! 42: #include <kern/lock.h> ! 43: #include <vm/vm_kern.h> ! 44: #include <device/device_port.h> ! 45: #include <alloca.h> ! 46: ! 47: #if MACH_KDB ! 48: #include <machine/db_machdep.h> ! 49: #include <ddb/db_sym.h> ! 50: #endif ! 51: ! 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: ! 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 */ ! 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 */ ! 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: { ! 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. */ ! 154: ! 155: char *flag_string = alloca(1024); ! 156: char *root_string = alloca(1024); ! 157: ! 158: /* ! 159: * Get the (compatibility) boot flags and root name strings. ! 160: */ ! 161: get_compat_strings(flag_string, root_string); ! 162: ! 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: } ! 247: ! 248: static void ! 249: bootstrap_exec_compat(void *e) ! 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: */ ! 276: bootstrap_thread->saved.other = e; ! 277: thread_start(bootstrap_thread, user_bootstrap_compat); ! 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: ! 317: strcpy (root_str, "UNKNOWN"); ! 318: ! 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: ! 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) ! 388: { ! 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; ! 397: } ! 398: ! 399: static int ! 400: read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size, ! 401: vm_offset_t mem_addr, vm_size_t mem_size, ! 402: exec_sectype_t sec_type) ! 403: { ! 404: struct multiboot_module *mod = handle; ! 405: ! 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: ! 411: if (mod->mod_start + file_ofs + file_size > mod->mod_end) ! 412: return -1; ! 413: ! 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: ! 423: #if 0 ! 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); ! 426: #endif ! 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: { ! 434: err = copyout((char *)phystokv (mod->mod_start) + file_ofs, ! 435: mem_addr, file_size); ! 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: } ! 444: ! 445: return 0; ! 446: } ! 447: ! 448: static void copy_bootstrap(void *e, exec_info_t *boot_exec_info) ! 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: { ! 479: vm_fault(user_map, text_page_start +i, ! 480: load_protect_text ? ! 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 ! 488: #endif /* MACH_KDB */ ! 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: ! 497: static void ! 498: build_args_and_stack(struct exec_info *boot_exec_info, ! 499: char **argv, char **envp) ! 500: { ! 501: vm_offset_t stack_base; ! 502: vm_size_t stack_size; ! 503: register ! 504: char * arg_ptr; ! 505: int arg_count, envc; ! 506: int arg_len; ! 507: char * arg_pos; ! 508: int arg_item_len; ! 509: char * string_pos; ! 510: char * zero = (char *)0; ! 511: int i; ! 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; ! 520: while (argv[arg_count] != 0) { ! 521: arg_ptr = argv[arg_count++]; ! 522: arg_len += strlen(arg_ptr) + 1; ! 523: } ! 524: envc = 0; ! 525: if (envp != 0) ! 526: while (envp[envc] != 0) ! 527: arg_len += strlen (envp[envc++]) + 1; ! 528: ! 529: /* ! 530: * Add space for: ! 531: * arg count ! 532: * pointers to arguments ! 533: * trailing 0 pointer ! 534: * pointers to environment variables ! 535: * trailing 0 pointer ! 536: * and align to integer boundary ! 537: */ ! 538: arg_len += (sizeof(integer_t) ! 539: + (arg_count + 1 + envc + 1) * sizeof(char *)); ! 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: */ ! 558: string_pos = (arg_pos ! 559: + sizeof(integer_t) ! 560: + (arg_count + 1 + envc + 1) * sizeof(char *)); ! 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: */ ! 573: for (i = 0; i < arg_count; ++i) { ! 574: arg_ptr = argv[i]; ! 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: /* ! 589: * Null terminator for argv. ! 590: */ ! 591: (void) copyout((char *)&zero, arg_pos, sizeof(char *)); ! 592: arg_pos += sizeof(char *); ! 593: ! 594: /* ! 595: * Then the strings and string pointers for each environment variable ! 596: */ ! 597: for (i = 0; i < envc; ++i) { ! 598: arg_ptr = envp[i]; ! 599: arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */ ! 600: ! 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: } ! 611: ! 612: /* ! 613: * Null terminator for envp. ! 614: */ ! 615: (void) copyout((char *)&zero, arg_pos, sizeof(char *)); ! 616: } ! 617: ! 618: ! 619: static void ! 620: user_bootstrap_compat() ! 621: { ! 622: exec_info_t boot_exec_info; ! 623: ! 624: char host_string[12]; ! 625: char device_string[12]; ! 626: char flag_string[1024]; ! 627: char root_string[1024]; ! 628: ! 629: /* ! 630: * Copy the bootstrap code from boot_exec into the user task. ! 631: */ ! 632: copy_bootstrap(current_thread()->saved.other, &boot_exec_info); ! 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>" ! 650: ! 651: $0 ${boot-args} ${host-port} ${device-port} ${root-device} $(task-create) $(task-resume) ! 652: ! 653: */ ! 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: } ! 671: ! 672: /* ! 673: * Exit to user thread. ! 674: */ ! 675: thread_bootstrap_return(); ! 676: /*NOTREACHED*/ ! 677: } ! 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.