]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Initial variable sector size support
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 29 Mar 2011 00:02:55 +0000 (02:02 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 29 Mar 2011 00:02:55 +0000 (02:02 +0200)
grub-core/disk/efi/efidisk.c
grub-core/disk/i386/pc/biosdisk.c
grub-core/disk/scsi.c
grub-core/kern/disk.c
grub-core/kern/emu/hostdisk.c
grub-core/partmap/msdos.c
include/grub/disk.h

index 08094fa5c9ec06f59e92cbffd2691ee6a3cb62e5..20fea956f9aae07b25038c708081e50efb63d6fd 100644 (file)
@@ -536,8 +536,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->blocksize & (m->blocksize - 1) || !m->blocksize)
+    return grub_error (GRUB_ERR_IO, "invalid sector size %d",
+                      m->blocksize);
+  for (disk->log_sector_size = 0;
+       (1 << disk->log_sector_size) < m->blocksize;
+       disk->log_sector_size++);
   disk->data = d;
 
   grub_dprintf ("efidisk", "opening %s succeeded\n", name);
@@ -571,8 +576,8 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
                (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,
+                     (grub_efi_uint64_t) sector << disk->log_sector_size,
+                     (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");
@@ -599,8 +604,8 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
                (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,
+                      (grub_efi_uint64_t) sector << disk->log_sector_size,
+                      (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");
index 069bb0b595bce99297d270c0490fadff48ea0bab..6e48fff43c191dc3e0a1c661dbd7ac59ea9d9620 100644 (file)
@@ -338,7 +338,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;
     }
@@ -347,6 +348,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)
        {
@@ -367,6 +370,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++);
+               }
            }
        }
     }
@@ -429,7 +441,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;
@@ -443,9 +455,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;
@@ -501,10 +510,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);
@@ -512,8 +523,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;
 }
@@ -522,21 +533,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;
@@ -545,9 +546,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;
     }
@@ -568,18 +570,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;
     }
index a40de278f899aff4a9979cf50b582be472a76f03..0d4734dc0dbf0c9bb55ad15ed6dc0246d00b75a8 100644 (file)
@@ -463,15 +463,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;
@@ -501,25 +506,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)
     {
index 807ee4277b1048b4901f5b6fb76d9f46230ad9c4..af56527adbcc492ca55e1f719872b8fdfff6d8f7 100644 (file)
@@ -247,6 +247,7 @@ grub_disk_open (const char *name)
   disk = (grub_disk_t) grub_zalloc (sizeof (*disk));
   if (! disk)
     return 0;
+  disk->log_sector_size = GRUB_DISK_SECTOR_BITS;
 
   p = find_part_sep (name);
   if (p)
@@ -266,7 +267,6 @@ grub_disk_open (const char *name)
   if (! disk->name)
     goto fail;
 
-
   for (dev = grub_disk_dev_list; dev; dev = dev->next)
     {
       if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
@@ -282,6 +282,14 @@ grub_disk_open (const char *name)
       grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk");
       goto fail;
     }
+  if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS
+      || disk->log_sector_size < GRUB_DISK_SECTOR_BITS)
+    {
+      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                 "sector sizes of %d bytes aren't supported yet",
+                 (1 << disk->log_sector_size));
+      goto fail;
+    }
 
   disk->dev = dev;
 
@@ -373,14 +381,23 @@ grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
       *sector += start;
     }
 
-  if (disk->total_sectors <= *sector
-      || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
-         >> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector)
+  if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN
+      && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector
+         || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
+         >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors
+                                      << (disk->log_sector_size
+                                          - GRUB_DISK_SECTOR_BITS)) - *sector))
     return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
 
   return GRUB_ERR_NONE;
 }
 
+static inline grub_disk_addr_t
+transform_sector (grub_disk_t disk, grub_disk_addr_t sector)
+{
+  return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
+}
+
 /* Read data from the disk.  */
 grub_err_t
 grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
