reading large extents and decrease amount of blocklist hook calls.
+2013-11-01 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Rewrite blocklist functions in order to get progress when
+ reading large extents and decrease amount of blocklist hook calls.
+
2013-11-01 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/term/serial.c (options), (grub_cmd_serial): Fix handling
if (ctx->num_sectors > 0)
{
if (ctx->start_sector + ctx->num_sectors == sector
- && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
+ && offset == 0 && length >= GRUB_DISK_SECTOR_SIZE)
{
- ctx->num_sectors++;
- return;
+ ctx->num_sectors += length >> GRUB_DISK_SECTOR_BITS;
+ sector += length >> GRUB_DISK_SECTOR_BITS;
+ length &= (GRUB_DISK_SECTOR_SIZE - 1);
}
+ if (!length)
+ return;
print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx);
ctx->num_sectors = 0;
}
- if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
+ if (offset)
{
- ctx->start_sector = sector;
- ctx->num_sectors++;
+ unsigned l = length + offset;
+ l &= (GRUB_DISK_SECTOR_SIZE - 1);
+ l -= offset;
+ print_blocklist (sector, 0, offset, l, ctx);
+ length -= l;
+ sector++;
+ offset = 0;
+ }
+
+ if (!length)
+ return;
+
+ if (length & (GRUB_DISK_SECTOR_SIZE - 1))
+ {
+ if (length >> GRUB_DISK_SECTOR_BITS)
+ {
+ print_blocklist (sector, length >> GRUB_DISK_SECTOR_BITS, 0, 0, ctx);
+ sector += length >> GRUB_DISK_SECTOR_BITS;
+ }
+ print_blocklist (sector, 0, 0, length & (GRUB_DISK_SECTOR_SIZE - 1), ctx);
}
else
- print_blocklist (sector, 0, offset, length, ctx);
+ {
+ ctx->start_sector = sector;
+ ctx->num_sectors = length >> GRUB_DISK_SECTOR_BITS;
+ }
}
static grub_err_t
for (p = blocklists; p; p = p->next)
{
struct blocklist *q;
+ /* Check if any pair of blocks overlap. */
for (q = p->next; q; q = q->next)
{
- /* Check if any pair of blocks overlap. */
- if (p->sector == q->sector)
+ grub_disk_addr_t s1, s2;
+ grub_disk_addr_t e1, e2, t;
+
+ s1 = p->sector;
+ e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+
+ s2 = q->sector;
+ e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+
+ if (s2 > s1)
+ {
+ t = s2;
+ s2 = s1;
+ s1 = t;
+ t = e2;
+ e2 = e1;
+ e1 = t;
+ }
+ if (e1 > s2)
{
/* This might be actually valid, but it is unbelievable that
any filesystem makes such a silly allocation. */
part_start = grub_partition_get_start (disk->partition);
buf = grub_envblk_buffer (envblk);
+ char *blockbuf = NULL;
+ grub_size_t blockbuf_len = 0;
for (p = blocklists, index = 0; p; index += p->length, p = p->next)
{
- char blockbuf[GRUB_DISK_SECTOR_SIZE];
+ if (p->length > blockbuf_len)
+ {
+ grub_free (blockbuf);
+ blockbuf_len = 2 * p->length;
+ blockbuf = grub_malloc (blockbuf_len);
+ if (!blockbuf)
+ return grub_errno;
+ }
if (grub_disk_read (disk, p->sector - part_start,
p->offset, p->length, blockbuf))
struct grub_cmd_save_env_ctx *ctx = data;
struct blocklist *block;
- if (offset + length > GRUB_DISK_SECTOR_SIZE)
- /* Seemingly a bug. */
- return;
-
block = grub_malloc (sizeof (*block));
if (! block)
return;
static void
read_progress (grub_disk_addr_t sector __attribute__ ((unused)),
unsigned offset __attribute__ ((unused)),
- unsigned len __attribute__ ((unused)),
+ unsigned len,
void *data __attribute__ ((unused)))
{
- grub_xputs (".");
+ for (; len >= GRUB_DISK_SECTOR_SIZE; len -= GRUB_DISK_SECTOR_SIZE)
+ grub_xputs (".");
+ if (len)
+ grub_xputs (".");
grub_refresh ();
}
if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0)
{
- batch = 65536;
if (ata->dma)
{
cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT;
{
if (addressing == GRUB_ATA_LBA48)
addressing = GRUB_ATA_LBA;
- if (addressing != GRUB_ATA_CHS)
- batch = 256;
- else
- batch = 1;
if (ata->dma)
{
cmd = GRUB_ATA_CMD_READ_SECTORS_DMA;
}
}
- if (batch > (ata->maxbuffer >> ata->log_sector_size))
- batch = (ata->maxbuffer >> ata->log_sector_size);
+ if (addressing != GRUB_ATA_CHS)
+ batch = 256;
+ else
+ batch = 1;
while (nsectors < size)
{
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
disk->total_sectors = ata->size;
+ disk->max_agglomerate = (ata->maxbuffer >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
+ if (disk->max_agglomerate > (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size)))
+ disk->max_agglomerate = (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size));
+
disk->log_sector_size = ata->log_sector_size;
disk->id = grub_make_scsi_id (id, bus, 0);
disk->data = dev;
disk->total_sectors = dev->total_length;
+ disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
disk->id = dev->id;
dev->ref++;
return GRUB_ERR_NONE;
disk->data = lv;
disk->total_sectors = lv->size;
+ disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
return 0;
}
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 + 1;
+ /* Don't increase this value due to bug in some EFI. */
+ disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
if (m->block_size & (m->block_size - 1) || !m->block_size)
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
m->block_size);
d = disk->data;
bio = d->block_io;
- while (size > 0)
- {
- grub_size_t len;
- len = 0x500;
- if (len > size)
- len = size;
- status = efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
- bio->media->media_id,
- (grub_efi_uint64_t) sector,
- (grub_efi_uintn_t) len << disk->log_sector_size,
- buf);
- size -= len;
- buf += len << disk->log_sector_size;
- sector += len;
- if (status != GRUB_EFI_SUCCESS)
- return status;
- }
- return GRUB_EFI_SUCCESS;
+ return efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
+ bio->media->media_id,
+ (grub_efi_uint64_t) sector,
+ (grub_efi_uintn_t) size << disk->log_sector_size,
+ buf);
}
static grub_err_t
}
disk->total_sectors = total_sectors;
+ /* Limit the max to 0x7f because of Phoenix EDD. */
+ disk->max_agglomerate = 0x7f >> GRUB_DISK_CACHE_BITS;
+
disk->data = data;
return GRUB_ERR_NONE;
size = sectors - offset;
- /* Limit the max to 0x7f because of Phoenix EDD. */
- if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size))
- size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size);
-
return size;
}
/ GRUB_DISK_SECTOR_SIZE);
else
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
+ /* Avoid reading more than 512M. */
+ disk->max_agglomerate = 1 << (29 - GRUB_DISK_SECTOR_BITS
+ - GRUB_DISK_CACHE_BITS);
+
disk->id = (unsigned long) dev;
disk->data = dev;
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk");
disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE;
+ disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
disk->id = (unsigned long) "mdsk";
return GRUB_ERR_NONE;
}
disk->total_sectors = scsi->last_block + 1;
+ /* PATA doesn't support more than 32K reads.
+ Not sure about AHCI and USB. If it's confirmed that either of
+ them can do bigger reads reliably this value can be moved to 'scsi'
+ structure. */
+ disk->max_agglomerate = 32768 >> (GRUB_DISK_SECTOR_BITS
+ + GRUB_DISK_CACHE_BITS);
+
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
{
grub_free (scsi);
scsi = disk->data;
- while (size)
+ grub_err_t err;
+ /* Depending on the type, select a read function. */
+ switch (scsi->devtype)
{
- /* PATA doesn't support more than 32K reads.
- Not sure about AHCI and USB. If it's confirmed that either of
- them can do bigger reads reliably this value can be moved to 'scsi'
- structure. */
- grub_size_t len = 32768 >> disk->log_sector_size;
- grub_err_t err;
- if (len > size)
- len = size;
- /* Depending on the type, select a read function. */
- switch (scsi->devtype)
- {
- case grub_scsi_devtype_direct:
- if (sector >> 32)
- err = grub_scsi_read16 (disk, sector, len, buf);
- else
- err = grub_scsi_read10 (disk, sector, len, buf);
- if (err)
- return err;
- break;
-
- case grub_scsi_devtype_cdrom:
- if (sector >> 32)
- err = grub_scsi_read16 (disk, sector, len, buf);
- else
- err = grub_scsi_read12 (disk, sector, len, buf);
- if (err)
- return err;
- break;
- }
- size -= len;
- sector += len;
- buf += len << disk->log_sector_size;
+ case grub_scsi_devtype_direct:
+ if (sector >> 32)
+ err = grub_scsi_read16 (disk, sector, size, buf);
+ else
+ err = grub_scsi_read10 (disk, sector, size, buf);
+ if (err)
+ return err;
+ break;
+
+ case grub_scsi_devtype_cdrom:
+ if (sector >> 32)
+ err = grub_scsi_read16 (disk, sector, size, buf);
+ else
+ err = grub_scsi_read12 (disk, sector, size, buf);
+ if (err)
+ return err;
+ break;
}
return GRUB_ERR_NONE;
}
static grub_err_t
-grub_scsi_write (grub_disk_t disk __attribute((unused)),
- grub_disk_addr_t sector __attribute((unused)),
- grub_size_t size __attribute((unused)),
- const char *buf __attribute((unused)))
+grub_scsi_write (grub_disk_t disk,
+ grub_disk_addr_t sector,
+ grub_size_t size,
+ const char *buf)
{
grub_scsi_t scsi;
if (scsi->devtype == grub_scsi_devtype_cdrom)
return grub_error (GRUB_ERR_IO, N_("cannot write to CD-ROM"));
- while (size)
+ grub_err_t err;
+ /* Depending on the type, select a read function. */
+ switch (scsi->devtype)
{
- /* PATA doesn't support more than 32K reads.
- Not sure about AHCI and USB. If it's confirmed that either of
- them can do bigger reads reliably this value can be moved to 'scsi'
- structure. */
- grub_size_t len = 32768 >> disk->log_sector_size;
- grub_err_t err;
- if (len > size)
- len = size;
- /* Depending on the type, select a read function. */
- switch (scsi->devtype)
- {
- case grub_scsi_devtype_direct:
- if (sector >> 32)
- err = grub_scsi_write16 (disk, sector, len, buf);
- else
- err = grub_scsi_write10 (disk, sector, len, buf);
- if (err)
- return err;
- break;
- }
- size -= len;
- sector += len;
- buf += len << disk->log_sector_size;
+ case grub_scsi_devtype_direct:
+ if (sector >> 32)
+ err = grub_scsi_write16 (disk, sector, size, buf);
+ else
+ err = grub_scsi_write10 (disk, sector, size, buf);
+ if (err)
+ return err;
+ break;
}
return GRUB_ERR_NONE;
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a cbfsdisk");
disk->total_sectors = cbfsdisk_size / GRUB_DISK_SECTOR_SIZE;
+ disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
disk->id = (unsigned long) "cbfs";
return GRUB_ERR_NONE;
if (! disk)
return 0;
disk->log_sector_size = GRUB_DISK_SECTOR_BITS;
+ /* Default 1MiB of maximum agglomerate. */
+ disk->max_agglomerate = 1048576 >> (GRUB_DISK_SECTOR_BITS
+ + GRUB_DISK_CACHE_BITS);
p = find_part_sep (name);
if (p)
sector is already adjusted and is divisible by cache unit size.
*/
static grub_err_t
-grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
- grub_off_t offset, grub_size_t size, void *buf)
+grub_disk_read_small_real (grub_disk_t disk, grub_disk_addr_t sector,
+ grub_off_t offset, grub_size_t size, void *buf)
{
char *data;
char *tmp_buf;
}
}
+static grub_err_t
+grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
+ grub_off_t offset, grub_size_t size, void *buf)
+{
+ grub_err_t err;
+
+ err = grub_disk_read_small_real (disk, sector, offset, size, buf);
+ if (err)
+ return err;
+ if (disk->read_hook)
+ (disk->read_hook) (sector + (offset >> GRUB_DISK_SECTOR_BITS),
+ offset & (GRUB_DISK_SECTOR_SIZE - 1),
+ size, disk->read_hook_data);
+ return GRUB_ERR_NONE;
+}
+
/* Read data from the disk. */
grub_err_t
grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, void *buf)
{
- grub_off_t real_offset;
- grub_disk_addr_t real_sector;
- grub_size_t real_size;
-
/* First of all, check if the region is within the disk. */
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
{
return grub_errno;
}
- real_sector = sector;
- real_offset = offset;
- real_size = size;
-
/* First read until first cache boundary. */
if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1)))
{
/* agglomerate read until we find a first cached entry. */
for (agglomerate = 0; agglomerate
- < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS));
+ < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS))
+ && agglomerate < disk->max_agglomerate;
agglomerate++)
{
data = grub_disk_cache_fetch (disk->dev->id, disk->id,
+ (i << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS)));
+
+ if (disk->read_hook)
+ (disk->read_hook) (sector, 0, agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS),
+ disk->read_hook_data);
+
sector += agglomerate << GRUB_DISK_CACHE_BITS;
size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
buf = (char *) buf
if (data)
{
+ if (disk->read_hook)
+ (disk->read_hook) (sector, 0, (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS),
+ disk->read_hook_data);
sector += GRUB_DISK_CACHE_SIZE;
buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
return err;
}
- /* Call the read hook, if any. */
- if (disk->read_hook)
- {
- grub_disk_addr_t s = real_sector;
- grub_size_t l = real_size;
- grub_off_t o = real_offset;
-
- while (l)
- {
- grub_size_t cl;
- cl = GRUB_DISK_SECTOR_SIZE - o;
- if (cl > l)
- cl = l;
- (disk->read_hook) (s, o, cl, disk->read_hook_data);
- s++;
- l -= cl;
- o = 0;
- }
- }
-
return grub_errno;
}
disk->total_sectors = grub_util_get_fd_size (fd, map[drive].device,
&disk->log_sector_size);
disk->total_sectors >>= disk->log_sector_size;
+ disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
{
len = size & ~((1 << disk->log_sector_size) - 1);
n = size >> disk->log_sector_size;
+ if (n > (disk->max_agglomerate
+ << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS
+ - disk->log_sector_size)))
+ n = (disk->max_agglomerate
+ << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS
+ - disk->log_sector_size));
+
if ((disk->dev->write) (disk, transform_sector (disk, sector),
n, buf) != GRUB_ERR_NONE)
goto finish;
if (ioctl (fd, FS_IOC_FIEMAP, &fie1) < 0)
{
- int nblocks, i, j;
+ int nblocks, i;
int bsize;
int mul;
for (i = 0; i < nblocks; i++)
{
unsigned blk = i;
+ int rest;
if (ioctl (fd, FIBMAP, &blk) < 0)
grub_util_error (_("can't retrieve blocklists: %s"),
strerror (errno));
- for (j = 0; j < mul; j++)
- {
- int rest = core_size - ((i * mul + j) << GRUB_DISK_SECTOR_BITS);
- if (rest <= 0)
- break;
- if (rest > GRUB_DISK_SECTOR_SIZE)
- rest = GRUB_DISK_SECTOR_SIZE;
- callback (((grub_uint64_t) blk) * mul + j
- + container_start,
- 0, rest, hook_data);
- }
+ rest = core_size - ((i * mul) << GRUB_DISK_SECTOR_BITS);
+ if (rest <= 0)
+ break;
+ if (rest > GRUB_DISK_SECTOR_SIZE * mul)
+ rest = GRUB_DISK_SECTOR_SIZE * mul;
+ callback (((grub_uint64_t) blk) * mul
+ + container_start,
+ 0, rest, hook_data);
}
}
else
{
struct fiemap *fie2;
- int i, j;
+ int i;
fie2 = xmalloc (sizeof (*fie2)
+ fie1.fm_mapped_extents
* sizeof (fie1.fm_extents[1]));
strerror (errno));
for (i = 0; i < fie2->fm_mapped_extents; i++)
{
- for (j = 0;
- j < ((fie2->fm_extents[i].fe_length
- + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS);
- j++)
- {
- size_t len = (fie2->fm_extents[i].fe_length
- - j * GRUB_DISK_SECTOR_SIZE);
- if (len > GRUB_DISK_SECTOR_SIZE)
- len = GRUB_DISK_SECTOR_SIZE;
- callback ((fie2->fm_extents[i].fe_physical
- >> GRUB_DISK_SECTOR_BITS)
- + j + container_start,
- fie2->fm_extents[i].fe_physical
- & (GRUB_DISK_SECTOR_SIZE - 1), len, hook_data);
- }
+ callback ((fie2->fm_extents[i].fe_physical
+ >> GRUB_DISK_SECTOR_BITS)
+ + container_start,
+ fie2->fm_extents[i].fe_physical
+ & (GRUB_DISK_SECTOR_SIZE - 1),
+ fie2->fm_extents[i].fe_length, hook_data);
}
}
close (fd);
DWORD rets;
RETRIEVAL_POINTERS_BUFFER *extbuf;
size_t extbuf_size;
- DWORD i, j, k;
+ DWORD i;
grub_uint64_t sec_per_lcn;
grub_uint64_t curvcn = 0;
STARTING_VCN_INPUT_BUFFER start_vcn;
CloseHandle (filehd);
for (i = 0; i < extbuf->ExtentCount; i++)
- {
- for (j = 0; j < extbuf->Extents[i].NextVcn.QuadPart - curvcn; j++)
- for (k = 0; k < sec_per_lcn; k++)
- callback ((extbuf->Extents[i].Lcn.QuadPart + j)
- * sec_per_lcn + first_lcn
- + k, 0, 512, hook_data);
- }
+ callback (extbuf->Extents[i].Lcn.QuadPart
+ * sec_per_lcn + first_lcn,
+ 0, 512 * sec_per_lcn * (extbuf->Extents[i].NextVcn.QuadPart - curvcn), hook_data);
free (extbuf);
}
/* Logarithm of sector size. */
unsigned int log_sector_size;
+ /* Maximum number of sectors read divided by GRUB_DISK_CACHE_SIZE. */
+ unsigned int max_agglomerate;
+
/* The id used by the disk cache manager. */
unsigned long id;
#define GRUB_DISK_CACHE_BITS 6
#define GRUB_DISK_CACHE_SIZE (1 << GRUB_DISK_CACHE_BITS)
+#define GRUB_DISK_MAX_MAX_AGGLOMERATE ((1 << (30 - GRUB_DISK_CACHE_BITS - GRUB_DISK_SECTOR_BITS)) - 1)
+
/* Return value of grub_disk_get_size() in case disk size is unknown. */
#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL
{
struct blocklists *bl = data;
struct grub_boot_blocklist *prev = bl->block + 1;
+ grub_uint64_t seclen;
grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
sector, offset, length);
if (bl->first_sector == (grub_disk_addr_t) -1)
{
- if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
+ if (offset != 0 || length < GRUB_DISK_SECTOR_SIZE)
grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
bl->first_sector = sector;
- return;
+ sector++;
+ length -= GRUB_DISK_SECTOR_SIZE;
+ if (!length)
+ return;
}
- if (offset != 0 || bl->last_length != GRUB_DISK_SECTOR_SIZE)
+ if (offset != 0 || bl->last_length != 0)
grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
+ seclen = (length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS;
+
if (bl->block != bl->first_block
&& (grub_target_to_host64 (prev->start)
+ grub_target_to_host16 (prev->len)) == sector)
{
- grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
+ grub_uint16_t t = grub_target_to_host16 (prev->len);
+ t += seclen;
prev->len = grub_host_to_target16 (t);
}
else
{
bl->block->start = grub_host_to_target64 (sector);
- bl->block->len = grub_host_to_target16 (1);
+ bl->block->len = grub_host_to_target16 (seclen);
#ifdef GRUB_SETUP_BIOS
bl->block->segment = grub_host_to_target16 (bl->current_segment);
#endif
grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
}
- bl->last_length = length;
+ bl->last_length = length & (GRUB_DISK_SECTOR_SIZE - 1);
#ifdef GRUB_SETUP_BIOS
- bl->current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
+ bl->current_segment += seclen << (GRUB_DISK_SECTOR_BITS - 4);
#endif
}
bl.current_segment =
GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
#endif
- bl.last_length = GRUB_DISK_SECTOR_SIZE;
+ bl.last_length = 0;
/* Read the boot image by the OS service. */
boot_path = grub_util_get_path (dir, boot_file);
if ((char *) bl.block <= core_img)
grub_util_error ("%s", _("no terminator in the core image"));
}
+ if (len)
+ grub_util_error ("%s", _("blocklists are incomplete"));
core_dev->disk->partition = container;
free (buf);
}