]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
23 | * @OSF_COPYRIGHT@ | |
24 | */ | |
25 | /* | |
26 | * Mach Operating System | |
27 | * Copyright (c) 1991,1990,1989, 1988 Carnegie Mellon University | |
28 | * All Rights Reserved. | |
29 | * | |
30 | * Permission to use, copy, modify and distribute this software and its | |
31 | * documentation is hereby granted, provided that both the copyright | |
32 | * notice and this permission notice appear in all copies of the | |
33 | * software, derivative works or modified versions, and any portions | |
34 | * thereof, and that both notices appear in supporting documentation. | |
35 | * | |
36 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
37 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
38 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
39 | * | |
40 | * Carnegie Mellon requests users of this software to return to | |
41 | * | |
42 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
43 | * School of Computer Science | |
44 | * Carnegie Mellon University | |
45 | * Pittsburgh PA 15213-3890 | |
46 | * | |
47 | * any improvements or extensions that they make and grant Carnegie Mellon | |
48 | * the rights to redistribute these changes. | |
49 | */ | |
50 | ||
51 | /* | |
52 | */ | |
53 | ||
54 | /* | |
55 | * File: model_dep.c | |
56 | * Author: Avadis Tevanian, Jr., Michael Wayne Young | |
57 | * | |
58 | * Copyright (C) 1986, Avadis Tevanian, Jr., Michael Wayne Young | |
59 | * | |
60 | * Basic initialization for I386 - ISA bus machines. | |
61 | */ | |
62 | ||
63 | #include <cpus.h> | |
64 | #include <platforms.h> | |
65 | #include <mp_v1_1.h> | |
66 | #include <mach_kdb.h> | |
67 | #include <himem.h> | |
68 | #include <fast_idle.h> | |
69 | ||
70 | #include <mach/i386/vm_param.h> | |
71 | ||
72 | #include <string.h> | |
73 | #include <mach/vm_param.h> | |
74 | #include <mach/vm_prot.h> | |
75 | #include <mach/machine.h> | |
76 | #include <mach/time_value.h> | |
77 | #include <kern/etap_macros.h> | |
78 | #include <kern/spl.h> | |
79 | #include <kern/assert.h> | |
80 | #include <kern/debug.h> | |
81 | #include <kern/misc_protos.h> | |
82 | #include <kern/startup.h> | |
83 | #include <kern/clock.h> | |
84 | #include <kern/time_out.h> | |
85 | #include <kern/xpr.h> | |
86 | #include <kern/cpu_data.h> | |
87 | #include <vm/vm_page.h> | |
88 | #include <vm/pmap.h> | |
89 | #include <vm/vm_kern.h> | |
90 | #include <i386/fpu.h> | |
91 | #include <i386/pmap.h> | |
92 | #include <i386/ipl.h> | |
93 | #include <i386/pio.h> | |
94 | #include <i386/misc_protos.h> | |
95 | #include <i386/cpuid.h> | |
96 | #include <i386/rtclock_entries.h> | |
97 | #include <i386/AT386/mp/mp.h> | |
98 | #if MACH_KDB | |
99 | #include <ddb/db_aout.h> | |
100 | #endif /* MACH_KDB */ | |
101 | #include <ddb/tr.h> | |
102 | #ifdef __MACHO__ | |
103 | #include <i386/AT386/kernBootStruct.h> | |
104 | #include <mach/boot_info.h> | |
105 | #include <mach/thread_status.h> | |
106 | #endif | |
107 | ||
108 | #if NCPUS > 1 | |
109 | #include <i386/mp_desc.h> | |
110 | #endif /* NCPUS */ | |
111 | ||
112 | #if MP_V1_1 | |
113 | #include <i386/AT386/mp/mp_v1_1.h> | |
114 | #endif /* MP_V1_1 */ | |
115 | ||
116 | vm_size_t mem_size = 0; | |
117 | vm_offset_t first_addr = 0; /* set by start.s - keep out of bss */ | |
118 | vm_offset_t first_avail = 0;/* first after page tables */ | |
119 | vm_offset_t last_addr; | |
120 | ||
121 | vm_offset_t avail_start, avail_end; | |
122 | vm_offset_t virtual_avail, virtual_end; | |
123 | vm_offset_t hole_start, hole_end; | |
124 | vm_offset_t avail_next; | |
125 | unsigned int avail_remaining; | |
126 | ||
127 | /* parameters passed from bootstrap loader */ | |
128 | int cnvmem = 0; /* must be in .data section */ | |
129 | int extmem = 0; | |
130 | ||
131 | /* FIXME!! REMOVE WHEN OSFMK DEVICES ARE COMPLETELY PULLED OUT */ | |
132 | int dev_name_count = 0; | |
133 | int dev_name_list = 0; | |
134 | ||
135 | #ifndef __MACHO__ | |
136 | extern char edata, end; | |
137 | #endif | |
138 | ||
139 | extern char version[]; | |
140 | ||
141 | int rebootflag = 0; /* exported to kdintr */ | |
142 | ||
143 | ||
144 | void parse_arguments(void); | |
145 | const char *getenv(const char *); | |
146 | ||
147 | #define BOOT_LINE_LENGTH 160 | |
148 | char boot_string_store[BOOT_LINE_LENGTH] = {0}; | |
149 | char *boot_string = (char *)0; | |
150 | int boot_string_sz = BOOT_LINE_LENGTH; | |
151 | int boottype = 0; | |
152 | ||
153 | #if __MACHO__ | |
154 | #include <mach-o/loader.h> | |
155 | vm_offset_t edata, etext, end; | |
156 | ||
157 | extern struct mach_header _mh_execute_header; | |
158 | void *sectTEXTB; int sectSizeTEXT; | |
159 | void *sectDATAB; int sectSizeDATA; | |
160 | void *sectOBJCB; int sectSizeOBJC; | |
161 | void *sectLINKB; int sectSizeLINK; | |
162 | ||
163 | /* Kernel boot information */ | |
164 | KERNBOOTSTRUCT kernBootStructData; | |
165 | KERNBOOTSTRUCT *kernBootStruct; | |
166 | #endif | |
167 | ||
168 | vm_offset_t kern_args_start = 0; /* kernel arguments */ | |
169 | vm_size_t kern_args_size = 0; /* size of kernel arguments */ | |
170 | ||
171 | #ifdef __MACHO__ | |
172 | ||
173 | unsigned long | |
174 | i386_preinit() | |
175 | { | |
176 | int i; | |
177 | struct segment_command *sgp; | |
178 | struct section *sp; | |
179 | ||
180 | sgp = (struct segment_command *) getsegbyname("__DATA"); | |
181 | if (sgp) { | |
182 | sp = (struct section *) firstsect(sgp); | |
183 | if (sp) { | |
184 | do { | |
185 | if (sp->flags & S_ZEROFILL) | |
186 | bzero((char *) sp->addr, sp->size); | |
187 | } while (sp = (struct section *)nextsect(sgp, sp)); | |
188 | } | |
189 | } | |
190 | ||
191 | ||
192 | bcopy((char *) KERNSTRUCT_ADDR, (char *) &kernBootStructData, | |
193 | sizeof(kernBootStructData)); | |
194 | ||
195 | kernBootStruct = &kernBootStructData; | |
196 | ||
197 | end = getlastaddr(); | |
198 | ||
199 | for (i = 0; i < kernBootStruct->numBootDrivers; i++) | |
200 | end += kernBootStruct->driverConfig[i].size; | |
201 | ||
202 | end = round_page(end); | |
203 | ||
204 | return end; | |
205 | } | |
206 | #endif | |
207 | ||
208 | /* | |
209 | * Cpu initialization. Running virtual, but without MACH VM | |
210 | * set up. First C routine called. | |
211 | */ | |
212 | void | |
213 | machine_startup(void) | |
214 | { | |
215 | ||
216 | #ifdef __MACHO__ | |
217 | ||
218 | ||
219 | /* Now copy over various bits.. */ | |
220 | cnvmem = kernBootStruct->convmem; | |
221 | extmem = kernBootStruct->extmem; | |
222 | kern_args_start = (vm_offset_t) kernBootStruct->bootString; | |
223 | kern_args_size = strlen(kernBootStruct->bootString); | |
224 | boottype = kernBootStruct->rootdev; | |
225 | ||
226 | /* Now retrieve addresses for end, edata, and etext | |
227 | * from MACH-O headers. | |
228 | */ | |
229 | ||
230 | sectTEXTB = (void *) getsegdatafromheader( | |
231 | &_mh_execute_header, "__TEXT", §SizeTEXT); | |
232 | sectDATAB = (void *) getsegdatafromheader( | |
233 | &_mh_execute_header, "__DATA", §SizeDATA); | |
234 | sectOBJCB = (void *) getsegdatafromheader( | |
235 | &_mh_execute_header, "__OBJC", §SizeOBJC); | |
236 | sectLINKB = (void *) getsegdatafromheader( | |
237 | &_mh_execute_header, "__LINKEDIT", §SizeLINK); | |
238 | ||
239 | etext = (vm_offset_t) sectTEXTB + sectSizeTEXT; | |
240 | edata = (vm_offset_t) sectDATAB + sectSizeDATA; | |
241 | #endif | |
242 | ||
243 | /* | |
244 | * Parse startup arguments | |
245 | */ | |
246 | parse_arguments(); | |
247 | ||
248 | disableDebugOuput = FALSE; | |
249 | debug_mode = TRUE; | |
250 | ||
251 | printf_init(); /* Init this in case we need debugger */ | |
252 | panic_init(); /* Init this in case we need debugger */ | |
253 | ||
254 | PE_init_platform(FALSE, kernBootStruct); | |
255 | PE_init_kprintf(FALSE); | |
256 | PE_init_printf(FALSE); | |
257 | ||
258 | /* | |
259 | * Do basic VM initialization | |
260 | */ | |
261 | i386_init(); | |
262 | ||
263 | PE_init_platform(TRUE, kernBootStruct); | |
264 | PE_init_kprintf(TRUE); | |
265 | PE_init_printf(TRUE); | |
266 | ||
267 | #if MACH_KDB | |
268 | ||
269 | /* | |
270 | * Initialize the kernel debugger. | |
271 | */ | |
272 | ddb_init(); | |
273 | ||
274 | /* | |
275 | * Cause a breakpoint trap to the debugger before proceeding | |
276 | * any further if the proper option bit was specified in | |
277 | * the boot flags. | |
278 | * | |
279 | * XXX use -a switch to invoke kdb, since there's no | |
280 | * boot-program switch to turn on RB_HALT! | |
281 | */ | |
282 | ||
283 | if (halt_in_debugger) { | |
284 | printf("inline call to debugger(machine_startup)\n"); | |
285 | Debugger("inline call"); | |
286 | } | |
287 | #endif /* MACH_KDB */ | |
288 | TR_INIT(); | |
289 | ||
290 | printf(version); | |
291 | ||
292 | machine_slot[0].is_cpu = TRUE; | |
293 | machine_slot[0].running = TRUE; | |
294 | #ifdef MACH_BSD | |
295 | /* FIXME */ | |
296 | machine_slot[0].cpu_type = CPU_TYPE_I386; | |
297 | machine_slot[0].cpu_subtype = CPU_SUBTYPE_PENTPRO; | |
298 | #else | |
299 | machine_slot[0].cpu_type = cpuid_cputype(0); | |
300 | machine_slot[0].cpu_subtype = CPU_SUBTYPE_AT386; | |
301 | #endif | |
302 | ||
303 | /* | |
304 | * Start the system. | |
305 | */ | |
306 | #if NCPUS > 1 | |
307 | mp_desc_init(0); | |
308 | #endif /* NCPUS */ | |
309 | ||
310 | setup_main(); | |
311 | } | |
312 | ||
313 | ||
314 | vm_offset_t env_start = 0; /* environment */ | |
315 | vm_size_t env_size = 0; /* size of environment */ | |
316 | ||
317 | /* | |
318 | * Parse command line arguments. | |
319 | */ | |
320 | void | |
321 | parse_arguments(void) | |
322 | { | |
323 | char *p = (char *) kern_args_start; | |
324 | char *endp = (char *) kern_args_start + kern_args_size - 1; | |
325 | char ch; | |
326 | ||
327 | if (kern_args_start == 0) | |
328 | return; | |
329 | while (p < endp) { | |
330 | if (*p++ != '-') { | |
331 | while (*p++ != '\0') | |
332 | ; | |
333 | continue; | |
334 | } | |
335 | while (ch = *p++) { | |
336 | switch (ch) { | |
337 | case 'h': | |
338 | halt_in_debugger = 1; | |
339 | break; | |
340 | case 'm': /* -m??: memory size Mbytes*/ | |
341 | mem_size = atoi_term(p, &p)*1024*1024; | |
342 | break; | |
343 | case 'k': /* -k??: memory size Kbytes */ | |
344 | mem_size = atoi_term(p, &p)*1024; | |
345 | break; | |
346 | default: | |
347 | #if NCPUS > 1 && AT386 | |
348 | if (ch > '0' && ch <= '9') | |
349 | wncpu = ch - '0'; | |
350 | #endif /* NCPUS > 1 && AT386 */ | |
351 | break; | |
352 | } | |
353 | } | |
354 | } | |
355 | } | |
356 | ||
357 | const char * | |
358 | getenv(const char *name) | |
359 | { | |
360 | int len = strlen(name); | |
361 | const char *p = (const char *)env_start; | |
362 | const char *endp = p + env_size; | |
363 | ||
364 | while (p < endp) { | |
365 | if (len >= endp - p) | |
366 | break; | |
367 | if (strncmp(name, p, len) == 0 && *(p + len) == '=') | |
368 | return p + len + 1; | |
369 | while (*p++) | |
370 | ; | |
371 | } | |
372 | return NULL; | |
373 | } | |
374 | ||
375 | extern void | |
376 | calibrate_delay(void); | |
377 | ||
378 | /* | |
379 | * Find devices. The system is alive. | |
380 | */ | |
381 | void | |
382 | machine_init(void) | |
383 | { | |
384 | int unit; | |
385 | const char *p; | |
386 | int n; | |
387 | ||
388 | /* | |
389 | * Adjust delay count before entering drivers | |
390 | */ | |
391 | ||
392 | calibrate_delay(); | |
393 | ||
394 | /* | |
395 | * Display CPU identification | |
396 | */ | |
397 | cpuid_cpu_display("CPU identification", 0); | |
398 | cpuid_cache_display("CPU configuration", 0); | |
399 | ||
400 | #if MP_V1_1 | |
401 | mp_v1_1_init(); | |
402 | #endif /* MP_V1_1 */ | |
403 | ||
404 | /* | |
405 | * Set up to use floating point. | |
406 | */ | |
407 | init_fpu(); | |
408 | ||
409 | #if 0 | |
410 | #if NPCI > 0 | |
411 | dma_zones_init(); | |
412 | #endif /* NPCI > 0 */ | |
413 | #endif | |
414 | ||
415 | /* | |
416 | * Configure clock devices. | |
417 | */ | |
418 | clock_config(); | |
419 | } | |
420 | ||
421 | /* | |
422 | * Halt a cpu. | |
423 | */ | |
424 | void | |
425 | halt_cpu(void) | |
426 | { | |
427 | halt_all_cpus(FALSE); | |
428 | } | |
429 | ||
430 | int reset_mem_on_reboot = 1; | |
431 | ||
432 | /* | |
433 | * Halt the system or reboot. | |
434 | */ | |
435 | void | |
436 | halt_all_cpus( | |
437 | boolean_t reboot) | |
438 | { | |
439 | if (reboot) { | |
440 | /* | |
441 | * Tell the BIOS not to clear and test memory. | |
442 | */ | |
443 | if (! reset_mem_on_reboot) | |
444 | *(unsigned short *)phystokv(0x472) = 0x1234; | |
445 | ||
446 | kdreboot(); | |
447 | } | |
448 | else { | |
449 | rebootflag = 1; | |
450 | printf("In tight loop: hit ctl-alt-del to reboot\n"); | |
451 | (void) spllo(); | |
452 | } | |
453 | for (;;) | |
454 | continue; | |
455 | } | |
456 | ||
457 | /* | |
458 | * Basic VM initialization. | |
459 | */ | |
460 | ||
461 | void | |
462 | i386_init(void) | |
463 | { | |
464 | int i,j; /* Standard index vars. */ | |
465 | vm_size_t bios_hole_size; | |
466 | ||
467 | #ifndef __MACHO__ | |
468 | /* | |
469 | * Zero the BSS. | |
470 | */ | |
471 | ||
472 | bzero((char *)&edata,(unsigned)(&end - &edata)); | |
473 | #endif | |
474 | ||
475 | boot_string = &boot_string_store[0]; | |
476 | ||
477 | /* | |
478 | * Initialize the pic prior to any possible call to an spl. | |
479 | */ | |
480 | ||
481 | set_cpu_model(); | |
482 | vm_set_page_size(); | |
483 | ||
484 | /* | |
485 | * Initialize the Event Trace Analysis Package | |
486 | * Static Phase: 1 of 2 | |
487 | */ | |
488 | etap_init_phase1(); | |
489 | ||
490 | /* | |
491 | * Compute the memory size. | |
492 | */ | |
493 | ||
494 | #if 1 | |
495 | /* FIXME | |
496 | * fdisk needs to change to use a sysctl instead of | |
497 | * opening /dev/kmem and reading out the kernboot structure | |
498 | */ | |
499 | ||
500 | first_addr = (char *)(KERNSTRUCT_ADDR) + sizeof(KERNBOOTSTRUCT); | |
501 | #else | |
502 | #if NCPUS > 1 | |
503 | first_addr = 0x1000; | |
504 | #else | |
505 | /* First two pages are used to boot the other cpus. */ | |
506 | /* TODO - reclaim pages after all cpus have booted */ | |
507 | ||
508 | first_addr = 0x3000; | |
509 | #endif | |
510 | #endif | |
511 | ||
512 | /* BIOS leaves data in low memory */ | |
513 | last_addr = 1024*1024 + extmem*1024; | |
514 | /* extended memory starts at 1MB */ | |
515 | ||
516 | bios_hole_size = 1024*1024 - trunc_page((vm_offset_t)(1024 * cnvmem)); | |
517 | ||
518 | /* | |
519 | * Initialize for pmap_free_pages and pmap_next_page. | |
520 | * These guys should be page-aligned. | |
521 | */ | |
522 | ||
523 | hole_start = trunc_page((vm_offset_t)(1024 * cnvmem)); | |
524 | hole_end = round_page((vm_offset_t)first_avail); | |
525 | ||
526 | /* | |
527 | * compute mem_size | |
528 | */ | |
529 | ||
530 | if (mem_size != 0) { | |
531 | if (mem_size < (last_addr) - bios_hole_size) | |
532 | last_addr = mem_size + bios_hole_size; | |
533 | } | |
534 | ||
535 | first_addr = round_page(first_addr); | |
536 | last_addr = trunc_page(last_addr); | |
537 | mem_size = last_addr - bios_hole_size; | |
538 | ||
539 | avail_start = first_addr; | |
540 | avail_end = last_addr; | |
541 | avail_next = avail_start; | |
542 | ||
543 | /* | |
544 | * Initialize kernel physical map, mapping the | |
545 | * region from loadpt to avail_start. | |
546 | * Kernel virtual address starts at VM_KERNEL_MIN_ADDRESS. | |
547 | */ | |
548 | ||
549 | ||
550 | #if NCPUS > 1 && AT386 | |
551 | /* | |
552 | * Must Allocate interrupt stacks before kdb is called and also | |
553 | * before vm is initialized. Must find out number of cpus first. | |
554 | */ | |
555 | /* | |
556 | * Get number of cpus to boot, passed as an optional argument | |
557 | * boot: mach [-sah#] # from 0 to 9 is the number of cpus to boot | |
558 | */ | |
559 | if (wncpu == -1) { | |
560 | /* | |
561 | * "-1" check above is to allow for old boot loader to pass | |
562 | * wncpu through boothowto. New boot loader uses environment. | |
563 | */ | |
564 | const char *cpus; | |
565 | if ((cpus = getenv("cpus")) != NULL) { | |
566 | /* only a single digit for now */ | |
567 | if ((*cpus > '0') && (*cpus <= '9')) | |
568 | wncpu = *cpus - '0'; | |
569 | } else | |
570 | wncpu = NCPUS; | |
571 | } | |
572 | mp_probe_cpus(); | |
573 | interrupt_stack_alloc(); | |
574 | ||
575 | #endif /* NCPUS > 1 && AT386 */ | |
576 | ||
577 | pmap_bootstrap(0); | |
578 | ||
579 | avail_remaining = atop((avail_end - avail_start) - | |
580 | (hole_end - hole_start)); | |
581 | } | |
582 | ||
583 | unsigned int | |
584 | pmap_free_pages(void) | |
585 | { | |
586 | return avail_remaining; | |
587 | } | |
588 | ||
589 | boolean_t | |
590 | pmap_next_page( | |
591 | vm_offset_t *addrp) | |
592 | { | |
593 | if (avail_next == avail_end) | |
594 | return FALSE; | |
595 | ||
596 | /* skip the hole */ | |
597 | ||
598 | if (avail_next == hole_start) | |
599 | avail_next = hole_end; | |
600 | ||
601 | *addrp = avail_next; | |
602 | avail_next += PAGE_SIZE; | |
603 | avail_remaining--; | |
604 | ||
605 | return TRUE; | |
606 | } | |
607 | ||
608 | boolean_t | |
609 | pmap_valid_page( | |
610 | vm_offset_t x) | |
611 | { | |
612 | return ((avail_start <= x) && (x < avail_end)); | |
613 | } | |
614 | ||
615 | /*XXX*/ | |
616 | void fc_get(mach_timespec_t *ts); | |
617 | #include <kern/clock.h> | |
618 | #include <i386/rtclock_entries.h> | |
619 | extern kern_return_t sysclk_gettime( | |
620 | mach_timespec_t *cur_time); | |
621 | void fc_get(mach_timespec_t *ts) { | |
622 | (void )sysclk_gettime(ts); | |
623 | } | |
624 | ||
625 | void | |
626 | Debugger( | |
627 | const char *message) | |
628 | { | |
629 | printf("Debugger called: <%s>\n", message); | |
630 | ||
631 | __asm__("int3"); | |
632 | } | |
633 | ||
634 | void | |
635 | display_syscall(int syscall) | |
636 | { | |
637 | printf("System call happened %d\n", syscall); | |
638 | } | |
639 | ||
640 | #if XPR_DEBUG && (NCPUS == 1 || MP_V1_1) | |
641 | ||
642 | extern kern_return_t sysclk_gettime_interrupts_disabled( | |
643 | mach_timespec_t *cur_time); | |
644 | ||
645 | int xpr_time(void) | |
646 | { | |
647 | mach_timespec_t time; | |
648 | ||
649 | sysclk_gettime_interrupts_disabled(&time); | |
650 | return(time.tv_sec*1000000 + time.tv_nsec/1000); | |
651 | } | |
652 | #endif /* XPR_DEBUG && (NCPUS == 1 || MP_V1_1) */ | |
653 | ||
654 | enable_bluebox() | |
655 | { | |
656 | } | |
657 | disable_bluebox() | |
658 | { | |
659 | } | |
660 | ||
661 | char * | |
662 | machine_boot_info(char *buf, vm_size_t size) | |
663 | { | |
664 | *buf ='\0'; | |
665 | return buf; | |
666 | } | |
667 |