diff options
author | Roland McGrath <roland@gnu.org> | 2001-08-17 09:03:24 +0000 |
---|---|---|
committer | Thomas Schwinge <tschwinge@gnu.org> | 2009-06-17 22:34:54 +0200 |
commit | 557e3882ef7ad2d9f601fd4c64dd69196637c16a (patch) | |
tree | 3d9f2a435f59228268712ba8758d1be303f5d564 /kern | |
parent | 44f46e79754be6ec06625f28a573abcfcf5d7b74 (diff) |
2001-08-17 Roland McGrath <roland@frob.com>
* kern/bootstrap.c: Largely rewritten, using Hurd boot_script code.
* kern/strings.c, kern/strings.h: Files removed.
* Makefile.in (kern-cfiles): Remove strings.c.
(kern-hfiles): Remove strings.h.
* kern/bootstrap.c: <kern/strings.h> -> <string.h>
Diffstat (limited to 'kern')
-rw-r--r-- | kern/bootstrap.c | 334 |
1 files changed, 256 insertions, 78 deletions
diff --git a/kern/bootstrap.c b/kern/bootstrap.c index 359842f1..231450da 100644 --- a/kern/bootstrap.c +++ b/kern/bootstrap.c @@ -37,22 +37,31 @@ #include "vm_param.h" #include <ipc/ipc_port.h> #include <kern/host.h> -#include <kern/strings.h> #include <kern/task.h> #include <kern/thread.h> #include <vm/vm_kern.h> #include <device/device_port.h> -#include <stdarg.h> - -#include <oskit/machine/multiboot.h> -#include <oskit/exec/exec.h> - #if MACH_KDB #include <machine/db_machdep.h> #include <ddb/db_sym.h> #endif +#if OSKIT_MACH +#include <stddef.h> +#include <string.h> +#include <oskit/machine/multiboot.h> +#include <oskit/exec/exec.h> +#include <oskit/c/stdio.h> +#define safe_gets(s, n) fgets((s),(n),stdin) +#else +#include <mach/machine/multiboot.h> +#include <mach/exec/exec.h> +#include <kern/strings.h> +#endif + +#include "../../hurd/boot/boot_script.h" + static mach_port_t boot_device_port; /* local name */ static mach_port_t boot_host_port; /* local name */ @@ -61,7 +70,8 @@ extern struct multiboot_info boot_info; extern char *kernel_cmdline; static void user_bootstrap(); /* forward */ -static void bootstrap_exec(void *exec_data); +static void user_bootstrap_compat(); /* forward */ +static void bootstrap_exec_compat(void *exec_data); /* forward */ static mach_port_t task_insert_send_right( @@ -85,25 +95,48 @@ task_insert_send_right( void bootstrap_create() { - struct multiboot_module *bmod; - - if (!(boot_info.flags & MULTIBOOT_MODS) - || (boot_info.mods_count == 0)) - panic("No bootstrap code loaded with the kernel!"); - if (boot_info.mods_count > 1) - printf("Warning: only one boot module currently used by Mach\n"); - bmod = (struct multiboot_module *)phystokv(boot_info.mods_addr); - bootstrap_exec((void*)phystokv(bmod->mod_start)); - - /* XXX at this point, we could free all the memory used - by the boot modules and the boot loader's descriptors and such. */ + struct multiboot_module *bmods = ((struct multiboot_module *) + phystokv(boot_info.mods_addr)); + + if (!(boot_info.flags & MULTIBOOT_MODS) + || (boot_info.mods_count == 0)) + panic ("No bootstrap code loaded with the kernel!"); + + if (boot_info.mods_count == 1 + && strchr((char*)phystokv(bmods[0].string), ' ') == 0) + { + printf("Loading single multiboot module in compat mode: %s\n", + (char*)phystokv(bmods[0].string)); + bootstrap_exec_compat((void*)phystokv(bmods[0].mod_start)); + } + else + { + int i, losers = 0; + for (i = 0; i < boot_info.mods_count; ++i) + { + char *line = (char*)phystokv(bmods[i].string); + int err = boot_script_parse_line (&bmods[i], line); + if (err) + { + printf ("ERROR: %s in multiboot module string: %s\n", + boot_script_error_string (err), line); + ++losers; + } + } + if (losers) + panic ("%d of %d boot script commands could not be parsed", + losers, boot_info.mods_count); + losers = boot_script_exec (); + if (losers) + panic ("ERROR in executing boot script: %s", + boot_script_error_string (losers)); + } + /* XXX at this point, we could free all the memory used + by the boot modules and the boot loader's descriptors and such. */ } -/* XXX won't work with more than one bootstrap service */ -static void *boot_exec; - static void -bootstrap_exec(void *e) +bootstrap_exec_compat(void *e) { task_t bootstrap_task; thread_t bootstrap_thread; @@ -130,8 +163,8 @@ bootstrap_exec(void *e) /* * Start the bootstrap thread. */ - boot_exec = e; - thread_start(bootstrap_thread, user_bootstrap); + bootstrap_thread->saved.other = e; + thread_start(bootstrap_thread, user_bootstrap_compat); (void) thread_resume(bootstrap_thread); } @@ -239,23 +272,35 @@ static boolean_t load_bootstrap_symbols = FALSE; -static int boot_read(void *handle, vm_offset_t file_ofs, void *buf, vm_size_t size, - vm_size_t *out_actual) +static int +boot_read(void *handle, vm_offset_t file_ofs, void *buf, vm_size_t size, + vm_size_t *out_actual) { - memcpy(buf, handle + file_ofs, size); - *out_actual = size; - return 0; + struct multiboot_module *mod = handle; + + if (mod->mod_start + file_ofs + size > mod->mod_end) + return -1; + + memcpy(buf, (const char*)mod->mod_start + file_ofs, size); + *out_actual = size; + return 0; } -static int read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size, +static int +read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size, vm_offset_t mem_addr, vm_size_t mem_size, exec_sectype_t sec_type) { + struct multiboot_module *mod = handle; + vm_map_t user_map = current_task()->map; vm_offset_t start_page, end_page; vm_prot_t mem_prot = sec_type & EXEC_SECTYPE_PROT_MASK; int err; + if (mod->mod_start + file_ofs + file_size > mod->mod_end) + return -1; + if (!(sec_type & EXEC_SECTYPE_ALLOC)) return 0; @@ -276,7 +321,8 @@ static int read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size, if (file_size > 0) { - err = copyout(handle + file_ofs, mem_addr, file_size); + err = copyout((char *)mod->mod_start + file_ofs, + mem_addr, file_size); assert(err == 0); } @@ -285,6 +331,8 @@ static int read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size, err = vm_protect(user_map, start_page, end_page - start_page, FALSE, mem_prot); assert(err == 0); } + + return 0; } static void copy_bootstrap(void *e, exec_info_t *boot_exec_info) @@ -336,53 +384,49 @@ static void copy_bootstrap(void *e, exec_info_t *boot_exec_info) extern vm_offset_t user_stack_low(); extern vm_offset_t set_user_regs(); -void -static build_args_and_stack(struct exec_info *boot_exec_info, ...) +static void +build_args_and_stack(struct exec_info *boot_exec_info, + char **argv, char **envp) { vm_offset_t stack_base; vm_size_t stack_size; - va_list argv_ptr; register char * arg_ptr; + int arg_count, envc; int arg_len; - int arg_count; - register char * arg_pos; int arg_item_len; char * string_pos; char * zero = (char *)0; - static const char cmdline_var[] = "MULTIBOOT_CMDLINE="; + int i; #define STACK_SIZE (64*1024) /* * Calculate the size of the argument list. */ - va_start(argv_ptr, boot_exec_info); arg_len = 0; arg_count = 0; - for (;;) { - arg_ptr = va_arg(argv_ptr, char *); - if (arg_ptr == 0) - break; - arg_count++; + while (argv[arg_count] != 0) { + arg_ptr = argv[arg_count++]; arg_len += strlen(arg_ptr) + 1; } - va_end(argv_ptr); - - if (kernel_cmdline[0] != '\0') - arg_len += sizeof cmdline_var + strlen (kernel_cmdline); + envc = 0; + if (envp != 0) + while (envp[envc] != 0) + arg_len += strlen (envp[envc++]) + 1; /* * Add space for: * arg count * pointers to arguments * trailing 0 pointer - * dummy 0 pointer to environment variables + * pointers to environment variables + * trailing 0 pointer * and align to integer boundary */ - arg_len += sizeof(integer_t) - + (3 + arg_count) * sizeof(char *); + arg_len += (sizeof(integer_t) + + (arg_count + 1 + envc + 1) * sizeof(char *)); arg_len = (arg_len + sizeof(integer_t) - 1) & ~(sizeof(integer_t)-1); /* @@ -401,10 +445,9 @@ static build_args_and_stack(struct exec_info *boot_exec_info, ...) /* * Start the strings after the arg-count and pointers */ - string_pos = arg_pos - + sizeof(integer_t) - + arg_count * sizeof(char *) - + 3 * sizeof(char *); + string_pos = (arg_pos + + sizeof(integer_t) + + (arg_count + 1 + envc + 1) * sizeof(char *)); /* * first the argument count @@ -417,9 +460,8 @@ static build_args_and_stack(struct exec_info *boot_exec_info, ...) /* * Then the strings and string pointers for each argument */ - va_start(argv_ptr, boot_exec_info); - while (--arg_count >= 0) { - arg_ptr = va_arg(argv_ptr, char *); + for (i = 0; i < arg_count; ++i) { + arg_ptr = argv[i]; arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */ /* set string pointer */ @@ -432,7 +474,6 @@ static build_args_and_stack(struct exec_info *boot_exec_info, ...) (void) copyout(arg_ptr, string_pos, arg_item_len); string_pos += arg_item_len; } - va_end(argv_ptr); /* * Null terminator for argv. @@ -441,9 +482,12 @@ static build_args_and_stack(struct exec_info *boot_exec_info, ...) arg_pos += sizeof(char *); /* - * If we have a command line, put it in an environment variable. + * Then the strings and string pointers for each environment variable */ - if (kernel_cmdline[0] != '\0') { + for (i = 0; i < envc; ++i) { + arg_ptr = envp[i]; + arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */ + /* set string pointer */ (void) copyout((char *)&string_pos, arg_pos, @@ -451,24 +495,19 @@ static build_args_and_stack(struct exec_info *boot_exec_info, ...) arg_pos += sizeof(char *); /* copy string */ - arg_ptr = (char *) cmdline_var; - arg_item_len = sizeof cmdline_var - 1; - (void) copyout(arg_ptr, string_pos, arg_item_len); - string_pos += arg_item_len; - - /* copy string */ - arg_ptr = kernel_cmdline; - arg_item_len = strlen(kernel_cmdline) + 1; (void) copyout(arg_ptr, string_pos, arg_item_len); string_pos += arg_item_len; } + /* * Null terminator for envp. */ (void) copyout((char *)&zero, arg_pos, sizeof(char *)); } -static void user_bootstrap() + +static void +user_bootstrap_compat() { exec_info_t boot_exec_info; @@ -480,7 +519,7 @@ static void user_bootstrap() /* * Copy the bootstrap code from boot_exec into the user task. */ - copy_bootstrap(boot_exec, &boot_exec_info); + copy_bootstrap(current_thread()->saved.other, &boot_exec_info); /* * Convert the host and device ports to strings, @@ -498,14 +537,27 @@ static void user_bootstrap() * Build the argument list and insert in the user task. * Argument list is * "bootstrap -<boothowto> <host_port> <device_port> <root_name>" + +$0 ${boot-args} ${host-port} ${device-port} ${root-device} $(task-create) $(task-resume) + */ - build_args_and_stack(&boot_exec_info, - "bootstrap", - flag_string, - host_string, - device_string, - root_string, - (char *)0); + { + char *argv[] = { "bootstrap", + flag_string, + host_string, + device_string, + root_string, + 0 }; + char *envp[] = { 0, 0 }; + if (kernel_cmdline[0] != '\0') + { + static const char cmdline_var[] = "MULTIBOOT_CMDLINE="; + envp[0] = alloca (sizeof cmdline_var + strlen (kernel_cmdline)); + memcpy (envp[0], cmdline_var, sizeof cmdline_var - 1); + strcpy (envp[0] + sizeof cmdline_var - 1, kernel_cmdline); + } + build_args_and_stack(&boot_exec_info, argv, envp); + } /* * Exit to user thread. @@ -513,3 +565,129 @@ static void user_bootstrap() thread_bootstrap_return(); /*NOTREACHED*/ } + + +struct user_bootstrap_info +{ + struct multiboot_module *mod; + char **argv; +}; + +int +boot_script_exec_cmd (void *hook, task_t task, char *path, int argc, + char **argv, char *strings, int stringlen) +{ + struct multiboot_module *mod = hook; + exec_info_t boot_exec_info; + + register vm_map_t user_map = current_task()->map; + int err; + + if (task != MACH_PORT_NULL) + { + struct user_bootstrap_info info = { hook, argv }; + thread_t thread; + err = thread_create ((task_t)task, &thread); + assert(err == 0); + thread->saved.other = &info; + thread_start (thread, user_bootstrap); + thread_resume (thread); + } +} + +static void user_bootstrap() +{ + struct user_bootstrap_info *info = current_thread()->saved.other; + exec_info_t boot_exec_info; + int err; + + /* Load this task up from the executable file in the module. */ + err = exec_load(boot_read, read_exec, info->mod, &boot_exec_info); + if (err) + panic ("Cannot load user executable module (error code %d): %s", + err, info->argv[0]); + + /* Set up the stack with arguments. */ + build_args_and_stack(&boot_exec_info, info->argv, 0); + + task_suspend (current_task()); + + /* + * Exit to user thread. + */ + thread_bootstrap_return(); + /*NOTREACHED*/ +} + + + +void * +boot_script_malloc (unsigned int size) +{ + return (void *) kalloc (size); +} + +void +boot_script_free (void *ptr, unsigned int size) +{ + kfree ((vm_offset_t)ptr, size); +} + +int +boot_script_task_create (struct cmd *cmd) +{ + kern_return_t rc = task_create(TASK_NULL, FALSE, &cmd->task); + if (rc) + { + printf("boot_script_task_create failed with %x", rc); + return BOOT_SCRIPT_MACH_ERROR; + } + return 0; +} + +int +boot_script_task_resume (struct cmd *cmd) +{ + kern_return_t rc = task_resume (cmd->task); + if (rc) + { + printf("boot_script_task_resume failed with %x", rc); + return BOOT_SCRIPT_MACH_ERROR; + } + return 0; +} + +int +boot_script_prompt_task_resume (struct cmd *cmd) +{ + char xx[5]; + + printf ("Hit return to resume %s...", cmd->path); + safe_gets (xx, sizeof xx); + + return boot_script_task_resume (cmd); +} + +void +boot_script_free_task (task_t task, int aborting) +{ + if (aborting) + task_terminate (task); +} + +int +boot_script_insert_right (struct cmd *cmd, mach_port_t port) +{ + kern_return_t rc = mach_port_insert_right(cmd->task->itk_space, port, + (ipc_object_t)port, + MACH_MSG_TYPE_COPY_SEND); + if (rc) + { + printf("boot_script_insert_right failed with %x", rc); + return BOOT_SCRIPT_MACH_ERROR; + } + return 0; +} + + +#include "../../hurd/boot/boot_script.c" |