|
|
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/strings.h> ! 41: #include <kern/task.h> ! 42: #include <kern/thread.h> ! 43: #include <vm/vm_kern.h> ! 44: #include <device/device_port.h> ! 45: ! 46: #include <sys/varargs.h> ! 47: ! 48: #include <mach/machine/multiboot.h> ! 49: #include <mach/exec/exec.h> ! 50: ! 51: #if MACH_KDB ! 52: #include <machine/db_machdep.h> ! 53: #include <ddb/db_sym.h> ! 54: #endif ! 55: ! 56: ! 57: static mach_port_t boot_device_port; /* local name */ ! 58: static mach_port_t boot_host_port; /* local name */ ! 59: ! 60: extern struct multiboot_info *boot_info; ! 61: extern char *kernel_cmdline; ! 62: ! 63: static void user_bootstrap(); /* forward */ ! 64: static void bootstrap_exec(void *exec_data); ! 65: ! 66: static mach_port_t ! 67: task_insert_send_right( ! 68: task_t task, ! 69: ipc_port_t port) ! 70: { ! 71: mach_port_t name; ! 72: ! 73: for (name = 1;; name++) { ! 74: kern_return_t kr; ! 75: ! 76: kr = mach_port_insert_right(task->itk_space, name, ! 77: (ipc_object_t)port, MACH_MSG_TYPE_PORT_SEND); ! 78: if (kr == KERN_SUCCESS) ! 79: break; ! 80: assert(kr == KERN_NAME_EXISTS); ! 81: } ! 82: ! 83: return name; ! 84: } ! 85: ! 86: void bootstrap_create() ! 87: { ! 88: struct multiboot_module *bmod; ! 89: ! 90: if (!(boot_info->flags & MULTIBOOT_MODS) ! 91: || (boot_info->mods_count == 0)) ! 92: panic("No bootstrap code loaded with the kernel!"); ! 93: if (boot_info->mods_count > 1) ! 94: printf("Warning: only one boot module currently used by Mach\n"); ! 95: bmod = (struct multiboot_module *)phystokv(boot_info->mods_addr); ! 96: bootstrap_exec((void*)phystokv(bmod->mod_start)); ! 97: ! 98: /* XXX at this point, we could free all the memory used ! 99: by the boot modules and the boot loader's descriptors and such. */ ! 100: } ! 101: ! 102: /* XXX won't work with more than one bootstrap service */ ! 103: static void *boot_exec; ! 104: ! 105: static void ! 106: bootstrap_exec(void *e) ! 107: { ! 108: task_t bootstrap_task; ! 109: thread_t bootstrap_thread; ! 110: ! 111: /* ! 112: * Create the bootstrap task. ! 113: */ ! 114: ! 115: (void) task_create(TASK_NULL, FALSE, &bootstrap_task); ! 116: (void) thread_create(bootstrap_task, &bootstrap_thread); ! 117: ! 118: /* ! 119: * Insert send rights to the master host and device ports. ! 120: */ ! 121: ! 122: boot_host_port = ! 123: task_insert_send_right(bootstrap_task, ! 124: ipc_port_make_send(realhost.host_priv_self)); ! 125: ! 126: boot_device_port = ! 127: task_insert_send_right(bootstrap_task, ! 128: ipc_port_make_send(master_device_port)); ! 129: ! 130: /* ! 131: * Start the bootstrap thread. ! 132: */ ! 133: boot_exec = e; ! 134: thread_start(bootstrap_thread, user_bootstrap); ! 135: (void) thread_resume(bootstrap_thread); ! 136: } ! 137: ! 138: /* ! 139: * The following code runs as the kernel mode portion of the ! 140: * first user thread. ! 141: */ ! 142: ! 143: /* ! 144: * Convert an unsigned integer to its decimal representation. ! 145: */ ! 146: static void ! 147: itoa( ! 148: char *str, ! 149: vm_size_t num) ! 150: { ! 151: char buf[sizeof(vm_size_t)*2+3]; ! 152: register char *np; ! 153: ! 154: np = buf + sizeof(buf); ! 155: *--np = 0; ! 156: ! 157: do { ! 158: *--np = '0' + num % 10; ! 159: num /= 10; ! 160: } while (num != 0); ! 161: ! 162: strcpy(str, np); ! 163: } ! 164: ! 165: /* ! 166: * Collect the boot flags into a single argument string, ! 167: * for compatibility with existing bootstrap and startup code. ! 168: * Format as a standard flag argument: '-qsdn...' ! 169: */ ! 170: static void get_compat_strings(char *flags_str, char *root_str) ! 171: { ! 172: register char *ip, *cp; ! 173: ! 174: cp = flags_str; ! 175: *cp++ = '-'; ! 176: ! 177: for (ip = kernel_cmdline; *ip; ) ! 178: { ! 179: if (*ip == ' ') ! 180: { ! 181: ip++; ! 182: } ! 183: else if (*ip == '-') ! 184: { ! 185: ip++; ! 186: while (*ip > ' ') ! 187: *cp++ = *ip++; ! 188: } ! 189: else if (strncmp(ip, "root=", 5) == 0) ! 190: { ! 191: char *rp = root_str; ! 192: ! 193: ip += 5; ! 194: if (strncmp(ip, "/dev/", 5) == 0) ! 195: ip += 5; ! 196: while (*ip > ' ') ! 197: *rp++ = *ip++; ! 198: *rp = '\0'; ! 199: } ! 200: else ! 201: { ! 202: while (*ip > ' ') ! 203: ip++; ! 204: } ! 205: } ! 206: ! 207: if (cp == &flags_str[1]) /* no flags */ ! 208: *cp++ = 'x'; ! 209: *cp = '\0'; ! 210: } ! 211: ! 212: /* ! 213: * Copy boot_data (executable) to the user portion of this task. ! 214: */ ! 215: static boolean_t load_protect_text = TRUE; ! 216: #if MACH_KDB ! 217: /* if set, fault in the text segment */ ! 218: static boolean_t load_fault_in_text = TRUE; ! 219: #endif ! 220: ! 221: static vm_offset_t ! 222: boot_map( ! 223: void * data, /* private data */ ! 224: vm_offset_t offset) /* offset to map */ ! 225: { ! 226: vm_offset_t start_offset = (vm_offset_t) data; ! 227: ! 228: return pmap_extract(kernel_pmap, start_offset + offset); ! 229: } ! 230: ! 231: ! 232: #if BOOTSTRAP_SYMBOLS ! 233: static boolean_t load_bootstrap_symbols = TRUE; ! 234: #else ! 235: static boolean_t load_bootstrap_symbols = FALSE; ! 236: #endif ! 237: ! 238: ! 239: ! 240: static int boot_read(void *handle, vm_offset_t file_ofs, void *buf, vm_size_t size, ! 241: vm_size_t *out_actual) ! 242: { ! 243: memcpy(buf, handle + file_ofs, size); ! 244: *out_actual = size; ! 245: return 0; ! 246: } ! 247: ! 248: static int read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size, ! 249: vm_offset_t mem_addr, vm_size_t mem_size, ! 250: exec_sectype_t sec_type) ! 251: { ! 252: vm_map_t user_map = current_task()->map; ! 253: vm_offset_t start_page, end_page; ! 254: vm_prot_t mem_prot = sec_type & EXEC_SECTYPE_PROT_MASK; ! 255: int err; ! 256: ! 257: if (!(sec_type & EXEC_SECTYPE_ALLOC)) ! 258: return 0; ! 259: ! 260: assert(mem_size > 0); ! 261: assert(mem_size >= file_size); ! 262: ! 263: start_page = trunc_page(mem_addr); ! 264: end_page = round_page(mem_addr + mem_size); ! 265: ! 266: /* ! 267: printf("reading bootstrap section %08x-%08x-%08x prot %d pages %08x-%08x\n", ! 268: mem_addr, mem_addr+file_size, mem_addr+mem_size, mem_prot, start_page, end_page); ! 269: */ ! 270: ! 271: err = vm_allocate(user_map, &start_page, end_page - start_page, FALSE); ! 272: assert(err == 0); ! 273: assert(start_page == trunc_page(mem_addr)); ! 274: ! 275: if (file_size > 0) ! 276: { ! 277: err = copyout(handle + file_ofs, mem_addr, file_size); ! 278: assert(err == 0); ! 279: } ! 280: ! 281: if (mem_prot != VM_PROT_ALL) ! 282: { ! 283: err = vm_protect(user_map, start_page, end_page - start_page, FALSE, mem_prot); ! 284: assert(err == 0); ! 285: } ! 286: } ! 287: ! 288: static void copy_bootstrap(void *e, struct exec_info *boot_exec_info) ! 289: { ! 290: register vm_map_t user_map = current_task()->map; ! 291: int err; ! 292: ! 293: if (err = exec_load(boot_read, read_exec, e, boot_exec_info)) ! 294: panic("Cannot load user-bootstrap image: error code %d", err); ! 295: ! 296: #if MACH_KDB ! 297: /* ! 298: * Enter the bootstrap symbol table. ! 299: */ ! 300: ! 301: #if 0 /*XXX*/ ! 302: if (load_bootstrap_symbols) ! 303: (void) X_db_sym_init( ! 304: (char*) boot_start+lp->sym_offset, ! 305: (char*) boot_start+lp->sym_offset+lp->sym_size, ! 306: "bootstrap", ! 307: (char *) user_map); ! 308: #endif ! 309: ! 310: #if 0 /*XXX*/ ! 311: if (load_fault_in_text) ! 312: { ! 313: vm_offset_t lenp = round_page(lp->text_start+lp->text_size) - ! 314: trunc_page(lp->text_start); ! 315: vm_offset_t i = 0; ! 316: ! 317: while (i < lenp) ! 318: { ! 319: vm_fault(user_map, text_page_start +i, ! 320: load_protect_text ? ! 321: VM_PROT_READ|VM_PROT_EXECUTE : ! 322: VM_PROT_READ|VM_PROT_EXECUTE | VM_PROT_WRITE, ! 323: 0,0,0); ! 324: i = round_page (i+1); ! 325: } ! 326: } ! 327: #endif ! 328: #endif MACH_KDB ! 329: } ! 330: ! 331: /* ! 332: * Allocate the stack, and build the argument list. ! 333: */ ! 334: extern vm_offset_t user_stack_low(); ! 335: extern vm_offset_t set_user_regs(); ! 336: ! 337: void ! 338: static build_args_and_stack(boot_exec_info, va_alist) ! 339: struct exec_info *boot_exec_info; ! 340: va_dcl ! 341: { ! 342: vm_offset_t stack_base; ! 343: vm_size_t stack_size; ! 344: va_list argv_ptr; ! 345: register ! 346: char * arg_ptr; ! 347: int arg_len; ! 348: int arg_count; ! 349: register ! 350: char * arg_pos; ! 351: int arg_item_len; ! 352: char * string_pos; ! 353: char * zero = (char *)0; ! 354: ! 355: #define STACK_SIZE (64*1024) ! 356: ! 357: /* ! 358: * Calculate the size of the argument list. ! 359: */ ! 360: va_start(argv_ptr); ! 361: arg_len = 0; ! 362: arg_count = 0; ! 363: for (;;) { ! 364: arg_ptr = va_arg(argv_ptr, char *); ! 365: if (arg_ptr == 0) ! 366: break; ! 367: arg_count++; ! 368: arg_len += strlen(arg_ptr) + 1; ! 369: } ! 370: va_end(argv_ptr); ! 371: ! 372: /* ! 373: * Add space for: ! 374: * arg count ! 375: * pointers to arguments ! 376: * trailing 0 pointer ! 377: * dummy 0 pointer to environment variables ! 378: * and align to integer boundary ! 379: */ ! 380: arg_len += sizeof(integer_t) ! 381: + (2 + arg_count) * sizeof(char *); ! 382: arg_len = (arg_len + sizeof(integer_t) - 1) & ~(sizeof(integer_t)-1); ! 383: ! 384: /* ! 385: * Allocate the stack. ! 386: */ ! 387: stack_size = round_page(STACK_SIZE); ! 388: stack_base = user_stack_low(stack_size); ! 389: (void) vm_allocate(current_task()->map, ! 390: &stack_base, ! 391: stack_size, ! 392: FALSE); ! 393: ! 394: arg_pos = (char *) ! 395: set_user_regs(stack_base, stack_size, boot_exec_info, arg_len); ! 396: ! 397: /* ! 398: * Start the strings after the arg-count and pointers ! 399: */ ! 400: string_pos = arg_pos ! 401: + sizeof(integer_t) ! 402: + arg_count * sizeof(char *) ! 403: + 2 * sizeof(char *); ! 404: ! 405: /* ! 406: * first the argument count ! 407: */ ! 408: (void) copyout((char *)&arg_count, ! 409: arg_pos, ! 410: sizeof(integer_t)); ! 411: arg_pos += sizeof(integer_t); ! 412: ! 413: /* ! 414: * Then the strings and string pointers for each argument ! 415: */ ! 416: va_start(argv_ptr); ! 417: while (--arg_count >= 0) { ! 418: arg_ptr = va_arg(argv_ptr, char *); ! 419: arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */ ! 420: ! 421: /* set string pointer */ ! 422: (void) copyout((char *)&string_pos, ! 423: arg_pos, ! 424: sizeof (char *)); ! 425: arg_pos += sizeof(char *); ! 426: ! 427: /* copy string */ ! 428: (void) copyout(arg_ptr, string_pos, arg_item_len); ! 429: string_pos += arg_item_len; ! 430: } ! 431: va_end(argv_ptr); ! 432: ! 433: /* ! 434: * last, the trailing 0 argument and a null environment pointer. ! 435: */ ! 436: (void) copyout((char *)&zero, arg_pos, sizeof(char *)); ! 437: arg_pos += sizeof(char *); ! 438: (void) copyout((char *)&zero, arg_pos, sizeof(char *)); ! 439: } ! 440: ! 441: static void user_bootstrap() ! 442: { ! 443: struct exec_info boot_exec_info; ! 444: ! 445: char host_string[12]; ! 446: char device_string[12]; ! 447: char flag_string[12]; ! 448: char root_string[12]; ! 449: ! 450: /* ! 451: * Copy the bootstrap code from boot_exec into the user task. ! 452: */ ! 453: copy_bootstrap(boot_exec, &boot_exec_info); ! 454: ! 455: /* ! 456: * Convert the host and device ports to strings, ! 457: * to put in the argument list. ! 458: */ ! 459: itoa(host_string, boot_host_port); ! 460: itoa(device_string, boot_device_port); ! 461: ! 462: /* ! 463: * Get the (compatibility) boot flags and root name strings. ! 464: */ ! 465: get_compat_strings(flag_string, root_string); ! 466: ! 467: /* ! 468: * Build the argument list and insert in the user task. ! 469: * Argument list is ! 470: * "bootstrap -<boothowto> <host_port> <device_port> <root_name>" ! 471: */ ! 472: build_args_and_stack(&boot_exec_info, ! 473: "bootstrap", ! 474: flag_string, ! 475: host_string, ! 476: device_string, ! 477: root_string, ! 478: (char *)0); ! 479: ! 480: /* ! 481: * Exit to user thread. ! 482: */ ! 483: thread_bootstrap_return(); ! 484: /*NOTREACHED*/ ! 485: } ! 486:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.