@@ -433,27 +450,39 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
       else
        {
          /* Otherwise read data from the disk actually.  */
-         if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors
-             || (disk->dev->read) (disk, start_sector,
-                                   GRUB_DISK_CACHE_SIZE, tmp_buf)
+         if ((disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN
+              && start_sector + GRUB_DISK_CACHE_SIZE
+              > (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
+             || (disk->dev->read) (disk, transform_sector (disk, start_sector),
+                                   1 << (GRUB_DISK_CACHE_BITS
+                                         + GRUB_DISK_SECTOR_BITS
+                                         - disk->log_sector_size), tmp_buf)
              != GRUB_ERR_NONE)
            {
              /* Uggh... Failed. Instead, just read necessary data.  */
              unsigned num;
              char *p;
+             grub_disk_addr_t aligned_sector;
 
              grub_errno = GRUB_ERR_NONE;
 
-             num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1)
-                    >> GRUB_DISK_SECTOR_BITS);
+             aligned_sector = (sector & ~((1 << (disk->log_sector_size
+                                                 - GRUB_DISK_SECTOR_BITS))
+                                          - 1));
+             real_offset += ((sector - aligned_sector)
+                             << GRUB_DISK_SECTOR_BITS);
+             num = ((size + real_offset + (1 << (disk->log_sector_size))
+                     - 1) >> (disk->log_sector_size));
 
-             p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS);
+             p = grub_realloc (tmp_buf, num << disk->log_sector_size);
              if (!p)
                goto finish;
 
              tmp_buf = p;
 
-             if ((disk->dev->read) (disk, sector, num, tmp_buf))
+             if ((disk->dev->read) (disk, transform_sector (disk,
+                                                            aligned_sector),
+                                    num, tmp_buf))
                {
                  grub_error_push ();
                  grub_dprintf ("disk", "%s read failed\n", disk->name);
@@ -528,25 +557,31 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
                 grub_off_t offset, grub_size_t size, const void *buf)
 {
   unsigned real_offset;
+  grub_disk_addr_t aligned_sector;
 
   grub_dprintf ("disk", "Writing `%s'...\n", disk->name);
 
   if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
     return -1;
 
-  real_offset = offset;
+  aligned_sector = (sector & ~((1 << (disk->log_sector_size
+                                     - GRUB_DISK_SECTOR_BITS)) - 1));
+  real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
+  sector = aligned_sector;
 
   while (size)
     {
-      if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0))
+      if (real_offset != 0 || (size < (1U << disk->log_sector_size)
+                              && size != 0))
        {
-         char tmp_buf[GRUB_DISK_SECTOR_SIZE];
+         char tmp_buf[1 << disk->log_sector_size];
          grub_size_t len;
          grub_partition_t part;
 
          part = disk->partition;
          disk->partition = 0;
-         if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf)
+         if (grub_disk_read (disk, sector,
+                             0, (1 << disk->log_sector_size), tmp_buf)
              != GRUB_ERR_NONE)
            {
              disk->partition = part;
@@ -554,7 +589,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
            }
          disk->partition = part;
 
-         len = GRUB_DISK_SECTOR_SIZE - real_offset;
+         len = (1 << disk->log_sector_size) - real_offset;
          if (len > size)
            len = size;
 
@@ -565,7 +600,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
          if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE)
            goto finish;
 
-         sector++;
+         sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
          buf = (char *) buf + len;
          size -= len;
          real_offset = 0;
@@ -575,8 +610,8 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
          grub_size_t len;
          grub_size_t n;
 
-         len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
-         n = size >> GRUB_DISK_SECTOR_BITS;
+         len = size & ~((1 << disk->log_sector_size) - 1);
+         n = size >> disk->log_sector_size;
 
          if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE)
            goto finish;
@@ -599,6 +634,8 @@ grub_disk_get_size (grub_disk_t disk)
 {
   if (disk->partition)
     return grub_partition_get_len (disk->partition);
+  else if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN)
+    return disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
   else
-    return disk->total_sectors;
+    return GRUB_DISK_SIZE_UNKNOWN;
 }
index 73d023ce9148cddf9020f04c85d24386edcef988..f082ada8982687281724582d6839a9c6cae0a511 100644 (file)
@@ -42,6 +42,7 @@
 
 #ifdef __linux__
 # include <sys/ioctl.h>         /* ioctl */
+# include <sys/mount.h>
 # if !defined(__GLIBC__) || \
         ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
 /* Maybe libc doesn't have large file support.  */
@@ -264,6 +265,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
 # else
     unsigned long long nr;
 # endif
+    int sector_size;
     int fd;
 
     fd = open (map[drive].device, O_RDONLY);
@@ -295,16 +297,28 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
        goto fail;
       }
 
+    if (ioctl (fd, BLKSSZGET, &sector_size))
+       {
+         close (fd);
+        goto fail;
+       }
+
     close (fd);
 
+    if (sector_size & (sector_size - 1) || !sector_size)
+      goto fail;
+    for (disk->log_sector_size = 0;
+        (1 << disk->log_sector_size) < sector_size;
+        disk->log_sector_size++);
+
 # if defined (__APPLE__)
     disk->total_sectors = nr;
 # elif defined(__NetBSD__)
     disk->total_sectors = label.d_secperunit;
 # else
-    disk->total_sectors = nr / 512;
+    disk->total_sectors = nr >> disk->log_sector_size;
 
-    if (nr % 512)
+    if (nr & ((1 << disk->log_sector_size) - 1))
       grub_util_error ("unaligned device size");
 # endif
 
