/* * Mach Operating System * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * Bootstrap the various built-in servers. */ #include #include #include #include #include "../boot/boot_script.h" /* Use this device if no root specified. */ #define DEFAULT_ROOT "hd0a" #if 0 /* * Use 8 Kbyte stacks instead of the default 64K. * Use 4 Kbyte waiting stacks instead of the default 8K. */ #if defined(alpha) vm_size_t cthread_stack_size = 16 * 1024; #else vm_size_t cthread_stack_size = 8 * 1024; #endif #endif extern vm_size_t cthread_wait_stack_size; mach_port_t bootstrap_master_device_port; /* local name */ mach_port_t bootstrap_master_host_port; /* local name */ int boot_load_program(); char *root_name; char boot_script_name[MAXPATHLEN]; extern void default_pager(); extern void default_pager_initialize(); extern void default_pager_setup(); /* initialized in default_pager_initialize */ extern mach_port_t default_pager_exception_port; extern mach_port_t default_pager_bootstrap_port; /* * Convert ASCII to integer. */ int atoi(str) register const char *str; { register int n; register int c; int is_negative = 0; n = 0; while (*str == ' ') str++; if (*str == '-') { is_negative = 1; str++; } while ((c = *str++) >= '0' && c <= '9') { n = n * 10 + (c - '0'); } if (is_negative) n = -n; return (n); } __main () { } static void boot_panic (kern_return_t err) { #define PFX "bootstrap: " char *err_string = boot_script_error_string (err); char panic_string[strlen (err_string) + sizeof (PFX)]; strcpy (panic_string, PFX); strcat (panic_string, err_string); panic (panic_string); #undef PFX } void safe_gets (char *str, int maxlen) { char *c; c = index (fgets (str, maxlen, stdin), '\n'); if (c) *c = '\0'; printf ("\r\n"); } printf_init (device_t master) { mach_port_t cons; device_open (master, D_READ|D_WRITE, "console", &cons); stdin = mach_open_devstream (cons, "r"); stdout = stderr = mach_open_devstream (cons, "w"); mach_port_deallocate (mach_task_self (), cons); setbuf (stdout, 0); } /* * Bootstrap task. * Runs in user spacep. * * Called as 'boot -switches host_port device_port root_name' * */ main(argc, argv) int argc; char **argv; { int doing_default_pager = 0; int had_a_partition = 0; int script_paging_file (const struct cmd *cmd, int *val) { if (add_paging_file (bootstrap_master_device_port, cmd->path)) printf ("(bootstrap): %s: Cannot add paging file\n", cmd->path); else had_a_partition = 1; } int script_default_pager (const struct cmd *cmd, int *val) { if (had_a_partition) { default_pager_initialize(bootstrap_master_host_port); doing_default_pager = 1; } else printf ("(bootstrap): Running without any paging\n"); return 0; } register kern_return_t result; struct file scriptf; task_t my_task = mach_task_self(); char *flag_string; boolean_t ask_boot_script = 0; /* * Use 4Kbyte cthread wait stacks. */ cthread_wait_stack_size = 4 * 1024; /* * Arg 1 is flags */ if (argv[1][0] != '-') panic("bootstrap: no flags"); flag_string = argv[1]; /* * Parse the arguments. */ if (argc >= 5) { /* * Arg 0 is program name */ /* * Arg 2 is host port number */ bootstrap_master_host_port = atoi(argv[2]); /* * Arg 3 is device port number */ bootstrap_master_device_port = atoi(argv[3]); /* * Arg 4 is root name */ root_name = argv[4]; } else if (argc == 3) { root_name = argv[2]; get_privileged_ports (&bootstrap_master_host_port, &bootstrap_master_device_port); } printf_init(bootstrap_master_device_port); #ifdef pleasenoXXX panic_init(bootstrap_master_host_port); #endif if (root_name[0] == '\0') root_name = DEFAULT_ROOT; /* * If the '-a' (ask) switch was specified, ask for * the root device. */ if (index(flag_string, 'a')) { static char new_root[16]; printf("root device? [%s] ", root_name); safe_gets(new_root, sizeof(new_root)); if (new_root[0] != '\0') strcpy (root_name, new_root); } (void) strbuild(boot_script_name, "/dev/", root_name, "/boot/servers.boot", (char *)0); /* * If the '-q' (query) switch was specified, ask for the * server boot script. */ if (index(flag_string, 'q')) ask_boot_script = TRUE; while (TRUE) { if (ask_boot_script) { char new_boot_script[MAXPATHLEN]; printf("Server boot script? [%s] ", boot_script_name); safe_gets(new_boot_script, sizeof(new_boot_script)); if (new_boot_script[0] != '\0') strcpy(boot_script_name, new_boot_script); } result = open_file(bootstrap_master_device_port, boot_script_name, &scriptf); if (result != 0) { printf("Can't open server boot script %s: %d\n", boot_script_name, result); ask_boot_script = TRUE; continue; } break; } /* * If the server boot script name was changed, * then use the new device name as the root device. */ { char *dev, *end; int len; dev = boot_script_name; if (strncmp(dev, "/dev/", 5) == 0) dev += 5; end = strchr(dev, '/'); len = end ? end-dev : strlen(dev); memcpy(root_name, dev, len); root_name[len] = 0; } /* * Set up the default pager. */ partition_init(); { /* Initialize boot script variables. */ if (boot_script_set_variable ("host-port", VAL_PORT, (int) bootstrap_master_host_port) || boot_script_set_variable ("device-port", VAL_PORT, (int) bootstrap_master_device_port) || boot_script_set_variable ("root-device", VAL_STR, (int) root_name) || boot_script_set_variable ("boot-args", VAL_STR, (int) flag_string) || boot_script_define_function ("add-paging-file", VAL_NONE, &script_paging_file) || boot_script_define_function ("default-pager", VAL_NONE, &script_default_pager) ) panic ("bootstrap: error setting boot script variables"); parse_script (&scriptf); close_file (&scriptf); } if (index (flag_string, 'd')) { char xx[5]; printf ("Hit return to boot..."); safe_gets (xx, sizeof xx); } /* * task_set_exception_port and task_set_bootstrap_port * both require a send right. */ (void) mach_port_insert_right(my_task, default_pager_bootstrap_port, default_pager_bootstrap_port, MACH_MSG_TYPE_MAKE_SEND); (void) mach_port_insert_right(my_task, default_pager_exception_port, default_pager_exception_port, MACH_MSG_TYPE_MAKE_SEND); /* * Change our exception port. */ (void) task_set_exception_port(my_task, default_pager_exception_port); result = boot_script_exec (); if (result) boot_panic (result); #if 0 { /* * Delete the old stack (containing only the arguments). */ vm_offset_t addr = (vm_offset_t) argv; vm_offset_t r_addr; vm_size_t r_size; vm_prot_t r_protection, r_max_protection; vm_inherit_t r_inheritance; boolean_t r_is_shared; memory_object_name_t r_object_name; vm_offset_t r_offset; kern_return_t kr; r_addr = addr; kr = vm_region(my_task, &r_addr, &r_size, &r_protection, &r_max_protection, &r_inheritance, &r_is_shared, &r_object_name, &r_offset); if ((kr == KERN_SUCCESS) && MACH_PORT_VALID(r_object_name)) (void) mach_port_deallocate(my_task, r_object_name); if ((kr == KERN_SUCCESS) && (r_addr <= addr) && ((r_protection & (VM_PROT_READ|VM_PROT_WRITE)) == (VM_PROT_READ|VM_PROT_WRITE))) (void) vm_deallocate(my_task, r_addr, r_size); } #endif #if 0 /* Always stick around to handle swapon requests */ if (! doing_default_pager) task_terminate (mach_task_self ()); #endif /* * Become the default pager */ default_pager(); /*NOTREACHED*/ } /* Parse the boot script. */ parse_script (struct file *f) { char *p, *line, *buf; int amt, fd, err; int n = 0; buf = malloc (f->f_size); if (read_file (f, 0, buf, f->f_size, 0)) panic ("bootstrap: error reading boot script file"); line = p = buf; while (1) { while (p < buf + f->f_size && *p != '\n') p++; *p = '\0'; err = boot_script_parse_line (line); if (err) boot_panic (err); if (p == buf + f->f_size) break; line = ++p; } }