#include <cpus.h>
#include <platforms.h>
#include <mp_v1_1.h>
#include <mach_kdb.h>
#include <himem.h>
#include <fast_idle.h>
#include <mach/i386/vm_param.h>
#include <string.h>
#include <mach/vm_param.h>
#include <mach/vm_prot.h>
#include <mach/machine.h>
#include <mach/time_value.h>
#include <kern/etap_macros.h>
#include <kern/spl.h>
#include <kern/assert.h>
#include <kern/debug.h>
#include <kern/misc_protos.h>
#include <kern/startup.h>
#include <kern/clock.h>
#include <kern/time_out.h>
#include <kern/xpr.h>
#include <kern/cpu_data.h>
#include <vm/vm_page.h>
#include <vm/pmap.h>
#include <vm/vm_kern.h>
#include <i386/fpu.h>
#include <i386/pmap.h>
#include <i386/ipl.h>
#include <i386/pio.h>
#include <i386/misc_protos.h>
#include <i386/cpuid.h>
#include <i386/rtclock_entries.h>
#include <i386/AT386/mp/mp.h>
#if MACH_KDB
#include <ddb/db_aout.h>
#endif
#include <ddb/tr.h>
#ifdef __MACHO__
#include <i386/AT386/kernBootStruct.h>
#include <mach/boot_info.h>
#include <mach/thread_status.h>
#endif
#if NCPUS > 1
#include <i386/mp_desc.h>
#endif
#if MP_V1_1
#include <i386/AT386/mp/mp_v1_1.h>
#endif
vm_size_t mem_size = 0;
vm_offset_t first_addr = 0;
vm_offset_t first_avail = 0;
vm_offset_t last_addr;
vm_offset_t avail_start, avail_end;
vm_offset_t virtual_avail, virtual_end;
vm_offset_t hole_start, hole_end;
vm_offset_t avail_next;
unsigned int avail_remaining;
int cnvmem = 0;
int extmem = 0;
int dev_name_count = 0;
int dev_name_list = 0;
#ifndef __MACHO__
extern char edata, end;
#endif
extern char version[];
int rebootflag = 0;
void parse_arguments(void);
const char *getenv(const char *);
#define BOOT_LINE_LENGTH 160
char boot_string_store[BOOT_LINE_LENGTH] = {0};
char *boot_string = (char *)0;
int boot_string_sz = BOOT_LINE_LENGTH;
int boottype = 0;
#if __MACHO__
#include <mach-o/loader.h>
vm_offset_t edata, etext, end;
extern struct mach_header _mh_execute_header;
void *sectTEXTB; int sectSizeTEXT;
void *sectDATAB; int sectSizeDATA;
void *sectOBJCB; int sectSizeOBJC;
void *sectLINKB; int sectSizeLINK;
KERNBOOTSTRUCT kernBootStructData;
KERNBOOTSTRUCT *kernBootStruct;
#endif
vm_offset_t kern_args_start = 0;
vm_size_t kern_args_size = 0;
#ifdef __MACHO__
unsigned long
i386_preinit()
{
int i;
struct segment_command *sgp;
struct section *sp;
sgp = (struct segment_command *) getsegbyname("__DATA");
if (sgp) {
sp = (struct section *) firstsect(sgp);
if (sp) {
do {
if (sp->flags & S_ZEROFILL)
bzero((char *) sp->addr, sp->size);
} while (sp = (struct section *)nextsect(sgp, sp));
}
}
bcopy((char *) KERNSTRUCT_ADDR, (char *) &kernBootStructData,
sizeof(kernBootStructData));
kernBootStruct = &kernBootStructData;
end = round_page( kernBootStruct->kaddr + kernBootStruct->ksize );
return end;
}
#endif
void
machine_startup(void)
{
#ifdef __MACHO__
cnvmem = kernBootStruct->convmem;
extmem = kernBootStruct->extmem;
kern_args_start = (vm_offset_t) kernBootStruct->bootString;
kern_args_size = strlen(kernBootStruct->bootString);
boottype = kernBootStruct->rootdev;
sectTEXTB = (void *) getsegdatafromheader(
&_mh_execute_header, "__TEXT", §SizeTEXT);
sectDATAB = (void *) getsegdatafromheader(
&_mh_execute_header, "__DATA", §SizeDATA);
sectOBJCB = (void *) getsegdatafromheader(
&_mh_execute_header, "__OBJC", §SizeOBJC);
sectLINKB = (void *) getsegdatafromheader(
&_mh_execute_header, "__LINKEDIT", §SizeLINK);
etext = (vm_offset_t) sectTEXTB + sectSizeTEXT;
edata = (vm_offset_t) sectDATAB + sectSizeDATA;
#endif
parse_arguments();
disableDebugOuput = FALSE;
debug_mode = TRUE;
printf_init();
panic_init();
PE_init_platform(FALSE, kernBootStruct);
PE_init_kprintf(FALSE);
PE_init_printf(FALSE);
i386_init();
PE_init_platform(TRUE, kernBootStruct);
PE_init_kprintf(TRUE);
PE_init_printf(TRUE);
#if MACH_KDB
ddb_init();
if (halt_in_debugger) {
printf("inline call to debugger(machine_startup)\n");
Debugger("inline call");
}
#endif
TR_INIT();
printf(version);
machine_slot[0].is_cpu = TRUE;
machine_slot[0].running = TRUE;
#ifdef MACH_BSD
machine_slot[0].cpu_type = CPU_TYPE_I386;
machine_slot[0].cpu_subtype = CPU_SUBTYPE_PENTPRO;
#else
machine_slot[0].cpu_type = cpuid_cputype(0);
machine_slot[0].cpu_subtype = CPU_SUBTYPE_AT386;
#endif
#if NCPUS > 1
mp_desc_init(0);
#endif
setup_main();
}
vm_offset_t env_start = 0;
vm_size_t env_size = 0;
void
parse_arguments(void)
{
char *p = (char *) kern_args_start;
char *endp = (char *) kern_args_start + kern_args_size - 1;
char ch;
if (kern_args_start == 0)
return;
while ( (p < endp) && (*p != '\0')) {
if (*p++ != '-')
continue;
switch (*p++) {
case 'h':
halt_in_debugger = 1;
break;
case 'm':
mem_size = atoi_term(p,&p)*1024*1024;
break;
case 'k':
mem_size = atoi_term(p,&p)*1024;
break;
default:
break;
}
}
}
const char *
getenv(const char *name)
{
int len = strlen(name);
const char *p = (const char *)env_start;
const char *endp = p + env_size;
while (p < endp) {
if (len >= endp - p)
break;
if (strncmp(name, p, len) == 0 && *(p + len) == '=')
return p + len + 1;
while (*p++)
;
}
return NULL;
}
extern void
calibrate_delay(void);
void
machine_init(void)
{
int unit;
const char *p;
int n;
calibrate_delay();
cpuid_cpu_display("CPU identification", 0);
cpuid_cache_display("CPU configuration", 0);
#if MP_V1_1
mp_v1_1_init();
#endif
init_fpu();
#if 0
#if NPCI > 0
dma_zones_init();
#endif
#endif
clock_config();
}
void
halt_cpu(void)
{
halt_all_cpus(FALSE);
}
int reset_mem_on_reboot = 1;
void
halt_all_cpus(
boolean_t reboot)
{
if (reboot) {
if (! reset_mem_on_reboot)
*(unsigned short *)phystokv(0x472) = 0x1234;
kdreboot();
}
else {
rebootflag = 1;
printf("In tight loop: hit ctl-alt-del to reboot\n");
(void) spllo();
}
for (;;)
continue;
}
void
i386_init(void)
{
int i,j;
vm_size_t bios_hole_size;
#ifndef __MACHO__
bzero((char *)&edata,(unsigned)(&end - &edata));
#endif
boot_string = &boot_string_store[0];
set_cpu_model();
vm_set_page_size();
etap_init_phase1();
#if 1
first_addr = (char *)(KERNSTRUCT_ADDR) + sizeof(KERNBOOTSTRUCT);
#else
#if NCPUS > 1
first_addr = 0x1000;
#else
first_addr = 0x3000;
#endif
#endif
last_addr = 1024*1024 + extmem*1024;
bios_hole_size = 1024*1024 - trunc_page((vm_offset_t)(1024 * cnvmem));
hole_start = trunc_page((vm_offset_t)(1024 * cnvmem));
hole_end = round_page((vm_offset_t)first_avail);
if (mem_size != 0) {
if (mem_size < (last_addr) - bios_hole_size)
last_addr = mem_size + bios_hole_size;
}
first_addr = round_page(first_addr);
last_addr = trunc_page(last_addr);
mem_size = last_addr - bios_hole_size;
avail_start = first_addr;
avail_end = last_addr;
avail_next = avail_start;
#if NCPUS > 1 && AT386
if (wncpu == -1) {
const char *cpus;
if ((cpus = getenv("cpus")) != NULL) {
if ((*cpus > '0') && (*cpus <= '9'))
wncpu = *cpus - '0';
} else
wncpu = NCPUS;
}
mp_probe_cpus();
interrupt_stack_alloc();
#endif
pmap_bootstrap(0);
avail_remaining = atop((avail_end - avail_start) -
(hole_end - hole_start));
}
unsigned int
pmap_free_pages(void)
{
return avail_remaining;
}
boolean_t
pmap_next_page(
vm_offset_t *addrp)
{
if (avail_next == avail_end)
return FALSE;
if (avail_next == hole_start)
avail_next = hole_end;
*addrp = avail_next;
avail_next += PAGE_SIZE;
avail_remaining--;
return TRUE;
}
boolean_t
pmap_valid_page(
vm_offset_t x)
{
return ((avail_start <= x) && (x < avail_end));
}
void fc_get(mach_timespec_t *ts);
#include <kern/clock.h>
#include <i386/rtclock_entries.h>
extern kern_return_t sysclk_gettime(
mach_timespec_t *cur_time);
void fc_get(mach_timespec_t *ts) {
(void )sysclk_gettime(ts);
}
void
Debugger(
const char *message)
{
printf("Debugger called: <%s>\n", message);
__asm__("int3");
}
void
display_syscall(int syscall)
{
printf("System call happened %d\n", syscall);
}
#if XPR_DEBUG && (NCPUS == 1 || MP_V1_1)
extern kern_return_t sysclk_gettime_interrupts_disabled(
mach_timespec_t *cur_time);
int xpr_time(void)
{
mach_timespec_t time;
sysclk_gettime_interrupts_disabled(&time);
return(time.tv_sec*1000000 + time.tv_nsec/1000);
}
#endif
enable_bluebox()
{
}
disable_bluebox()
{
}
char *
machine_boot_info(char *buf, vm_size_t size)
{
*buf ='\0';
return buf;
}