예제 #1
0
/*
 * There is an ELF kernel and one or more ELF modules loaded.  
 * We wish to start executing the kernel image, so make such 
 * preparations as are required, and do so.
 */
static int
elf32_exec(struct preloaded_file *fp)
{
    struct file_metadata	*md;
    Elf_Ehdr 			*ehdr;
    vm_offset_t			entry, bootinfop, modulep, kernend;
    int				boothowto, err, bootdev;

    if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
	return(EFTYPE);
    ehdr = (Elf_Ehdr *)&(md->md_data);

    err = bi_load(fp->f_args, &boothowto, &bootdev, &bootinfop, &modulep, &kernend);
    if (err != 0)
	return(err);
    entry = ehdr->e_entry & 0xffffff;

    printf("Start @ 0x%lx ...\n", entry);

    ldr_enter(fp->f_name);

    dev_cleanup();
    __exec((void *)entry, boothowto, bootdev, 0, 0, 0, bootinfop, modulep, kernend);

    panic("exec returned");
}
예제 #2
0
static int
__elfN(arm_exec)(struct preloaded_file *fp)
{
	struct file_metadata *fmp;
	vm_offset_t modulep, kernend;
	Elf_Ehdr *e;
	int error;
	void (*entry)(void *);

	if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
		return (EFTYPE);

	e = (Elf_Ehdr *)&fmp->md_data;

	if ((error = bi_load(fp->f_args, &modulep, &kernend)) != 0)
		return (error);

	entry = efi_translate(e->e_entry);
	printf("Kernel entry at 0x%x...\n", (unsigned)entry);
	printf("Kernel args: %s\n", fp->f_args);
	printf("modulep: %#x\n", modulep);
	printf("relocation_offset %llx\n", __elfN(relocation_offset));

	dev_cleanup();

	(*entry)((void *)modulep);
	panic("exec returned");
}
예제 #3
0
static int
elf_exec(struct loaded_module *mp)
{
    static struct bootinfo_v1	bootinfo_v1;
    struct module_metadata	*md;
    Elf_Ehdr			*hdr;
    int				err;
    int				flen;

    if ((md = mod_findmetadata(mp, MODINFOMD_ELFHDR)) == NULL)
	return(EFTYPE);			/* XXX actually EFUCKUP */
    hdr = (Elf_Ehdr *)&(md->md_data);

    /* XXX ffp_save does not appear to be used in the kernel.. */
    bzero(&bootinfo_v1, sizeof(bootinfo_v1));
    err = bi_load(&bootinfo_v1, &ffp_save, mp);
    if (err)
	return(err);

    /*
     * Fill in the bootinfo for the kernel.
     */
    strncpy(bootinfo_v1.booted_kernel, mp->m_name,
	    sizeof(bootinfo_v1.booted_kernel));
    flen = prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo_v1.boot_flags,
		sizeof(bootinfo_v1.boot_flags));
    bootinfo_v1.hwrpb = (void *)HWRPB_ADDR;
    bootinfo_v1.hwrpbsize = ((struct rpb *)HWRPB_ADDR)->rpb_size;
    bootinfo_v1.cngetc = NULL;
    bootinfo_v1.cnputc = NULL;
    bootinfo_v1.cnpollc = NULL;

    /*
     * Append the boot command flags.
     */
    if (mp->m_args != NULL && *mp->m_args != '\0') {
	const char *p = mp->m_args;

	do {
	    if (*p == '-') {
		while (*++p != ' ' && *p != '\0')
		    if (flen < sizeof(bootinfo_v1.boot_flags) - 1)
			bootinfo_v1.boot_flags[flen++] = *p;
	    } else
		while (*p != ' ' && *p != '\0')
		    p++;
	    while (*p == ' ')
		p++;
	} while (*p != '\0');
	bootinfo_v1.boot_flags[flen] = '\0';
    }

    printf("Entering %s at 0x%lx...\n", mp->m_name, hdr->e_entry);
    closeall();
    alpha_pal_imb();
    (*(void (*)())hdr->e_entry)(ffp_save, ptbr_save,
			       BOOTINFO_MAGIC, &bootinfo_v1, 1, 0);
}
예제 #4
0
static int
elf64_exec(struct preloaded_file *fp)
{
	struct file_metadata	*md;
	Elf_Ehdr		*hdr;
	struct ia64_pte		pte;
	struct bootinfo		*bi;

	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
		return(EFTYPE);			/* XXX actually EFUCKUP */
	hdr = (Elf_Ehdr *)&(md->md_data);

	/*
	 * Ugly hack, similar to linux. Dump the bootinfo into a
	 * special page reserved in the link map.
	 */
	bi = &bootinfo;
	bzero(bi, sizeof(struct bootinfo));
	bi_load(bi, fp);

	/*
	 * Region 6 is direct mapped UC and region 7 is direct mapped
	 * WC. The details of this is controlled by the Alt {I,D}TLB
	 * handlers. Here we just make sure that they have the largest 
	 * possible page size to minimise TLB usage.
	 */
	ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (28 << 2));
	ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (28 << 2));

	bzero(&pte, sizeof(pte));
	pte.pte_p = 1;
	pte.pte_ma = PTE_MA_WB;
	pte.pte_a = 1;
	pte.pte_d = 1;
	pte.pte_pl = PTE_PL_KERN;
	pte.pte_ar = PTE_AR_RWX;
	pte.pte_ppn = 0;

	__asm __volatile("mov cr.ifa=%0" :: "r"(IA64_RR_BASE(7)));
	__asm __volatile("mov cr.itir=%0" :: "r"(28 << 2));
	__asm __volatile("srlz.i;;");
	__asm __volatile("itr.i itr[%0]=%1;;"
			 :: "r"(0), "r"(*(u_int64_t*)&pte));
	__asm __volatile("srlz.i;;");
	__asm __volatile("itr.d dtr[%0]=%1;;"
			 :: "r"(0), "r"(*(u_int64_t*)&pte));
	__asm __volatile("srlz.i;;");

	enter_kernel(fp->f_name, hdr->e_entry, bi);
}
예제 #5
0
static int
elf64_exec(struct preloaded_file *fp)
{
    struct file_metadata	*md;
    Elf_Ehdr		*hdr;
    pt_entry_t		pte;
    uint64_t		bi_addr;

    md = file_findmetadata(fp, MODINFOMD_ELFHDR);
    if (md == NULL)
        return (EINVAL);
    hdr = (Elf_Ehdr *)&(md->md_data);

    bi_load(fp, &bi_addr);

    printf("Entering %s at 0x%lx...\n", fp->f_name, hdr->e_entry);

    ldr_enter(fp->f_name);

    __asm __volatile("rsm psr.ic|psr.i;;");
    __asm __volatile("srlz.i;;");

    /*
     * Region 6 is direct mapped UC and region 7 is direct mapped
     * WC. The details of this is controlled by the Alt {I,D}TLB
     * handlers. Here we just make sure that they have the largest
     * possible page size to minimise TLB usage.
     */
    ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (28 << 2));
    ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (28 << 2));

    pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY |
          PTE_PL_KERN | PTE_AR_RWX | PTE_ED;

    __asm __volatile("mov cr.ifa=%0" :: "r"(IA64_RR_BASE(7)));
    __asm __volatile("mov cr.itir=%0" :: "r"(28 << 2));
    __asm __volatile("ptr.i %0,%1" :: "r"(IA64_RR_BASE(7)), "r"(28<<2));
    __asm __volatile("ptr.d %0,%1" :: "r"(IA64_RR_BASE(7)), "r"(28<<2));
    __asm __volatile("srlz.i;;");
    __asm __volatile("itr.i itr[%0]=%1;;" :: "r"(0), "r"(pte));
    __asm __volatile("srlz.i;;");
    __asm __volatile("itr.d dtr[%0]=%1;;" :: "r"(0), "r"(pte));
    __asm __volatile("srlz.i;;");

    enter_kernel(hdr->e_entry, bi_addr);

    /* NOTREACHED */
    return (0);
}
예제 #6
0
static int
elf64_exec(struct preloaded_file *fp)
{
	vm_offset_t modulep, kernendp;
	vm_offset_t clean_addr;
	size_t clean_size;
	struct file_metadata *md;
	ACPI_TABLE_RSDP *rsdp;
	Elf_Ehdr *ehdr;
	char buf[24];
	int err, revision;
	void (*entry)(vm_offset_t);

	rsdp = efi_get_table(&acpi20_guid);
	if (rsdp == NULL) {
		rsdp = efi_get_table(&acpi_guid);
	}
	if (rsdp != NULL) {
		sprintf(buf, "0x%016llx", (unsigned long long)rsdp);
		setenv("hint.acpi.0.rsdp", buf, 1);
		revision = rsdp->Revision;
		if (revision == 0)
			revision = 1;
		sprintf(buf, "%d", revision);
		setenv("hint.acpi.0.revision", buf, 1);
		strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
		buf[sizeof(rsdp->OemId)] = '\0';
		setenv("hint.acpi.0.oem", buf, 1);
		sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress);
		setenv("hint.acpi.0.rsdt", buf, 1);
		if (revision >= 2) {
			/* XXX extended checksum? */
			sprintf(buf, "0x%016llx",
			    (unsigned long long)rsdp->XsdtPhysicalAddress);
			setenv("hint.acpi.0.xsdt", buf, 1);
			sprintf(buf, "%d", rsdp->Length);
			setenv("hint.acpi.0.xsdt_length", buf, 1);
		}
	}

	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
        	return(EFTYPE);

	ehdr = (Elf_Ehdr *)&(md->md_data);
	entry = efi_translate(ehdr->e_entry);

	err = bi_load(fp->f_args, &modulep, &kernendp);
	if (err != 0)
		return (err);

	dev_cleanup();

	/* Clean D-cache under kernel area and invalidate whole I-cache */
	clean_addr = (vm_offset_t)efi_translate(fp->f_addr);
	clean_size = (vm_offset_t)efi_translate(kernendp) - clean_addr;

	cpu_flush_dcache((void *)clean_addr, clean_size);
	cpu_inval_icache(NULL, 0);

	(*entry)(modulep);
	panic("exec returned");
}
예제 #7
0
/*
 * There is an ELF kernel and one or more ELF modules loaded.
 * We wish to start executing the kernel image, so make such
 * preparations as are required, and do so.
 */
