merge 4096 into luks

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-04-24 03:12:06 +02:00
commit 572e3ea650
9 changed files with 334 additions and 221 deletions

View file

@ -460,11 +460,12 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
#ifdef GRUB_UTIL
if (dev->cheat)
{
err = grub_util_fd_sector_seek (dev->cheat_fd, dev->cheat, sector);
err = grub_util_fd_seek (dev->cheat_fd, dev->cheat,
sector << disk->log_sector_size);
if (err)
return err;
if (grub_util_fd_read (dev->cheat_fd, buf, size << GRUB_DISK_SECTOR_BITS)
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
if (grub_util_fd_read (dev->cheat_fd, buf, size << disk->log_sector_size)
!= (ssize_t) (size << disk->log_sector_size))
return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'",
dev->cheat);
return GRUB_ERR_NONE;
@ -476,15 +477,17 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
size, sector, dev->offset);
err = grub_disk_read (dev->source_disk, sector + dev->offset, 0,
size << GRUB_DISK_SECTOR_BITS, buf);
err = grub_disk_read (dev->source_disk,
(sector << (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS)) + dev->offset, 0,
size << disk->log_sector_size, buf);
if (err)
{
grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err);
return err;
}
gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf,
size << GRUB_DISK_SECTOR_BITS,
size << disk->log_sector_size,
sector);
return grub_crypto_gcry_error (gcry_err);
}

View file

