/* * Load the information expected by the kernel. * * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load(struct preloaded_file *fp, uint64_t *bi_addr) { struct bootinfo bi; struct preloaded_file *xp; struct file_metadata *md; struct devdesc *rootdev; char *rootdevname; vm_offset_t addr, ssym, esym; bzero(&bi, sizeof(struct bootinfo)); bi.bi_version = 1; // bi.bi_boothowto = bi_getboothowto(fp->f_args); /* * Allow the environment variable 'rootdev' to override the supplied * device. This should perhaps go to MI code and/or have $rootdev * tested/set by MI code before launching the kernel. */ rootdevname = getenv("rootdev"); i386_getdev((void**)&rootdev, rootdevname, NULL); if (rootdev != NULL) { /* Try reading /etc/fstab to select the root device. */ getrootmount(i386_fmtdev(rootdev)); free(rootdev); } md = file_findmetadata(fp, MODINFOMD_SSYM); ssym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; md = file_findmetadata(fp, MODINFOMD_ESYM); esym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; if (ssym != 0 && esym != 0) { bi.bi_symtab = ssym; bi.bi_esymtab = esym; } /* Find the last module in the chain. */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } addr = (addr + 15) & ~15; /* Copy module list and metadata. */ bi.bi_modulep = addr; addr = bi_copymodules(addr); if (addr <= bi.bi_modulep) { addr = bi.bi_modulep; bi.bi_modulep = 0; } addr = (addr + 15) & ~15; /* Copy our environment. */ bi.bi_envp = addr; addr = bi_copyenv(addr); if (addr <= bi.bi_envp) { addr = bi.bi_envp; bi.bi_envp = 0; } addr = (addr + PAGE_MASK) & ~PAGE_MASK; bi.bi_kernend = addr; return (ldr_bootinfo(&bi, bi_addr)); }
/* * Load the information expected by an alpha kernel. * * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load(struct bootinfo *bi, struct preloaded_file *fp, char *args) { char *rootdevname; struct ski_devdesc *rootdev; struct preloaded_file *xp; vm_offset_t addr, bootinfo_addr; u_int pad; char *kernelname; vm_offset_t ssym, esym; struct file_metadata *md; EFI_MEMORY_DESCRIPTOR *memp; /* * Version 1 bootinfo. */ bi->bi_magic = BOOTINFO_MAGIC; bi->bi_version = 1; /* * Calculate boothowto. */ bi->bi_boothowto = bi_getboothowto(fp->f_args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); ski_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(ski_fmtdev((void *)rootdev)); free(rootdev); ssym = esym = 0; if ((md = file_findmetadata(fp, MODINFOMD_SSYM)) != NULL) ssym = *((vm_offset_t *)&(md->md_data)); if ((md = file_findmetadata(fp, MODINFOMD_ESYM)) != NULL) esym = *((vm_offset_t *)&(md->md_data)); if (ssym == 0 || esym == 0) ssym = esym = 0; /* sanity */ bi->bi_symtab = ssym; bi->bi_esymtab = esym; /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ pad = (u_int)addr & PAGE_MASK; if (pad != 0) { pad = PAGE_SIZE - pad; addr += pad; } /* copy our environment */ bi->bi_envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ pad = (u_int)addr & PAGE_MASK; if (pad != 0) { pad = PAGE_SIZE - pad; addr += pad; } /* copy module list and metadata */ bi->bi_modulep = addr; addr = bi_copymodules(addr); /* all done copying stuff in, save end of loaded object space */ bi->bi_kernend = addr; /* Describe the SKI memory map. */ bi->bi_memmap = (u_int64_t)(bi + 1); bi->bi_memmap_size = 2 * sizeof(EFI_MEMORY_DESCRIPTOR); bi->bi_memdesc_size = sizeof(EFI_MEMORY_DESCRIPTOR); bi->bi_memdesc_version = 1; memp = (EFI_MEMORY_DESCRIPTOR *) bi->bi_memmap; memp[0].Type = EfiConventionalMemory; memp[0].PhysicalStart = 2L*1024*1024; memp[0].VirtualStart = 0; memp[0].NumberOfPages = (64L*1024*1024)>>12; memp[0].Attribute = EFI_MEMORY_WB; memp[1].Type = EfiMemoryMappedIOPortSpace; memp[1].PhysicalStart = 0xffffc000000; memp[1].VirtualStart = 0; memp[1].NumberOfPages = (64L*1024*1024)>>12; memp[1].Attribute = EFI_MEMORY_UC; return(0); }
/* * Load the information expected by an i386 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernendp) { struct preloaded_file *xp, *kfp; struct i386_devdesc *rootdev; struct file_metadata *md; vm_offset_t addr; vm_offset_t kernend; vm_offset_t envp; vm_offset_t size; vm_offset_t ssym, esym; char *rootdevname; int bootdevnr, i, howto; char *kernelname; const char *kernelpath; howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); i386_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(i386_fmtdev(rootdev)); /* Do legacy rootdev guessing */ /* XXX - use a default bootdev of 0. Is this ok??? */ bootdevnr = 0; switch(rootdev->d_type) { case DEVT_CD: /* Pass in BIOS device number. */ bi.bi_bios_dev = bc_unit2bios(rootdev->d_kind.bioscd.unit); bootdevnr = bc_getdev(rootdev); break; case DEVT_DISK: /* pass in the BIOS device number of the current disk */ bi.bi_bios_dev = bd_unit2bios(rootdev->d_kind.biosdisk.unit); bootdevnr = bd_getdev(rootdev); break; case DEVT_NET: break; default: printf("WARNING - don't know how to boot from device type %d\n", rootdev->d_type); } if (bootdevnr == -1) { printf("root device %s invalid\n", i386_fmtdev(rootdev)); return (EINVAL); } free(rootdev); /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* copy our environment */ envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf32 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); bios_addsmapdata(kfp); /* Figure out the size and location of the metadata */ *modulep = addr; size = bi_copymodules32(0); kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* copy module list and metadata */ (void)bi_copymodules32(addr); ssym = esym = 0; md = file_findmetadata(kfp, MODINFOMD_SSYM); if (md != NULL) ssym = *((vm_offset_t *)&(md->md_data)); md = file_findmetadata(kfp, MODINFOMD_ESYM); if (md != NULL) esym = *((vm_offset_t *)&(md->md_data)); if (ssym == 0 || esym == 0) ssym = esym = 0; /* sanity */ /* legacy bootinfo structure */ kernelname = getenv("kernelname"); i386_getdev(NULL, kernelname, &kernelpath); bi.bi_version = BOOTINFO_VERSION; bi.bi_kernelname = 0; /* XXX char * -> kernel name */ bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */ bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */ for (i = 0; i < N_BIOS_GEOM; i++) bi.bi_bios_geom[i] = bd_getbigeom(i); bi.bi_size = sizeof(bi); bi.bi_memsizes_valid = 1; bi.bi_basemem = bios_basemem / 1024; bi.bi_extmem = bios_extmem / 1024; bi.bi_envp = envp; bi.bi_modulep = *modulep; bi.bi_kernend = kernend; bi.bi_kernelname = VTOP(kernelpath); bi.bi_symtab = ssym; /* XXX this is only the primary kernel symtab */ bi.bi_esymtab = esym; /* legacy boot arguments */ *howtop = howto | RB_BOOTINFO; *bootdevp = bootdevnr; *bip = VTOP(&bi); return(0); }
/* * Load the information expected by an amd64 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp) { struct preloaded_file *xp, *kfp; struct userboot_devdesc *rootdev; struct file_metadata *md; vm_offset_t addr; u_int64_t kernend; u_int64_t envp; vm_offset_t size; char *rootdevname; int howto; if (!bi_checkcpu()) { printf("CPU doesn't support long mode\n"); return (EINVAL); } howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); userboot_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(userboot_fmtdev((void *)rootdev)); /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* copy our environment */ envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf64 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); bios_addsmapdata(kfp); /* Figure out the size and location of the metadata */ *modulep = addr; size = bi_copymodules64(0); kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* copy module list and metadata */ (void)bi_copymodules64(addr); return(0); }
/* * Load the information expected by the kernel. * * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey, UINTN pages) { char *rootdevname; struct efi_devdesc *rootdev; struct preloaded_file *xp; vaddr_t addr, bootinfo_addr; vaddr_t ssym, esym; struct file_metadata *md; EFI_STATUS status; UINTN bisz, key; /* * Version 1 bootinfo. */ bi->bi_magic = BOOTINFO_MAGIC; bi->bi_version = 1; /* * Calculate boothowto. */ bi->bi_boothowto = bi_getboothowto(fp->f_args); /* * Stash EFI System Table. */ bi->bi_systab = (u_int64_t) ST; /* * Allow the environment variable 'rootdev' to override the supplied * device. This should perhaps go to MI code and/or have $rootdev * tested/set by MI code before launching the kernel. */ rootdevname = getenv("rootdev"); efi_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(efi_fmtdev((void *)rootdev)); free(rootdev); ssym = esym = 0; ssym = fp->marks[MARK_SYM]; esym = fp->marks[MARK_END]; if (ssym == 0 || esym == 0) ssym = esym = 0; /* sanity */ bi->bi_symtab = ssym; bi->bi_esymtab = esym; bi->bi_hcdp = (uint64_t)efi_get_table(&hcdp); /* DIG64 HCDP table addr. */ fpswa_init(&bi->bi_fpswa); /* find FPSWA interface */ /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ addr = (addr + PAGE_MASK) & ~PAGE_MASK; /* copy our environment */ bi->bi_envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ addr = (addr + PAGE_MASK) & ~PAGE_MASK; /* all done copying stuff in, save end of loaded object space */ bi->bi_kernend = addr; /* * Read the memory map and stash it after bootinfo. Align the memory map * on a 16-byte boundary (the bootinfo block is page aligned). */ bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f; bi->bi_memmap = ((u_int64_t)bi) + bisz; bi->bi_memmap_size = EFI_PAGE_SIZE * pages - bisz; status = BS->GetMemoryMap(&bi->bi_memmap_size, (EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, &key, &bi->bi_memdesc_size, &bi->bi_memdesc_version); if (EFI_ERROR(status)) { printf("bi_load: Can't read memory map\n"); return EINVAL; } *mapkey = key; return(0); }
/* * Load the information expected by the kernel. * * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int ia64_bootinfo(struct preloaded_file *fp, struct bootinfo **res) { struct bootinfo bi; struct preloaded_file *xp; struct file_metadata *md; struct devdesc *rootdev; char *rootdevname; vm_offset_t addr, ssym, esym; int error; *res = NULL; bzero(&bi, sizeof(struct bootinfo)); bi.bi_magic = BOOTINFO_MAGIC; bi.bi_version = 1; bi.bi_boothowto = bi_getboothowto(fp->f_args); /* * Allow the environment variable 'rootdev' to override the supplied * device. This should perhaps go to MI code and/or have $rootdev * tested/set by MI code before launching the kernel. */ rootdevname = getenv("rootdev"); ia64_getdev((void**)&rootdev, rootdevname, NULL); if (rootdev != NULL) { /* Try reading /etc/fstab to select the root device. */ getrootmount(ia64_fmtdev(rootdev)); free(rootdev); } md = file_findmetadata(fp, MODINFOMD_SSYM); ssym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; md = file_findmetadata(fp, MODINFOMD_ESYM); esym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; if (ssym != 0 && esym != 0) { bi.bi_symtab = ssym; bi.bi_esymtab = esym; } /* Find the last module in the chain. */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } addr = (addr + 15) & ~15; /* Copy module list and metadata. */ bi.bi_modulep = addr; addr = bi_copymodules(addr); if (addr <= bi.bi_modulep) { addr = bi.bi_modulep; bi.bi_modulep = 0; } addr = (addr + 15) & ~15; /* Copy our environment. */ bi.bi_envp = addr; addr = bi_copyenv(addr); if (addr <= bi.bi_envp) { addr = bi.bi_envp; bi.bi_envp = 0; } addr = (addr + 15) & ~15; bi.bi_kernend = addr; error = ia64_platform_bootinfo(&bi, res); if (error) return (error); if (IS_LEGACY_KERNEL()) { if (*res == NULL) return (EDOOFUS); bcopy(&bi, *res, sizeof(bi)); return (0); } bi.bi_pbvm_pgtbl = (uintptr_t)ia64_pgtbl; bi.bi_pbvm_pgtblsz = ia64_pgtblsz; ia64_copyin((void *)bi.bi_memmap, addr, bi.bi_memmap_size); bi.bi_memmap = addr; addr = (addr + bi.bi_memmap_size + 15) & ~15; bi.bi_kernend = addr + sizeof(bi); ia64_copyin(&bi, addr, sizeof(bi)); *res = (void *)addr; return (0); }