Changeset View
Changeset View
Standalone View
Standalone View
head/sys/boot/i386/zfsboot/zfsboot.c
Show All 33 Lines | |||||
#include <a.out.h> | #include <a.out.h> | ||||
#include <btxv86.h> | #include <btxv86.h> | ||||
#include "lib.h" | #include "lib.h" | ||||
#include "rbx.h" | #include "rbx.h" | ||||
#include "drv.h" | #include "drv.h" | ||||
#include "edd.h" | |||||
#include "util.h" | #include "util.h" | ||||
#include "cons.h" | #include "cons.h" | ||||
#include "bootargs.h" | #include "bootargs.h" | ||||
#include "paths.h" | #include "paths.h" | ||||
#include "libzfs.h" | #include "libzfs.h" | ||||
#define ARGS 0x900 | #define ARGS 0x900 | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
void exit(int); | void exit(int); | ||||
void reboot(void); | void reboot(void); | ||||
static void load(void); | static void load(void); | ||||
static int parse_cmd(void); | static int parse_cmd(void); | ||||
static void bios_getmem(void); | static void bios_getmem(void); | ||||
void *malloc(size_t n); | void *malloc(size_t n); | ||||
void free(void *ptr); | void free(void *ptr); | ||||
int main(void); | |||||
void * | void * | ||||
malloc(size_t n) | malloc(size_t n) | ||||
{ | { | ||||
char *p = heap_next; | char *p = heap_next; | ||||
if (p + n > heap_end) { | if (p + n > heap_end) { | ||||
printf("malloc failure\n"); | printf("malloc failure\n"); | ||||
for (;;) | for (;;) | ||||
▲ Show 20 Lines • Show All 328 Lines • ▼ Show 20 Lines | copy_dsk(struct dsk *dsk) | ||||
struct dsk *newdsk; | struct dsk *newdsk; | ||||
newdsk = malloc(sizeof(struct dsk)); | newdsk = malloc(sizeof(struct dsk)); | ||||
*newdsk = *dsk; | *newdsk = *dsk; | ||||
return (newdsk); | return (newdsk); | ||||
} | } | ||||
/* | /* | ||||
* Get disk size from eax=0x800 and 0x4800. We need to probe both | |||||
* because 0x4800 may not be available and we would like to get more | |||||
* or less correct disk size - if it is possible at all. | |||||
* Note we do not really want to touch drv.c because that code is shared | |||||
* with boot2 and we can not afford to grow that code. | |||||
*/ | |||||
static uint64_t | |||||
drvsize_ext(struct dsk *dskp) | |||||
{ | |||||
uint64_t size, tmp; | |||||
int cyl, hds, sec; | |||||
v86.ctl = V86_FLAGS; | |||||
v86.addr = 0x13; | |||||
v86.eax = 0x800; | |||||
v86.edx = dskp->drive; | |||||
v86int(); | |||||
/* Don't error out if we get bad sector number, try EDD as well */ | |||||
if (V86_CY(v86.efl) || /* carry set */ | |||||
(v86.edx & 0xff) <= (unsigned)(dskp->drive & 0x7f)) /* unit # bad */ | |||||
return (0); | |||||
cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1; | |||||
/* Convert max head # -> # of heads */ | |||||
hds = ((v86.edx & 0xff00) >> 8) + 1; | |||||
sec = v86.ecx & 0x3f; | |||||
size = (uint64_t)cyl * hds * sec; | |||||
/* Determine if we can use EDD with this device. */ | |||||
v86.ctl = V86_FLAGS; | |||||
v86.addr = 0x13; | |||||
v86.eax = 0x4100; | |||||
v86.edx = dskp->drive; | |||||
v86.ebx = 0x55aa; | |||||
v86int(); | |||||
if (V86_CY(v86.efl) || /* carry set */ | |||||
(v86.ebx & 0xffff) != 0xaa55 || /* signature */ | |||||
(v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0) | |||||
return (size); | |||||
tmp = drvsize(dskp); | |||||
if (tmp > size) | |||||
size = tmp; | |||||
return (size); | |||||
} | |||||
/* | |||||
* The "layered" ioctl to read disk/partition size. Unfortunately | * The "layered" ioctl to read disk/partition size. Unfortunately | ||||
* the zfsboot case is hardest, because we do not have full software | * the zfsboot case is hardest, because we do not have full software | ||||
* stack available, so we need to do some manual work here. | * stack available, so we need to do some manual work here. | ||||
*/ | */ | ||||
uint64_t | uint64_t | ||||
ldi_get_size(void *priv) | ldi_get_size(void *priv) | ||||
{ | { | ||||
struct dsk *dskp = priv; | struct dsk *dskp = priv; | ||||
uint64_t size = dskp->size; | uint64_t size = dskp->size; | ||||
if (dskp->start == 0) | if (dskp->start == 0) | ||||
size = drvsize(dskp); | size = drvsize_ext(dskp); | ||||
return (size * DEV_BSIZE); | return (size * DEV_BSIZE); | ||||
} | } | ||||
static void | static void | ||||
probe_drive(struct dsk *dsk) | probe_drive(struct dsk *dsk) | ||||
{ | { | ||||
#ifdef GPT | #ifdef GPT | ||||
Show All 18 Lines | |||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
/* | /* | ||||
* Taste the disk, if it is GELI encrypted, decrypt it and check to see if | * Taste the disk, if it is GELI encrypted, decrypt it and check to see if | ||||
* it is a usable vdev then. Otherwise dig | * it is a usable vdev then. Otherwise dig | ||||
* out the partition table and probe each slice/partition | * out the partition table and probe each slice/partition | ||||
* in turn for a vdev or GELI encrypted vdev. | * in turn for a vdev or GELI encrypted vdev. | ||||
*/ | */ | ||||
elba = drvsize(dsk); | elba = drvsize_ext(dsk); | ||||
if (elba > 0) { | if (elba > 0) { | ||||
elba--; | elba--; | ||||
} | } | ||||
if (geli_taste(vdev_read, dsk, elba) == 0) { | if (geli_taste(vdev_read, dsk, elba) == 0) { | ||||
if (geli_havekey(dsk) == 0 || geli_passphrase(&gelipw, dsk->unit, | if (geli_havekey(dsk) == 0 || geli_passphrase(&gelipw, dsk->unit, | ||||
':', 0, dsk) == 0) { | ':', 0, dsk) == 0) { | ||||
if (vdev_probe(vdev_read, dsk, NULL) == 0) { | if (vdev_probe(vdev_read, dsk, NULL) == 0) { | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 573 Lines • Show Last 20 Lines |