|
|
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.