static int
elf64_exec(struct preloaded_file *fp)
{
	struct file_metadata	*md;
	Elf_Ehdr 		*ehdr;
	vm_offset_t		modulep, kernend, trampcode, trampstack;
	int			err, i;
	ACPI_TABLE_RSDP		*rsdp;
	char			buf[24];
	int			revision;

	rsdp = efi_get_table(&acpi20_guid);
	if (rsdp == NULL) {
		rsdp = efi_get_table(&acpi_guid);
	}
	if (rsdp != NULL) {
		sprintf(buf, "0x%016llx", (unsigned long long)rsdp);
		setenv("hint.acpi.0.rsdp", buf, 1);
		revision = rsdp->Revision;
		if (revision == 0)
			revision = 1;
		sprintf(buf, "%d", revision);
		setenv("hint.acpi.0.revision", buf, 1);
		strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
		buf[sizeof(rsdp->OemId)] = '\0';
		setenv("hint.acpi.0.oem", buf, 1);
		sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress);
		setenv("hint.acpi.0.rsdt", buf, 1);
		if (revision >= 2) {
			/* XXX extended checksum? */
			sprintf(buf, "0x%016llx",
			    (unsigned long long)rsdp->XsdtPhysicalAddress);
			setenv("hint.acpi.0.xsdt", buf, 1);
			sprintf(buf, "%d", rsdp->Length);
			setenv("hint.acpi.0.xsdt_length", buf, 1);
		}
	}

	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
		return(EFTYPE);
	ehdr = (Elf_Ehdr *)&(md->md_data);

	trampcode = (vm_offset_t)0x0000000040000000;
	err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1,
	    (EFI_PHYSICAL_ADDRESS *)&trampcode);
	bzero((void *)trampcode, EFI_PAGE_SIZE);
	trampstack = trampcode + EFI_PAGE_SIZE - 8;
	bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size);
	trampoline = (void *)trampcode;

	PT4 = (p4_entry_t *)0x0000000040000000;
	err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3,
	    (EFI_PHYSICAL_ADDRESS *)&PT4);
	bzero(PT4, 3 * EFI_PAGE_SIZE);

	PT3 = &PT4[512];
	PT2 = &PT3[512];

	/*
	 * This is kinda brutal, but every single 1GB VM memory segment points
	 * to the same first 1GB of physical memory.  But it is more than
	 * adequate.
	 */
	for (i = 0; i < 512; i++) {
		/* Each slot of the L4 pages points to the same L3 page. */
		PT4[i] = (p4_entry_t)PT3;
		PT4[i] |= PG_V | PG_RW | PG_U;

		/* Each slot of the L3 pages points to the same L2 page. */
		PT3[i] = (p3_entry_t)PT2;
		PT3[i] |= PG_V | PG_RW | PG_U;

		/* The L2 page slots are mapped with 2MB pages for 1GB. */
		PT2[i] = i * (2 * 1024 * 1024);
		PT2[i] |= PG_V | PG_RW | PG_PS | PG_U;
	}

	printf("Start @ 0x%lx ...\n", ehdr->e_entry);

	err = bi_load(fp->f_args, &modulep, &kernend);
	if (err != 0)
		return(err);

	dev_cleanup();

	trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4,
	    ehdr->e_entry);

	panic("exec returned");
}