FreeBSD/Linux Kernel Cross Reference
sys/kern/bootstrap.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1992-1989 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: bootstrap.c,v $
29 * Revision 2.31 93/03/26 17:54:41 mrt
30 * Changed boot_map to be palatable to vm_object_page_map().
31 * ANSIfied (except for varargs functions).
32 * [93/03/23 af]
33 *
34 * Revision 2.30 93/03/09 12:26:38 danner
35 * String protos.
36 * [93/03/07 af]
37 *
38 * Revision 2.29 93/02/05 07:51:14 danner
39 * Alpha like mips, has machdep init flags.
40 * [93/02/04 01:56:09 af]
41 *
42 * 64bit cleanup. Added a magic number to the boot label.
43 * Changed ovbcopy_ints to be quicker where it can.
44 * [92/11/30 af]
45 *
46 * Revision 2.28 92/08/03 17:36:37 jfriedl
47 * removed silly prototypes
48 * [92/08/02 jfriedl]
49 *
50 * Revision 2.27 92/05/21 17:12:55 jfriedl
51 * Removed unused variable 'port' from bootstrap_create().
52 * Cleanup to quiet gcc warnings.
53 * [92/05/16 jfriedl]
54 *
55 * Revision 2.26 92/05/04 11:26:09 danner
56 * Set load_bootstrap_symbols from bootstrap_symbols option file.
57 * [92/05/03 danner]
58 *
59 * Revision 2.25 92/04/01 19:33:06 rpd
60 * Fixed ovbcopy_ints to handle zero size.
61 * [92/03/13 rpd]
62 *
63 * Revision 2.24 92/02/26 13:12:51 elf
64 * Added protect in copy_bootstrap against zero size bss.
65 * [92/02/26 danner]
66 *
67 * Revision 2.23 92/02/19 16:46:30 elf
68 * Change -a switch into -q switch.
69 * Do not load the default-pager's symtable by default,
70 * it gets in the way of debugging UX.
71 * [92/02/10 17:50:23 af]
72 *
73 * Revision 2.22 92/02/18 18:00:12 elf
74 * Added global load_fault_in_text to force the faulting in of the
75 * bootstrap task text. Useful for debugging.
76 * [92/02/14 danner]
77 *
78 * Revision 2.21 92/01/03 20:13:43 dbg
79 * Move bootstrap code out to user space.
80 * Mac2 and iPSC-dependent code must be moved there also.
81 * [91/12/18 dbg]
82 *
83 * Revision 2.20 91/12/10 16:32:40 jsb
84 * Fixes from Intel
85 * [91/12/10 15:51:50 jsb]
86 *
87 * Revision 2.19 91/11/12 11:51:53 rvb
88 * Added task_insert_send_right.
89 * Changed BOOTSTRAP_MAP_SIZE to 4 meg.
90 * [91/11/12 rpd]
91 *
92 * Revision 2.18 91/09/12 16:37:49 bohman
93 * Made bootstrap task call mac2 machine dependent code before running
94 * 'startup', which is loaded from the UX file system. This needs to
95 * be handled more generally in the future.
96 * [91/09/11 17:07:59 bohman]
97 *
98 * Revision 2.17 91/08/28 11:14:22 jsb
99 * Changed msgh_kind to msgh_seqno.
100 * [91/08/10 rpd]
101 *
102 * Revision 2.16 91/08/03 18:18:45 jsb
103 * Moved bootstrap query earlier. Removed all NORMA specific code.
104 * [91/07/25 18:25:35 jsb]
105 *
106 * Revision 2.15 91/07/31 17:44:14 dbg
107 * Pass host port to boot_load_program and read_emulator_symbols.
108 * [91/07/30 17:02:40 dbg]
109 *
110 * Revision 2.14 91/07/01 08:24:54 jsb
111 * Removed notion of master/slave. Instead, refuse to start up
112 * a bootstrap task whenever startup_name is null.
113 * [91/06/29 16:48:14 jsb]
114 *
115 * Revision 2.13 91/06/19 11:55:57 rvb
116 * Ask for startup program to override default.
117 * [91/06/18 21:39:17 rvb]
118 *
119 * Revision 2.12 91/06/17 15:46:51 jsb
120 * Renamed NORMA conditionals.
121 * [91/06/17 10:49:04 jsb]
122 *
123 * Revision 2.11 91/06/06 17:06:53 jsb
124 * Allow slaves to act as masters (for now).
125 * [91/05/13 17:36:17 jsb]
126 *
127 * Revision 2.10 91/05/18 14:31:32 rpd
128 * Added argument to kernel_thread.
129 * [91/04/03 rpd]
130 *
131 * Revision 2.9 91/05/14 16:40:06 mrt
132 * Correcting copyright
133 *
134 * Revision 2.8 91/02/05 17:25:42 mrt
135 * Changed to new Mach copyright
136 * [91/02/01 16:11:22 mrt]
137 *
138 * Revision 2.7 90/12/14 11:01:58 jsb
139 * Changes to NORMA_BOOT support. Use real device port, not a proxy;
140 * new device forwarding code handles forwarding of requests.
141 * Have slave not bother starting bootstrap task if there is nothing
142 * for it to run.
143 * [90/12/13 21:37:57 jsb]
144 *
145 * Revision 2.6 90/09/28 16:55:30 jsb
146 * Added NORMA_BOOT support.
147 * [90/09/28 14:04:43 jsb]
148 *
149 * Revision 2.5 90/06/02 14:53:39 rpd
150 * Load emulator symbols.
151 * [90/05/11 16:58:37 rpd]
152 *
153 * Made bootstrap_task available externally.
154 * [90/04/05 rpd]
155 * Converted to new IPC.
156 * [90/03/26 22:03:39 rpd]
157 *
158 * Revision 2.4 90/01/11 11:43:02 dbg
159 * Initialize bootstrap print routines. Remove port number
160 * printout.
161 * [89/12/20 dbg]
162 *
163 * Revision 2.3 89/11/29 14:09:01 af
164 * Enlarged the bootstrap task's map to accomodate some unnamed
165 * greedy RISC box. Sigh.
166 * [89/11/07 af]
167 * Made root_name and startup_name non-preallocated, so that
168 * they can be changed at boot time on those machines like
169 * mips and Sun where the boot loader passes command line
170 * arguments to the kernel.
171 * [89/10/28 af]
172 *
173 * Revision 2.2 89/09/08 11:25:02 dbg
174 * Pass root partition name to default_pager_setup.
175 * [89/08/31 dbg]
176 *
177 * Assume that device service has already been created.
178 * Create bootstrap task here and give it the host and
179 * device ports.
180 * [89/08/01 dbg]
181 *
182 * Call default_pager_setup.
183 * [89/07/11 dbg]
184 *
185 * 12-Apr-89 David Golub (dbg) at Carnegie-Mellon University
186 * Removed console_port.
187 *
188 */
189 /*
190 * Bootstrap the various built-in servers.
191 */
192 #include <mach_kdb.h>
193 #include <bootstrap_symbols.h>
194
195 #include <mach/port.h>
196 #include <mach/message.h>
197 #include <mach/vm_param.h>
198 #include <ipc/ipc_port.h>
199 #include <kern/host.h>
200 #include <kern/strings.h>
201 #include <kern/task.h>
202 #include <kern/thread.h>
203 #include <vm/vm_kern.h>
204 #include <device/device_port.h>
205
206 #include <sys/varargs.h>
207
208 #include <mach/boot_info.h>
209
210 #if MACH_KDB
211 #include <machine/db_machdep.h>
212 #include <ddb/db_sym.h>
213 #endif
214
215 /*
216 * Bootstrap image is moved out of BSS at startup.
217 */
218
219 vm_offset_t boot_start = 0; /* pointer to bootstrap image */
220 vm_size_t boot_size = 0; /* size of bootstrap image */
221 vm_offset_t load_info_start = 0; /* pointer to bootstrap load info */
222 vm_size_t load_info_size = 0; /* size of bootstrap load info */
223 vm_offset_t kern_sym_start = 0; /* pointer to kernel symbols */
224 vm_size_t kern_sym_size = 0; /* size of kernel symbols */
225
226 #if DEBUG
227 load_info_print()
228 {
229 struct loader_info *lp = (struct loader_info *)load_info_start;
230
231 printf("Load info: text (%#x, %#x, %#x)\n",
232 lp->text_start, lp->text_size, lp->text_offset);
233 printf(" data (%#x, %#x, %#x)\n",
234 lp->data_start, lp->data_size, lp->data_offset);
235 printf(" bss (%#x)\n", lp->bss_size);
236 printf(" syms (%#x, %#x)\n",
237 lp->sym_offset, lp->sym_size);
238 printf(" entry(%#x, %#x)\n",
239 lp->entry_1, lp->entry_2);
240 }
241 #endif
242
243 /*
244 * Moves kernel symbol table, bootstrap image, and bootstrap
245 * load information out of BSS at startup. Returns the
246 * first unused address.
247 *
248 * PAGE_SIZE must be set.
249 *
250 * On some machines, this code must run before the page
251 * tables are set up, and therefore must be re-created
252 * in assembly language.
253 */
254
255 void
256 ovbcopy_ints(
257 vm_offset_t src,
258 vm_offset_t dst,
259 vm_size_t size)
260 {
261 register vm_size_t *srcp;
262 register vm_size_t *dstp;
263 register unsigned int count;
264
265 srcp = (vm_size_t *)(src + size);
266 dstp = (vm_size_t *)(dst + size);
267 count = size / sizeof(vm_size_t);
268
269 while (count-- != 0)
270 *--dstp = *--srcp;
271 }
272
273 extern char edata[]; /* start of BSS */
274 extern char end[]; /* end of BSS */
275
276 vm_offset_t
277 move_bootstrap()
278 {
279 register struct boot_info *bi = (struct boot_info *)edata;
280
281 /*
282 * Tolerate some "imprecision" in a certain linker
283 */
284 if (bi->magic_number != MACH_BOOT_INFO_MAGIC) {
285 register vm_size_t *addr, *erange;
286
287 addr = (vm_size_t *)edata;
288 erange = (vm_size_t *)(edata + PAGE_SIZE);
289 while (addr < erange) {
290 bi = (struct boot_info *) ++addr;
291 if (bi->magic_number == MACH_BOOT_INFO_MAGIC)
292 break;
293 }
294 if (bi->magic_number != MACH_BOOT_INFO_MAGIC)
295 return 0; /* good luck.. */
296 }
297
298 kern_sym_start = (vm_offset_t) end;
299 kern_sym_size = bi->sym_size;
300 /*
301 * Align start of bootstrap on page boundary,
302 * to allow mapping into user space.
303 */
304 boot_start = round_page(kern_sym_start + kern_sym_size);
305 boot_size = bi->boot_size;
306 load_info_start = boot_start + boot_size;
307 load_info_size = bi->load_info_size;
308
309 ovbcopy_ints((vm_offset_t)bi + sizeof(struct boot_info) + kern_sym_size,
310 boot_start,
311 boot_size + load_info_size);
312
313 ovbcopy_ints((vm_offset_t)bi + sizeof(struct boot_info),
314 kern_sym_start,
315 kern_sym_size);
316
317 return boot_start + boot_size + load_info_size;
318 }
319
320 /*
321
322 */
323 mach_port_t boot_device_port; /* local name */
324 mach_port_t boot_host_port; /* local name */
325
326 void user_bootstrap(); /* forward */
327
328 extern char *root_name;
329
330 mach_port_t
331 task_insert_send_right(
332 task_t task,
333 ipc_port_t port)
334 {
335 mach_port_t name;
336
337 for (name = 1;; name++) {
338 kern_return_t kr;
339
340 kr = mach_port_insert_right(task->itk_space, name,
341 (ipc_object_t)port, MACH_MSG_TYPE_PORT_SEND);
342 if (kr == KERN_SUCCESS)
343 break;
344 assert(kr == KERN_NAME_EXISTS);
345 }
346
347 return name;
348 }
349
350 void bootstrap_create()
351 {
352 task_t bootstrap_task;
353 thread_t bootstrap_thread;
354
355 if (boot_size == 0) {
356 printf("Not starting bootstrap task.\n");
357 return;
358 }
359
360 /*
361 * Create the bootstrap task.
362 */
363
364 (void) task_create(TASK_NULL, FALSE, &bootstrap_task);
365 (void) thread_create(bootstrap_task, &bootstrap_thread);
366
367 /*
368 * Insert send rights to the master host and device ports.
369 */
370
371 boot_host_port =
372 task_insert_send_right(bootstrap_task,
373 ipc_port_make_send(realhost.host_priv_self));
374
375 boot_device_port =
376 task_insert_send_right(bootstrap_task,
377 ipc_port_make_send(master_device_port));
378
379 /*
380 * Start the bootstrap thread.
381 */
382 thread_start(bootstrap_thread, user_bootstrap);
383 (void) thread_resume(bootstrap_thread);
384 }
385
386 /*
387 * The following code runs as the kernel mode portion of the
388 * first user thread.
389 */
390
391 /*
392 * Convert an unsigned integer to its decimal representation.
393 */
394 void
395 itoa(
396 char *str,
397 vm_size_t num)
398 {
399 char buf[sizeof(vm_size_t)*2+3];
400 register char *np;
401
402 np = buf + sizeof(buf);
403 *--np = 0;
404
405 do {
406 *--np = '' + num % 10;
407 num /= 10;
408 } while (num != 0);
409
410 strcpy(str, np);
411 }
412
413 /*
414 * Parse the boot flags into an argument string.
415 * Format as a standard flag argument: '-qsdn...'
416 */
417 #include <sys/reboot.h>
418
419 static void
420 get_boot_flags(
421 char str[]) /* OUT */
422 {
423 register char *cp;
424 register int bflag;
425
426 #if defined(mips) || defined(alpha)
427
428 extern char *machine_get_boot_flags();
429 cp = machine_get_boot_flags(str);
430 #else
431 cp = str;
432 *cp++ = '-';
433 #endif
434
435 bflag = boothowto;
436
437 if (bflag & RB_ASKNAME)
438 *cp++ = 'q';
439 if (bflag & RB_SINGLE)
440 *cp++ = 's';
441 #if MACH_KDB
442 if (bflag & RB_KDB)
443 *cp++ = 'd';
444 #endif MACH_KDB
445 if (bflag & RB_INITNAME)
446 *cp++ = 'n';
447
448 if (cp == &str[1]) /* no flags */
449 *cp++ = 'x';
450 *cp = '\0';
451 }
452
453 /*
454 * Copy boot_data (executable) to the user portion of this task.
455 */
456 boolean_t load_protect_text = TRUE;
457 #if MACH_KDB
458 /* if set, fault in the text segment */
459 boolean_t load_fault_in_text = TRUE;
460 #endif
461
462 vm_offset_t
463 boot_map(
464 void * data, /* private data */
465 vm_offset_t offset) /* offset to map */
466 {
467 vm_offset_t start_offset = (vm_offset_t) data;
468
469 return pmap_extract(kernel_pmap, start_offset + offset);
470 }
471
472
473 #if BOOTSTRAP_SYMBOLS
474 boolean_t load_bootstrap_symbols = TRUE;
475 #else
476 boolean_t load_bootstrap_symbols = FALSE;
477 #endif
478
479
480
481 void
482 copy_bootstrap(
483 vm_offset_t *entry)
484 {
485 struct loader_info *lp;
486 vm_offset_t text_page_start,
487 text_page_end,
488 data_page_start,
489 bss_start,
490 bss_page_start,
491 bss_page_end;
492
493 register vm_map_t user_map = current_task()->map;
494 vm_object_t boot_object;
495 vm_size_t bss_size;
496
497 /*
498 * Point to bootstrap load information.
499 */
500 lp = (struct loader_info *)load_info_start;
501
502 /*
503 * We assume that makeboot has aligned the various
504 * pieces of the bootstrap image on page boundaries.
505 */
506 assert(lp->text_start == trunc_page(lp->text_start));
507 assert(lp->data_start == trunc_page(lp->data_start));
508 assert(lp->text_offset == trunc_page(lp->text_offset));
509 assert(lp->data_offset == trunc_page(lp->data_offset)
510 || lp->data_offset == lp->text_offset + lp->text_size);
511
512 /*
513 * Find how much virtual space we have to allocate.
514 */
515 text_page_start = trunc_page(lp->text_start);
516 text_page_end = round_page(lp->text_start + lp->text_size);
517 data_page_start = trunc_page(lp->data_start);
518 bss_start = lp->data_start + lp->data_size;
519 bss_page_start = trunc_page(bss_start);
520 bss_page_end = round_page(bss_start + lp->bss_size);
521 bss_size = bss_page_end - bss_page_start;
522
523
524 /*
525 * Create an object that maps the pages in the
526 * bootstrap image. Map only until the end of the last
527 * whole page.
528 */
529 boot_size = lp->data_offset + bss_page_start - lp->data_start;
530 boot_object = vm_object_allocate(boot_size);
531 vm_object_page_map(boot_object,
532 (vm_offset_t) 0, /* from boot_start */
533 boot_size,
534 boot_map,
535 (char *)boot_start);
536
537 /*
538 * Map the text and data from the boot image into
539 * the user task. Map the data area only through
540 * the last whole page of data - the next page of
541 * data is split between data and bss, and must be
542 * partially cleared.
543 */
544
545 if (text_page_end >= data_page_start) {
546 /*
547 * One contiguous area for text and data.
548 */
549 (void) vm_map_enter(user_map,
550 &text_page_start,
551 (vm_size_t) (bss_page_start - text_page_start),
552 (vm_offset_t) 0, FALSE,
553 boot_object,
554 lp->text_offset,
555 FALSE,
556 VM_PROT_READ | VM_PROT_WRITE,
557 VM_PROT_ALL,
558 VM_INHERIT_DEFAULT);
559
560 }
561 else {
562 /*
563 * Separated text and data areas.
564 */
565 (void) vm_map_enter(user_map,
566 &text_page_start,
567 (vm_size_t)(text_page_end - text_page_start),
568 (vm_offset_t) 0, FALSE,
569 boot_object,
570 lp->text_offset,
571 FALSE,
572 VM_PROT_READ | VM_PROT_WRITE,
573 VM_PROT_ALL,
574 VM_INHERIT_DEFAULT);
575
576 (void) vm_map_enter(user_map,
577 &data_page_start,
578 (vm_size_t)(bss_page_start - data_page_start),
579 (vm_offset_t) 0, FALSE,
580 boot_object,
581 lp->data_offset,
582 FALSE,
583 VM_PROT_READ | VM_PROT_WRITE,
584 VM_PROT_ALL,
585 VM_INHERIT_DEFAULT);
586 }
587
588
589 /*
590 * Allocate the remainder of the data segment and all
591 * of the BSS. Protect against zero size bss.
592 */
593 if (bss_size)
594 {
595 (void) vm_allocate(user_map, &bss_page_start,
596 (vm_size_t)(bss_size), FALSE);
597
598 /*
599 * If the data segment does not end on a VM page boundary,
600 * we copy the end of the data segment onto a new page
601 * so that the bss segment will be zero, and so that
602 * we do not overwrite the bootstrap symbol table.
603 */
604 if (bss_start > bss_page_start) {
605 (void) copyout((char *) boot_start +
606 lp->data_offset +
607 lp->data_size -
608 (bss_start - bss_page_start),
609 (char *)bss_page_start,
610 bss_start - bss_page_start);
611 }
612 }
613
614 /*
615 * Protect the text.
616 */
617 if (load_protect_text)
618 (void) vm_protect(user_map,
619 text_page_start,
620 (vm_size_t)(trunc_page(lp->text_start+lp->text_size)
621 - text_page_start),
622 FALSE,
623 VM_PROT_READ|VM_PROT_EXECUTE);
624
625 #if MACH_KDB
626 /*
627 * Enter the bootstrap symbol table.
628 */
629
630 if (load_bootstrap_symbols)
631 (void) X_db_sym_init(
632 (char*) boot_start+lp->sym_offset,
633 (char*) boot_start+lp->sym_offset+lp->sym_size,
634 "bootstrap",
635 (char *) user_map);
636
637 if (load_fault_in_text)
638 {
639 vm_offset_t lenp = round_page(lp->text_start+lp->text_size) -
640 trunc_page(lp->text_start);
641 vm_offset_t i = 0;
642
643 while (i < lenp)
644 {
645 vm_fault(user_map, text_page_start +i,
646 load_protect_text ?
647 VM_PROT_READ|VM_PROT_EXECUTE :
648 VM_PROT_READ|VM_PROT_EXECUTE | VM_PROT_WRITE,
649 0,0,0);
650 i = round_page (i+1);
651 }
652 }
653
654
655 #endif MACH_KDB
656 /*
657 * Return the entry points.
658 */
659 entry[0] = lp->entry_1;
660 entry[1] = lp->entry_2;
661 }
662
663 /*
664 * Allocate the stack, and build the argument list.
665 */
666 extern vm_offset_t user_stack_low();
667 extern vm_offset_t set_user_regs();
668
669 void
670 build_args_and_stack(entry, va_alist)
671 vm_offset_t entry;
672 va_dcl
673 {
674 vm_offset_t stack_base;
675 vm_size_t stack_size;
676 va_list argv_ptr;
677 register
678 char * arg_ptr;
679 int arg_len;
680 int arg_count;
681 register
682 char * arg_pos;
683 int arg_item_len;
684 char * string_pos;
685 char * zero = (char *)0;
686
687 #define STACK_SIZE (64*1024)
688
689 /*
690 * Calculate the size of the argument list.
691 */
692 va_start(argv_ptr);
693 arg_len = 0;
694 arg_count = 0;
695 for (;;) {
696 arg_ptr = va_arg(argv_ptr, char *);
697 if (arg_ptr == 0)
698 break;
699 arg_count++;
700 arg_len += strlen(arg_ptr) + 1;
701 }
702 va_end(argv_ptr);
703
704 /*
705 * Add space for:
706 * arg count
707 * pointers to arguments
708 * trailing 0 pointer
709 * dummy 0 pointer to environment variables
710 * and align to integer boundary
711 */
712 arg_len += sizeof(integer_t)
713 + (2 + arg_count) * sizeof(char *);
714 arg_len = (arg_len + sizeof(integer_t) - 1) & ~(sizeof(integer_t)-1);
715
716 /*
717 * Allocate the stack.
718 */
719 stack_size = round_page(STACK_SIZE);
720 stack_base = user_stack_low(stack_size);
721 (void) vm_allocate(current_task()->map,
722 &stack_base,
723 stack_size,
724 FALSE);
725
726 arg_pos = (char *)
727 set_user_regs(stack_base, stack_size, entry, arg_len);
728
729 /*
730 * Start the strings after the arg-count and pointers
731 */
732 string_pos = arg_pos
733 + sizeof(integer_t)
734 + arg_count * sizeof(char *)
735 + 2 * sizeof(char *);
736
737 /*
738 * first the argument count
739 */
740 (void) copyout((char *)&arg_count,
741 arg_pos,
742 sizeof(integer_t));
743 arg_pos += sizeof(integer_t);
744
745 /*
746 * Then the strings and string pointers for each argument
747 */
748 va_start(argv_ptr);
749 while (--arg_count >= 0) {
750 arg_ptr = va_arg(argv_ptr, char *);
751 arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */
752
753 /* set string pointer */
754 (void) copyout((char *)&string_pos,
755 arg_pos,
756 sizeof (char *));
757 arg_pos += sizeof(char *);
758
759 /* copy string */
760 (void) copyout(arg_ptr, string_pos, arg_item_len);
761 string_pos += arg_item_len;
762 }
763 va_end(argv_ptr);
764
765 /*
766 * last, the trailing 0 argument and a null environment pointer.
767 */
768 (void) copyout((char *)&zero, arg_pos, sizeof(char *));
769 arg_pos += sizeof(char *);
770 (void) copyout((char *)&zero, arg_pos, sizeof(char *));
771 }
772
773 void user_bootstrap()
774 {
775 vm_offset_t entry[2];
776
777 char host_string[12];
778 char device_string[12];
779 char flag_string[12];
780
781 /*
782 * Copy the bootstrap code from boot_data to the user task.
783 */
784 copy_bootstrap(entry);
785
786 /*
787 * Convert the host and device ports to strings,
788 * to put in the argument list.
789 */
790 itoa(host_string, boot_host_port);
791 itoa(device_string, boot_device_port);
792
793 /*
794 * Get the boot flags, also
795 */
796 get_boot_flags(flag_string);
797
798 /*
799 * Build the argument list and insert in the user task.
800 * Argument list is
801 * "bootstrap -<boothowto> <host_port> <device_port> <root_name>"
802 */
803 build_args_and_stack(entry,
804 "bootstrap",
805 flag_string,
806 host_string,
807 device_string,
808 root_name,
809 (char *)0);
810
811 /*
812 * Exit to user thread.
813 */
814 thread_bootstrap_return();
815 /*NOTREACHED*/
816 }
817
Cache object: 3b9453ce8e82716744515861e85d216a
|