@@ -321,7 +335,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
   if (stat (map[drive].device, &st) < 0)
     return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
 
-  disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
+  disk->total_sectors = st.st_size >> disk->log_sector_size;
 
   grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
 
@@ -760,7 +774,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
     _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
                loff_t *, res, uint, wh);
 
-    offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
+    offset = (loff_t) sector << disk->log_sector_size;
     if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
       {
        grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
@@ -770,7 +784,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
   }
 #else
   {
-    off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
+    off_t offset = (off_t) sector << disk->log_sector_size;
 
     if (lseek (fd, offset, SEEK_SET) != offset)
       {
@@ -870,20 +884,21 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
         sectors that are read together with the MBR in one read.  It
         should only remap the MBR, so we split the read in two
         parts. -jochen  */
-      if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
+      if (nread (fd, buf, (1 << disk->log_sector_size))
+         != (1 << disk->log_sector_size))
        {
          grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
          close (fd);
          return grub_errno;
        }
 
-      buf += GRUB_DISK_SECTOR_SIZE;
+      buf += (1 << disk->log_sector_size);
       size--;
     }
 #endif /* __linux__ */
 
-  if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
-      != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+  if (nread (fd, buf, size << disk->log_sector_size)
+      != (ssize_t) (size << disk->log_sector_size))
     grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
 
   return grub_errno;
@@ -916,8 +931,8 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
   if (fd < 0)
     return grub_errno;
 
-  if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
-      != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+  if (nwrite (fd, buf, size << disk->log_sector_size)
+      != (ssize_t) (size << disk->log_sector_size))
     grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
 
   return grub_errno;
index 31a0a0707642a4d4c2fd82b39a4ddc1d7a2f9ff2..c2e726bd7906756659563653e3e4555c637e25d2 100644 (file)
@@ -90,8 +90,11 @@ grub_partition_msdos_iterate (grub_disk_t disk,
        {
          e = mbr.entries + p.index;
 
-         p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
-         p.len = grub_le_to_cpu32 (e->length);
+         p.start = p.offset
+           + (grub_le_to_cpu32 (e->start)
+              << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) - delta;
+         p.len = grub_le_to_cpu32 (e->length)
+           << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
          p.msdostype = e->type;
 
          grub_dprintf ("partition",
@@ -126,7 +129,9 @@ grub_partition_msdos_iterate (grub_disk_t disk,
 
          if (grub_msdos_partition_is_extended (e->type))
            {
-             p.offset = ext_offset + grub_le_to_cpu32 (e->start);
+             p.offset = ext_offset
+               + (grub_le_to_cpu32 (e->start)
+                  << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
              if (! ext_offset)
                ext_offset = p.offset;
 
@@ -204,8 +209,11 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
          e = mbr.entries + i;
 
          if (!grub_msdos_partition_is_empty (e->type)
-             && end > offset + grub_le_to_cpu32 (e->start))
-           end = offset + grub_le_to_cpu32 (e->start);
+             && end > offset
+             + (grub_le_to_cpu32 (e->start)
+                << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
+           end = offset + (grub_le_to_cpu32 (e->start)
+                           << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
 
          /* If this is a GPT partition, this MBR is just a dummy.  */
          if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0)
@@ -219,7 +227,9 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
 
          if (grub_msdos_partition_is_extended (e->type))
            {
-             offset = ext_offset + grub_le_to_cpu32 (e->start);
+             offset = ext_offset 
+               + (grub_le_to_cpu32 (e->start) 
+                  << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
              if (! ext_offset)
                ext_offset = offset;
 
index 66db1149a4394810d29ebce9c35cbfb5169a2341..b46d6670a6b9cb7b505cc6f110661a273e149f02 100644 (file)
@@ -100,6 +100,9 @@ struct grub_disk
   /* The total number of sectors.  */
   grub_uint64_t total_sectors;
 
+  /* Logarithm of sector size.  */
+  unsigned int log_sector_size;
+
   /* The id used by the disk cache manager.  */
   unsigned long id;
 
@@ -132,9 +135,10 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
 /* The maximum number of disk caches.  */
 #define GRUB_DISK_CACHE_NUM    1021
 
-/* The size of a disk cache in sector units.  */
-#define GRUB_DISK_CACHE_SIZE   8
-#define GRUB_DISK_CACHE_BITS   3
+/* The size of a disk cache in 512B units. Must be at least as big as the
+   largest supported sector size, currently 16K.  */
+#define GRUB_DISK_CACHE_BITS   6
+#define GRUB_DISK_CACHE_SIZE   (1 << GRUB_DISK_CACHE_BITS)
 
 /* Return value of grub_disk_get_size() in case disk size is unknown. */
 #define GRUB_DISK_SIZE_UNKNOWN  0xffffffffffffffffULL