/* * Do all the stuff that locore normally does before calling main(). * Process arguments passed to us by the prom monitor. * Return the first page address following the system. */ void mach_init(int x_boothowto, int x_bootdev, int x_bootname, int x_maxmem) { u_long first, last; char *kernend; struct btinfo_magic *bi_magic; struct btinfo_bootarg *bi_arg; struct btinfo_systype *bi_systype; #if NKSYMS || defined(DDB) || defined(MODULAR) struct btinfo_symtab *bi_sym; int nsym = 0; char *ssym, *esym; ssym = esym = NULL; /* XXX: gcc */ #endif bi_arg = NULL; bootinfo = (void *)BOOTINFO_ADDR; /* XXX */ bi_magic = lookup_bootinfo(BTINFO_MAGIC); if (bi_magic && bi_magic->magic == BOOTINFO_MAGIC) { bi_arg = lookup_bootinfo(BTINFO_BOOTARG); if (bi_arg) { x_boothowto = bi_arg->howto; x_bootdev = bi_arg->bootdev; x_maxmem = bi_arg->maxmem; } #if NKSYMS || defined(DDB) || defined(MODULAR) bi_sym = lookup_bootinfo(BTINFO_SYMTAB); if (bi_sym) { nsym = bi_sym->nsym; ssym = (void *)bi_sym->ssym; esym = (void *)bi_sym->esym; } #endif bi_systype = lookup_bootinfo(BTINFO_SYSTYPE); if (bi_systype) systype = bi_systype->type; } else { /* * Running kernel is loaded by non-native loader; * clear the BSS segment here. */ memset(edata, 0, end - edata); } if (systype == 0) systype = NEWS3400; /* XXX compatibility for old boot */ #ifdef news5000 if (systype == NEWS5000) { int i; char *bootspec = (char *)x_bootdev; if (bi_arg == NULL) panic("news5000 requires BTINFO_BOOTARG to boot"); _sip = (void *)bi_arg->sip; x_maxmem = _sip->apbsi_memsize; x_maxmem -= 0x00100000; /* reserve 1MB for ROM monitor */ if (strncmp(bootspec, "scsi", 4) == 0) { x_bootdev = (5 << 28) | 0; /* magic, sd */ bootspec += 4; if (*bootspec != '(' /*)*/) goto bootspec_end; i = strtoul(bootspec + 1, &bootspec, 10); x_bootdev |= (i << 24); /* bus */ if (*bootspec != ',') goto bootspec_end; i = strtoul(bootspec + 1, &bootspec, 10); x_bootdev |= (i / 10) << 20; /* controller */ x_bootdev |= (i % 10) << 16; /* unit */ if (*bootspec != ',') goto bootspec_end; i = strtoul(bootspec + 1, &bootspec, 10); x_bootdev |= (i << 8); /* partition */ } bootspec_end: consinit(); } #endif /* * Save parameters into kernel work area. */ *(int *)(MIPS_PHYS_TO_KSEG1(MACH_MAXMEMSIZE_ADDR)) = x_maxmem; *(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTDEV_ADDR)) = x_bootdev; *(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTSW_ADDR)) = x_boothowto; kernend = (char *)mips_round_page(end); #if NKSYMS || defined(DDB) || defined(MODULAR) if (nsym) kernend = (char *)mips_round_page(esym); #endif /* * Set the VM page size. */ uvm_setpagesize(); boothowto = x_boothowto; bootdev = x_bootdev; physmem = btoc(x_maxmem); /* * Now that we know how much memory we have, initialize the * mem cluster array. */ mem_clusters[0].start = 0; /* XXX is this correct? */ mem_clusters[0].size = ctob(physmem); mem_cluster_cnt = 1; /* * Copy exception-dispatch code down to exception vector. * Initialize locore-function vector. * Clear out the I and D caches. */ mips_vector_init(NULL, false); /* * We know the CPU type now. Initialize our DMA tags (might * need this early). */ newsmips_bus_dma_init(); #if NKSYMS || defined(DDB) || defined(MODULAR) if (nsym) ksyms_addsyms_elf(esym - ssym, ssym, esym); #endif #ifdef KADB boothowto |= RB_KDB; #endif /* * Check to see if a mini-root was loaded into memory. It resides * at the start of the next page just after the end of BSS. */ if (boothowto & RB_MINIROOT) kernend += round_page(mfs_initminiroot(kernend)); /* * Load the rest of the available pages into the VM system. */ first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); last = mem_clusters[0].start + mem_clusters[0].size; uvm_page_physload(atop(first), atop(last), atop(first), atop(last), VM_FREELIST_DEFAULT); /* * Initialize error message buffer (at end of core). */ mips_init_msgbuf(); /* * Initialize the virtual memory system. */ pmap_bootstrap(); /* * Allocate uarea page for lwp0 and set it. */ mips_init_lwp0_uarea(); /* * Determine what model of computer we are running on. */ switch (systype) { #ifdef news3400 case NEWS3400: news3400_init(); strcpy(cpu_model, idrom.id_machine); if (strcmp(cpu_model, "news3400") == 0 || strcmp(cpu_model, "news3200") == 0 || strcmp(cpu_model, "news3700") == 0) { /* * Set up interrupt handling and I/O addresses. */ hardware_intr = news3400_intr; cpuspeed = 10; } else { printf("kernel not configured for machine %s\n", cpu_model); } break; #endif #ifdef news5000 case NEWS5000: news5000_init(); strcpy(cpu_model, idrom.id_machine); if (strcmp(cpu_model, "news5000") == 0 || strcmp(cpu_model, "news5900") == 0) { /* * Set up interrupt handling and I/O addresses. */ hardware_intr = news5000_intr; cpuspeed = 50; /* ??? XXX */ } else { printf("kernel not configured for machine %s\n", cpu_model); } break; #endif default: printf("kernel not configured for systype %d\n", systype); break; } }
void machine_startup(int argc, char *argv[], struct bootinfo *bi) { extern char edata[], end[]; vaddr_t kernend; size_t symbolsize; int i; char *p; /* * this routines stack is never polluted since stack pointer * is lower than kernel text segment, and at exiting, stack pointer * is changed to proc0. */ struct kloader_bootinfo kbi; /* Symbol table size */ symbolsize = 0; if (memcmp(&end, ELFMAG, SELFMAG) == 0) { Elf_Ehdr *eh = (void *)end; Elf_Shdr *sh = (void *)(end + eh->e_shoff); for(i = 0; i < eh->e_shnum; i++, sh++) if (sh->sh_offset > 0 && (sh->sh_offset + sh->sh_size) > symbolsize) symbolsize = sh->sh_offset + sh->sh_size; } /* Clear BSS */ memset(edata, 0, end - edata); /* Setup bootinfo */ bootinfo = &kbi.bootinfo; memcpy(bootinfo, bi, sizeof(struct bootinfo)); if (bootinfo->magic == BOOTINFO_MAGIC) { platid.dw.dw0 = bootinfo->platid_cpu; platid.dw.dw1 = bootinfo->platid_machine; } /* CPU initialize */ if (platid_match(&platid, &platid_mask_CPU_SH_3)) sh_cpu_init(CPU_ARCH_SH3, CPU_PRODUCT_7709A); else if (platid_match(&platid, &platid_mask_CPU_SH_4)) sh_cpu_init(CPU_ARCH_SH4, CPU_PRODUCT_7750); /* Start to determine heap area */ kernend = (vaddr_t)sh3_round_page(end + symbolsize); /* Setup bootstrap options */ makebootdev("wd0"); /* default boot device */ boothowto = 0; for (i = 1; i < argc; i++) { /* skip 1st arg (kernel name). */ char *cp = argv[i]; switch (*cp) { case 'b': /* boot device: -b=sd0 etc. */ p = cp + 2; #ifdef NFS if (strcmp(p, "nfs") == 0) mountroot = nfs_mountroot; else makebootdev(p); #else /* NFS */ makebootdev(p); #endif /* NFS */ break; default: BOOT_FLAG(*cp, boothowto); break; } } #ifdef MFS /* * Check to see if a mini-root was loaded into memory. It resides * at the start of the next page just after the end of BSS. */ if (boothowto & RB_MINIROOT) { size_t fssz; fssz = sh3_round_page(mfs_initminiroot((void *)kernend)); #ifdef MEMORY_DISK_DYNAMIC md_root_setconf((caddr_t)kernend, fssz); #endif kernend += fssz; } #endif /* MFS */ /* Console */ consinit(); #ifdef HPC_DEBUG_LCD dbg_lcd_test(); #endif /* copy boot parameter for kloader */ kloader_bootinfo_set(&kbi, argc, argv, bi, TRUE); /* Find memory cluster. and load to UVM */ physmem = mem_cluster_init(SH3_P1SEG_TO_PHYS(kernend)); _DPRINTF("total memory = %dMbyte\n", (int)(sh3_ptob(physmem) >> 20)); mem_cluster_load(); /* Initialize proc0 u-area */ sh_proc0_init(); /* Initialize pmap and start to address translation */ pmap_bootstrap(); /* Debugger. */ #ifdef DDB if (symbolsize) { ddb_init(symbolsize, &end, end + symbolsize); _DPRINTF("symbol size = %d byte\n", symbolsize); } if (boothowto & RB_KDB) Debugger(); #endif /* DDB */ #ifdef KGDB if (boothowto & RB_KDB) { if (kgdb_dev == NODEV) { printf("no kgdb console.\n"); } else { kgdb_debug_init = 1; kgdb_connect(1); } } #endif /* KGDB */ /* Jump to main */ __asm__ __volatile__( "jmp @%0;" "mov %1, sp" :: "r"(main),"r"(proc0.p_md.md_pcb->pcb_sf.sf_r7_bank)); /* NOTREACHED */ while (1) ; }