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