#include <stand.h>
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/linker.h>
#include <machine/bootinfo.h>
#include <machine/metadata.h>
#include "bootstrap.h"
#include "modinfo.h"
#include "libi386.h"
#include "btxv86.h"
#ifdef LOADER_GELI_SUPPORT
#include "geliboot.h"
#endif
static struct bootinfo *bi;
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);
rootdevname = getenv("rootdev");
i386_getdev((void **)(&rootdev), rootdevname, NULL);
if (rootdev == NULL) {
printf("can't determine root device\n");
return(EINVAL);
}
getrootmount(devformat(&rootdev->dd));
bootdevnr = 0;
bi = calloc(sizeof(*bi), 1);
switch(rootdev->dd.d_dev->dv_type) {
case DEVT_CD:
case DEVT_DISK:
bi->bi_bios_dev = bd_unit2bios(rootdev);
bootdevnr = bd_getdev(rootdev);
break;
case DEVT_NET:
case DEVT_ZFS:
break;
default:
printf("WARNING - don't know how to boot from device type %d\n",
rootdev->dd.d_dev->dv_type);
}
if (bootdevnr == -1) {
printf("root device %s invalid\n", devformat(&rootdev->dd));
return (EINVAL);
}
free(rootdev);
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 = md_align(addr);
addr = build_font_module(addr);
envp = addr;
addr = md_copyenv(addr);
addr = md_align(addr);
kfp = file_findfile(NULL, md_kerntype);
if (kfp == NULL)
panic("can't find kernel file");
kernend = 0;
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);
#ifdef LOADER_GELI_SUPPORT
geli_export_key_metadata(kfp);
#endif
bi_load_vbe_data(kfp);
*modulep = addr;
size = md_copymodules(0, false);
kernend = md_align(addr + size);
*kernendp = kernend;
md = file_findmetadata(kfp, MODINFOMD_KERNEND);
bcopy(&kernend, md->md_data, sizeof kernend);
(void)md_copymodules(addr, false);
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;
kernelname = getenv("kernelname");
i386_getdev(NULL, kernelname, &kernelpath);
bi->bi_version = BOOTINFO_VERSION;
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;
bi->bi_esymtab = esym;
*howtop = howto | RB_BOOTINFO;
*bootdevp = bootdevnr;
*bip = VTOP(bi);
return(0);
}