Changeset View
Changeset View
Standalone View
Standalone View
head/sys/boot/i386/zfsboot/zfsboot.c
Show All 40 Lines | |||||
#include "drv.h" | #include "drv.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 | ||||
#define NOPT 14 | #define NOPT 14 | ||||
#define NDEV 3 | #define NDEV 3 | ||||
#define BIOS_NUMDRIVES 0x475 | #define BIOS_NUMDRIVES 0x475 | ||||
#define DRV_HARD 0x80 | #define DRV_HARD 0x80 | ||||
#define DRV_MASK 0x7f | #define DRV_MASK 0x7f | ||||
#define TYPE_AD 0 | #define TYPE_AD 0 | ||||
#define TYPE_DA 1 | #define TYPE_DA 1 | ||||
#define TYPE_MAXHARD TYPE_DA | #define TYPE_MAXHARD TYPE_DA | ||||
#define TYPE_FD 2 | #define TYPE_FD 2 | ||||
#define DEV_GELIBOOT_BSIZE 4096 | |||||
extern uint32_t _end; | extern uint32_t _end; | ||||
#ifdef GPT | #ifdef GPT | ||||
static const uuid_t freebsd_zfs_uuid = GPT_ENT_TYPE_FREEBSD_ZFS; | static const uuid_t freebsd_zfs_uuid = GPT_ENT_TYPE_FREEBSD_ZFS; | ||||
#endif | #endif | ||||
static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ | static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ | ||||
static const unsigned char flags[NOPT] = { | static const unsigned char flags[NOPT] = { | ||||
RBX_DUAL, | RBX_DUAL, | ||||
Show All 29 Lines | |||||
vm_offset_t high_heap_base; | vm_offset_t high_heap_base; | ||||
uint32_t bios_basemem, bios_extmem, high_heap_size; | uint32_t bios_basemem, bios_extmem, high_heap_size; | ||||
static struct bios_smap smap; | static struct bios_smap smap; | ||||
/* | /* | ||||
* The minimum amount of memory to reserve in bios_extmem for the heap. | * The minimum amount of memory to reserve in bios_extmem for the heap. | ||||
*/ | */ | ||||
#define HEAP_MIN (3 * 1024 * 1024) | #define HEAP_MIN (3 * 1024 * 1024) | ||||
static char *heap_next; | static char *heap_next; | ||||
static char *heap_end; | static char *heap_end; | ||||
/* Buffers that must not span a 64k boundary. */ | /* Buffers that must not span a 64k boundary. */ | ||||
#define READ_BUF_SIZE 8192 | #define READ_BUF_SIZE 8192 | ||||
struct dmadat { | struct dmadat { | ||||
char rdbuf[READ_BUF_SIZE]; /* for reading large things */ | char rdbuf[READ_BUF_SIZE]; /* for reading large things */ | ||||
char secbuf[READ_BUF_SIZE]; /* for MBR/disklabel */ | char secbuf[READ_BUF_SIZE]; /* for MBR/disklabel */ | ||||
}; | }; | ||||
static struct dmadat *dmadat; | static struct dmadat *dmadat; | ||||
void exit(int); | void exit(int); | ||||
static void load(void); | static void load(void); | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* A wrapper for dskread that doesn't have to worry about whether the | * A wrapper for dskread that doesn't have to worry about whether the | ||||
* buffer pointer crosses a 64k boundary. | * buffer pointer crosses a 64k boundary. | ||||
*/ | */ | ||||
static int | static int | ||||
vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) | vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) | ||||
{ | { | ||||
char *p; | char *p; | ||||
daddr_t lba; | daddr_t lba, alignlba; | ||||
unsigned int nb; | off_t alignoff, diff; | ||||
unsigned int nb, alignnb; | |||||
struct dsk *dsk = (struct dsk *) priv; | struct dsk *dsk = (struct dsk *) 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 += dsk->start; | lba += dsk->start; | ||||
/* Align reads to 4k else 4k sector GELIs will not decrypt. */ | |||||
alignoff = off & ~ (off_t)(DEV_GELIBOOT_BSIZE - 1); | |||||
/* Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes. */ | |||||
alignlba = alignoff / DEV_BSIZE; | |||||
/* | |||||
* The read must be aligned to DEV_GELIBOOT_BSIZE bytes relative to the | |||||
* start of the GELI partition, not the start of the actual disk. | |||||
*/ | |||||
alignlba += dsk->start; | |||||
diff = (lba - alignlba) * DEV_BSIZE; | |||||
while (bytes > 0) { | while (bytes > 0) { | ||||
nb = bytes / DEV_BSIZE; | nb = bytes / DEV_BSIZE; | ||||
if (nb > READ_BUF_SIZE / DEV_BSIZE) | if (nb > READ_BUF_SIZE / DEV_BSIZE) | ||||
nb = READ_BUF_SIZE / DEV_BSIZE; | nb = READ_BUF_SIZE / DEV_BSIZE; | ||||
if (drvread(dsk, dmadat->rdbuf, lba, nb)) | /* | ||||
* Ensure that the read size plus the leading offset does not | |||||
* exceed the size of the read buffer. | |||||
*/ | |||||
if (nb * DEV_BSIZE + diff > READ_BUF_SIZE) | |||||
nb -= diff / DEV_BSIZE; | |||||
/* | |||||
* Round the number of blocks to read up to the nearest multiple | |||||
* of DEV_GELIBOOT_BSIZE. | |||||
*/ | |||||
alignnb = nb + (diff / DEV_BSIZE) + | |||||
(DEV_GELIBOOT_BSIZE / DEV_BSIZE - 1) & ~ | |||||
(unsigned int)(DEV_GELIBOOT_BSIZE / DEV_BSIZE - 1); | |||||
if (drvread(dsk, dmadat->rdbuf, alignlba, alignnb)) | |||||
return -1; | return -1; | ||||
#ifdef LOADER_GELI_SUPPORT | #ifdef LOADER_GELI_SUPPORT | ||||
/* decrypt */ | /* decrypt */ | ||||
if (is_geli(dsk) == 0) { | if (is_geli(dsk) == 0) { | ||||
if (geli_read(dsk, ((lba - dsk->start) * DEV_BSIZE), | if (geli_read(dsk, ((alignlba - dsk->start) * | ||||
dmadat->rdbuf, nb * DEV_BSIZE)) | DEV_BSIZE), dmadat->rdbuf, alignnb * DEV_BSIZE)) | ||||
return (-1); | return (-1); | ||||
} | } | ||||
#endif | #endif | ||||
memcpy(p, dmadat->rdbuf, nb * DEV_BSIZE); | memcpy(p, dmadat->rdbuf + diff, nb * DEV_BSIZE); | ||||
p += nb * DEV_BSIZE; | p += nb * DEV_BSIZE; | ||||
lba += nb; | lba += nb; | ||||
alignlba += alignnb; | |||||
bytes -= nb * DEV_BSIZE; | bytes -= nb * DEV_BSIZE; | ||||
/* Don't need the leading offset after the first block. */ | |||||
diff = 0; | |||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte) | xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 683 Lines • Show Last 20 Lines |