@ -33,12 +33,10 @@ struct grub_efidisk_data
grub_efi_device_path_t *device_path;
grub_efi_device_path_t *last_device_path;
grub_efi_block_io_t *block_io;
grub_efi_disk_io_t *disk_io;
struct grub_efidisk_data *next;
};
/* GUIDs. */
static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
/* GUID. */
static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
static struct grub_efidisk_data *fd_devices;
@ -143,7 +141,7 @@ make_devices (void)
struct grub_efidisk_data *devices = 0;
/* Find handles which support the disk io interface. */
handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &disk_io_guid,
handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid,
0, &num_handles);
if (! handles)
return 0;
@ -155,7 +153,6 @@ make_devices (void)
grub_efi_device_path_t *ldp;
struct grub_efidisk_data *d;
grub_efi_block_io_t *bio;
grub_efi_disk_io_t *dio;
dp = grub_efi_get_device_path (*handle);
if (! dp)
@ -168,9 +165,7 @@ make_devices (void)
bio = grub_efi_open_protocol (*handle, &block_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
dio = grub_efi_open_protocol (*handle, &disk_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (! bio || ! dio)
if (! bio)
/* This should not happen... Why? */
continue;
@ -186,7 +181,6 @@ make_devices (void)
d->device_path = dp;
d->last_device_path = ldp;
d->block_io = bio;
d->disk_io = dio;
d->next = devices;
devices = d;
}
@ -536,8 +530,13 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
and total sectors should be replaced with total blocks. */
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
m, (unsigned long long) m->last_block, m->block_size);
disk->total_sectors = (m->last_block
* (m->block_size >> GRUB_DISK_SECTOR_BITS));
disk->total_sectors = m->last_block;
if (m->block_size & (m->block_size - 1) || !m->block_size)
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
m->block_size);
for (disk->log_sector_size = 0;
(1U << disk->log_sector_size) < m->block_size;
disk->log_sector_size++);
disk->data = d;
grub_dprintf ("efidisk", "opening %s succeeded\n", name);
@ -558,22 +557,20 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"reading 0x%lx sectors at the sector 0x%llx from %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
status = efi_call_5 (dio->read, dio, bio->media->media_id,
(grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
buf);
status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id,
(grub_efi_uint64_t) sector,
(grub_efi_uintn_t) size << disk->log_sector_size,
buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error");
@ -586,21 +583,19 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"writing 0x%lx sectors at the sector 0x%llx to %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
status = efi_call_5 (dio->write, dio, bio->media->media_id,
(grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id,
(grub_efi_uint64_t) sector,
(grub_efi_uintn_t) size << disk->log_sector_size,
(void *) buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error");

View file

@ -350,7 +350,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk,
if ((cd_drive) && (drive == cd_drive))
{
data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
data->sectors = 32;
data->sectors = 8;
disk->log_sector_size = 11;
/* TODO: get the correct size. */
total_sectors = GRUB_DISK_SIZE_UNKNOWN;
}
@ -359,6 +360,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk,
/* HDD */
int version;
disk->log_sector_size = 9;
version = grub_biosdisk_check_int13_extensions (drive);
if (version)
{
@ -379,6 +382,15 @@ grub_biosdisk_open (const char *name, grub_disk_t disk,
correctly but returns zero. So if it is zero, compute
it by C/H/S returned by the LBA BIOS call. */
total_sectors = drp->cylinders * drp->heads * drp->sectors;
if (drp->bytes_per_sector
&& !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
&& drp->bytes_per_sector >= 512
&& drp->bytes_per_sector <= 16384)
{
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < drp->bytes_per_sector;
disk->log_sector_size++);
}
}
}
}
@ -441,7 +453,7 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+ (data->sectors
<< GRUB_DISK_SECTOR_BITS));
<< disk->log_sector_size));
dap->length = sizeof (*dap);
dap->reserved = 0;
dap->blocks = size;
@ -455,9 +467,6 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
if (cmd)
return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
dap->blocks = ALIGN_UP (dap->blocks, 4) >> 2;
dap->block >>= 2;
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
break;
@ -513,10 +522,12 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
/* Return the number of sectors which can be read safely at a time. */
static grub_size_t
get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector)
{
grub_size_t size;
grub_uint32_t offset;
struct grub_biosdisk_data *data = disk->data;
grub_uint32_t sectors = data->sectors;
/* OFFSET = SECTOR % SECTORS */
grub_divmod64 (sector, sectors, &offset);
@ -524,8 +535,8 @@ get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
size = sectors - offset;
/* Limit the max to 0x7f because of Phoenix EDD. */
if (size > 0x7f)
size = 0x7f;
if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size))
size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size);
return size;
}
@ -534,21 +545,11 @@ static grub_err_t
grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
struct grub_biosdisk_data *data = disk->data;
while (size)
{
grub_size_t len;
grub_size_t cdoff = 0;
len = get_safe_sectors (sector, data->sectors);
if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
{
cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS;
len = ALIGN_UP (sector + len, 4) - (sector & ~3);
sector &= ~3;
}
len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
@ -557,9 +558,10 @@ grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff),
len << GRUB_DISK_SECTOR_BITS);
buf += len << GRUB_DISK_SECTOR_BITS;
grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
len << disk->log_sector_size);
buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
@ -580,18 +582,18 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
{
grub_size_t len;
len = get_safe_sectors (sector, data->sectors);
len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf,
len << GRUB_DISK_SECTOR_BITS);
len << disk->log_sector_size);
if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
buf += len << GRUB_DISK_SECTOR_BITS;
buf += len << disk->log_sector_size;
sector += len;
size -= len;
}

View file

@ -470,15 +470,20 @@ grub_scsi_open (const char *name, grub_disk_t disk,
return err;
}
/* SCSI blocks can be something else than 512, although GRUB
wants 512 byte blocks. */
disk->total_sectors = ((grub_uint64_t)scsi->size
* (grub_uint64_t)scsi->blocksize)
>> GRUB_DISK_SECTOR_BITS;
disk->total_sectors = scsi->size;
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
{
grub_free (scsi);
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
scsi->blocksize);
}
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < scsi->blocksize;
disk->log_sector_size++);
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
scsi->size, scsi->blocksize);
grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n",
grub_dprintf ("scsi", "Disk total sectors = %llu\n",
(unsigned long long) disk->total_sectors);
return GRUB_ERR_NONE;
@ -508,25 +513,6 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
scsi = disk->data;
/* SCSI sectors are variable in size. GRUB uses 512 byte
sectors. */
if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE)
{
unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS;
if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported SCSI block size");
grub_uint32_t sector_mod = 0;
sector = grub_divmod64 (sector, spb, &sector_mod);
if (! (sector_mod == 0 && size % spb == 0))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unaligned SCSI read not supported");
size /= spb;
}
/* Depending on the type, select a read function. */
switch (scsi->devtype)
{