Changeset View
Changeset View
Standalone View
Standalone View
head/stand/i386/gptboot/gptboot.c
Show First 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | |||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
static int vdev_read(void *vdev __unused, void *priv, off_t off, void *buf, | static int vdev_read(void *vdev __unused, void *priv, off_t off, void *buf, | ||||
size_t bytes); | size_t bytes); | ||||
#endif | #endif | ||||
#include "ufsread.c" | #include "ufsread.c" | ||||
#include "gpt.c" | #include "gpt.c" | ||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
#include "geliboot.c" | #include "geliboot.h" | ||||
static char gelipw[GELI_PW_MAXLEN]; | static char gelipw[GELI_PW_MAXLEN]; | ||||
static struct keybuf *gelibuf; | static struct keybuf *gelibuf; | ||||
#endif | #endif | ||||
struct gptdsk { | |||||
struct dsk dsk; | |||||
#ifdef LOADER_GELI_SUPPORT | |||||
struct geli_dev *gdev; | |||||
#endif | |||||
}; | |||||
static struct gptdsk gdsk; | |||||
static inline int | static inline int | ||||
xfsread(ufs_ino_t inode, void *buf, size_t nbyte) | xfsread(ufs_ino_t inode, void *buf, size_t nbyte) | ||||
{ | { | ||||
if ((size_t)fsread(inode, buf, nbyte) != nbyte) { | if ((size_t)fsread(inode, buf, nbyte) != nbyte) { | ||||
printf("Invalid %s\n", "format"); | printf("Invalid %s\n", "format"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) { | ||||
high_heap_base = bios_extmem + 0x100000 - HEAP_MIN; | high_heap_base = bios_extmem + 0x100000 - HEAP_MIN; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
gptinit(void) | gptinit(void) | ||||
{ | { | ||||
if (gptread(&freebsd_ufs_uuid, &dsk, dmadat->secbuf) == -1) { | if (gptread(&freebsd_ufs_uuid, &gdsk.dsk, dmadat->secbuf) == -1) { | ||||
printf("%s: unable to load GPT\n", BOOTPROG); | printf("%s: unable to load GPT\n", BOOTPROG); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (gptfind(&freebsd_ufs_uuid, &dsk, dsk.part) == -1) { | if (gptfind(&freebsd_ufs_uuid, &gdsk.dsk, gdsk.dsk.part) == -1) { | ||||
printf("%s: no UFS partition was found\n", BOOTPROG); | printf("%s: no UFS partition was found\n", BOOTPROG); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
if (geli_taste(vdev_read, &dsk, (gpttable[curent].ent_lba_end - | gdsk.gdev = geli_taste(vdev_read, &gdsk.dsk, | ||||
gpttable[curent].ent_lba_start)) == 0) { | (gpttable[curent].ent_lba_end - gpttable[curent].ent_lba_start), | ||||
if (geli_havekey(&dsk) != 0 && geli_passphrase(gelipw, | "disk%up%u:", gdsk.dsk.unit, curent + 1); | ||||
dsk.unit, 'p', curent + 1, &dsk) != 0) { | if (gdsk.gdev != NULL) { | ||||
if (geli_havekey(gdsk.gdev) != 0 && | |||||
geli_passphrase(gdsk.gdev, gelipw) != 0) { | |||||
printf("%s: unable to decrypt GELI key\n", BOOTPROG); | printf("%s: unable to decrypt GELI key\n", BOOTPROG); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
dsk_meta = 0; | dsk_meta = 0; | ||||
return (0); | return (0); | ||||
Show All 19 Lines | main(void) | ||||
} else { | } else { | ||||
heap_next = (char *)dmadat + sizeof(*dmadat); | heap_next = (char *)dmadat + sizeof(*dmadat); | ||||
heap_end = (char *)PTOV(bios_basemem); | heap_end = (char *)PTOV(bios_basemem); | ||||
} | } | ||||
setheap(heap_next, heap_end); | setheap(heap_next, heap_end); | ||||
v86.ctl = V86_FLAGS; | v86.ctl = V86_FLAGS; | ||||
v86.efl = PSL_RESERVED_DEFAULT | PSL_I; | v86.efl = PSL_RESERVED_DEFAULT | PSL_I; | ||||
dsk.drive = *(uint8_t *)PTOV(ARGS); | gdsk.dsk.drive = *(uint8_t *)PTOV(ARGS); | ||||
dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD; | gdsk.dsk.type = gdsk.dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD; | ||||
dsk.unit = dsk.drive & DRV_MASK; | gdsk.dsk.unit = gdsk.dsk.drive & DRV_MASK; | ||||
dsk.part = -1; | gdsk.dsk.part = -1; | ||||
dsk.start = 0; | gdsk.dsk.start = 0; | ||||
bootinfo.bi_version = BOOTINFO_VERSION; | bootinfo.bi_version = BOOTINFO_VERSION; | ||||
bootinfo.bi_size = sizeof(bootinfo); | bootinfo.bi_size = sizeof(bootinfo); | ||||
bootinfo.bi_basemem = bios_basemem / 1024; | bootinfo.bi_basemem = bios_basemem / 1024; | ||||
bootinfo.bi_extmem = bios_extmem / 1024; | bootinfo.bi_extmem = bios_extmem / 1024; | ||||
bootinfo.bi_memsizes_valid++; | bootinfo.bi_memsizes_valid++; | ||||
bootinfo.bi_bios_dev = dsk.drive; | bootinfo.bi_bios_dev = gdsk.dsk.drive; | ||||
#ifdef LOADER_GELI_SUPPORT | |||||
geli_init(); | |||||
#endif | |||||
/* Process configuration file */ | /* Process configuration file */ | ||||
if (gptinit() != 0) | if (gptinit() != 0) | ||||
return (-1); | return (-1); | ||||
autoboot = 1; | autoboot = 1; | ||||
*cmd = '\0'; | *cmd = '\0'; | ||||
Show All 28 Lines | for (;;) { | ||||
* directly instead. | * directly instead. | ||||
*/ | */ | ||||
if (*kname != '\0') | if (*kname != '\0') | ||||
load(); | load(); | ||||
memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER)); | memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER)); | ||||
load(); | load(); | ||||
memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); | memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); | ||||
load(); | load(); | ||||
gptbootfailed(&dsk); | gptbootfailed(&gdsk.dsk); | ||||
if (gptfind(&freebsd_ufs_uuid, &dsk, -1) == -1) | if (gptfind(&freebsd_ufs_uuid, &gdsk.dsk, -1) == -1) | ||||
break; | break; | ||||
dsk_meta = 0; | dsk_meta = 0; | ||||
} | } | ||||
/* Present the user with the boot2 prompt. */ | /* Present the user with the boot2 prompt. */ | ||||
for (;;) { | for (;;) { | ||||
if (!OPT_CHECK(RBX_QUIET)) { | if (!OPT_CHECK(RBX_QUIET)) { | ||||
printf("\nFreeBSD/x86 boot\n" | printf("\nFreeBSD/x86 boot\n" | ||||
"Default: %u:%s(%up%u)%s\n" | "Default: %u:%s(%up%u)%s\n" | ||||
"boot: ", | "boot: ", | ||||
dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, | gdsk.dsk.drive & DRV_MASK, dev_nm[gdsk.dsk.type], | ||||
dsk.part, kname); | gdsk.dsk.unit, gdsk.dsk.part, kname); | ||||
} | } | ||||
if (ioctrl & IO_SERIAL) | if (ioctrl & IO_SERIAL) | ||||
sio_flush(); | sio_flush(); | ||||
*cmd = '\0'; | *cmd = '\0'; | ||||
if (keyhit(0)) | if (keyhit(0)) | ||||
getstr(cmd, sizeof(cmd)); | getstr(cmd, sizeof(cmd)); | ||||
else if (!OPT_CHECK(RBX_QUIET)) | else if (!OPT_CHECK(RBX_QUIET)) | ||||
putchar('\n'); | putchar('\n'); | ||||
Show All 29 Lines | load(void) | ||||
caddr_t p; | caddr_t p; | ||||
ufs_ino_t ino; | ufs_ino_t ino; | ||||
uint32_t addr, x; | uint32_t addr, x; | ||||
int fmt, i, j; | int fmt, i, j; | ||||
if (!(ino = lookup(kname))) { | if (!(ino = lookup(kname))) { | ||||
if (!ls) { | if (!ls) { | ||||
printf("%s: No %s on %u:%s(%up%u)\n", BOOTPROG, | printf("%s: No %s on %u:%s(%up%u)\n", BOOTPROG, | ||||
kname, dsk.drive & DRV_MASK, dev_nm[dsk.type], | kname, gdsk.dsk.drive & DRV_MASK, dev_nm[gdsk.dsk.type], | ||||
dsk.unit, | gdsk.dsk.unit, gdsk.dsk.part); | ||||
dsk.part); | |||||
} | } | ||||
return; | return; | ||||
} | } | ||||
if (xfsread(ino, &hdr, sizeof(hdr))) | if (xfsread(ino, &hdr, sizeof(hdr))) | ||||
return; | return; | ||||
if (N_GETMAGIC(hdr.ex) == ZMAGIC) | if (N_GETMAGIC(hdr.ex) == ZMAGIC) | ||||
fmt = 0; | fmt = 0; | ||||
else if (IS_ELF(hdr.eh)) | else if (IS_ELF(hdr.eh)) | ||||
fmt = 1; | fmt = 1; | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { | ||||
return; | return; | ||||
p += es[i].sh_size; | p += es[i].sh_size; | ||||
} | } | ||||
} | } | ||||
addr = hdr.eh.e_entry & 0xffffff; | addr = hdr.eh.e_entry & 0xffffff; | ||||
} | } | ||||
bootinfo.bi_esymtab = VTOP(p); | bootinfo.bi_esymtab = VTOP(p); | ||||
bootinfo.bi_kernelname = VTOP(kname); | bootinfo.bi_kernelname = VTOP(kname); | ||||
bootinfo.bi_bios_dev = dsk.drive; | bootinfo.bi_bios_dev = gdsk.dsk.drive; | ||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
geliargs.size = sizeof(geliargs); | geliargs.size = sizeof(geliargs); | ||||
explicit_bzero(gelipw, sizeof(gelipw)); | explicit_bzero(gelipw, sizeof(gelipw)); | ||||
gelibuf = malloc(sizeof(struct keybuf) + | gelibuf = malloc(sizeof(struct keybuf) + | ||||
(GELI_MAX_KEYS * sizeof(struct keybuf_ent))); | (GELI_MAX_KEYS * sizeof(struct keybuf_ent))); | ||||
geli_fill_keybuf(gelibuf); | geli_export_key_buffer(gelibuf); | ||||
geliargs.notapw = '\0'; | geliargs.notapw = '\0'; | ||||
geliargs.keybuf_sentinel = KEYBUF_SENTINEL; | geliargs.keybuf_sentinel = KEYBUF_SENTINEL; | ||||
geliargs.keybuf = gelibuf; | geliargs.keybuf = gelibuf; | ||||
#endif | #endif | ||||
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), | __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), | ||||
MAKEBOOTDEV(dev_maj[dsk.type], dsk.part + 1, dsk.unit, 0xff), | MAKEBOOTDEV(dev_maj[gdsk.dsk.type], gdsk.dsk.part + 1, gdsk.dsk.unit, 0xff), | ||||
KARGS_FLAGS_EXTARG, 0, 0, VTOP(&bootinfo) | KARGS_FLAGS_EXTARG, 0, 0, VTOP(&bootinfo) | ||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
, geliargs | , geliargs | ||||
#endif | #endif | ||||
); | ); | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | parse_cmds(char *cmdstr, int *dskupdated) | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
dskread(void *buf, daddr_t lba, unsigned nblk) | dskread(void *buf, daddr_t lba, unsigned nblk) | ||||
{ | { | ||||
int err; | int err; | ||||
err = drvread(&dsk, buf, lba + dsk.start, nblk); | err = drvread(&gdsk.dsk, buf, lba + gdsk.dsk.start, nblk); | ||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
if (err == 0 && is_geli(&dsk) == 0) { | if (err == 0 && gdsk.gdev != NULL) { | ||||
/* Decrypt */ | /* Decrypt */ | ||||
if (geli_read(&dsk, lba * DEV_BSIZE, buf, nblk * DEV_BSIZE)) | if (geli_read(gdsk.gdev, lba * DEV_BSIZE, buf, | ||||
nblk * DEV_BSIZE)) | |||||
return (err); | return (err); | ||||
} | } | ||||
#endif | #endif | ||||
return (err); | return (err); | ||||
} | } | ||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
/* | /* | ||||
* Read function compartible with the ZFS callback, required to keep the GELI | * Read function compatible with the ZFS callback, required to keep the GELI | ||||
* Implementation the same for both UFS and ZFS | * implementation the same for both UFS and ZFS. | ||||
*/ | */ | ||||
static int | static int | ||||
vdev_read(void *vdev __unused, void *priv, off_t off, void *buf, size_t bytes) | vdev_read(void *vdev __unused, void *priv, off_t off, void *buf, size_t bytes) | ||||
{ | { | ||||
char *p; | char *p; | ||||
daddr_t lba; | daddr_t lba; | ||||
unsigned int nb; | unsigned int nb; | ||||
struct dsk *dskp; | struct gptdsk *dskp; | ||||
dskp = (struct dsk *)priv; | dskp = (struct gptdsk *)priv; | ||||
if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1))) | if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1))) | ||||
return (-1); | return (-1); | ||||
p = buf; | p = buf; | ||||
lba = off / DEV_BSIZE; | lba = off / DEV_BSIZE; | ||||
lba += dskp->start; | lba += dskp->dsk.start; | ||||
while (bytes > 0) { | while (bytes > 0) { | ||||
nb = bytes / DEV_BSIZE; | nb = bytes / DEV_BSIZE; | ||||
if (nb > VBLKSIZE / DEV_BSIZE) | if (nb > VBLKSIZE / DEV_BSIZE) | ||||
nb = VBLKSIZE / DEV_BSIZE; | nb = VBLKSIZE / DEV_BSIZE; | ||||
if (drvread(dskp, dmadat->blkbuf, lba, nb)) | if (drvread(&dskp->dsk, dmadat->blkbuf, lba, nb)) | ||||
return (-1); | return (-1); | ||||
memcpy(p, dmadat->blkbuf, nb * DEV_BSIZE); | memcpy(p, dmadat->blkbuf, nb * DEV_BSIZE); | ||||
p += nb * DEV_BSIZE; | p += nb * DEV_BSIZE; | ||||
lba += nb; | lba += nb; | ||||
bytes -= nb * DEV_BSIZE; | bytes -= nb * DEV_BSIZE; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
#endif /* LOADER_GELI_SUPPORT */ | #endif /* LOADER_GELI_SUPPORT */ |