Blob Blame History Raw
From aa7ca7c9f7266c432b5dad65302ae7cfa7a1c050 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 19 Nov 2010 11:25:00 -0500
Subject: [PATCH] Make most SECTOR_SIZE checks use functions.

Most uses of SECTOR_SIZE or SECTOR_BITS are changed to get_sector_size()
or get_sector_bits(), respectively.
---
 efi/efidisk.c             |   62 ++++++++++++++++++++++++++++++++++++++++----
 efi/ia32/loader/linux.c   |    9 ++++++-
 efi/x86_64/loader/linux.c |    9 ++++++-
 grub/asmstub.c            |   25 +++++++++++++-----
 lib/device.c              |    3 ++
 stage2/boot.c             |   11 ++++---
 stage2/builtins.c         |   20 ++++++++++----
 stage2/disk_io.c          |   50 ++++++++++++++++++++++-------------
 stage2/fsys_ext2fs.c      |    5 ++-
 stage2/fsys_fat.c         |   20 +++++++++-----
 stage2/fsys_jfs.c         |   12 +++++---
 stage2/fsys_reiserfs.c    |   24 +++++++++--------
 stage2/fsys_xfs.c         |    2 +-
 stage2/gpt.h              |    9 +++---
 stage2/shared.h           |   12 ++++++---
 15 files changed, 194 insertions(+), 79 deletions(-)

diff --git a/efi/efidisk.c b/efi/efidisk.c
index 145ed16..edd830e 100644
--- a/efi/efidisk.c
+++ b/efi/efidisk.c
@@ -44,6 +44,10 @@ static struct grub_efidisk_data *fd_devices;
 static struct grub_efidisk_data *hd_devices;
 static struct grub_efidisk_data *cd_devices;
 
+static int get_device_sector_bits(struct grub_efidisk_data *device);
+static int get_device_sector_size(struct grub_efidisk_data *device);
+static struct grub_efidisk_data *get_device_from_drive (int drive);
+
 static struct grub_efidisk_data *
 make_devices (void)
 {
@@ -190,7 +194,9 @@ name_devices (struct grub_efidisk_data *devices)
       m = d->block_io->media;
       if (GRUB_EFI_DEVICE_PATH_TYPE(dp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE)
 	{
-	  if (m->read_only && m->block_size > SECTOR_SIZE)
+	  /* XXX FIXME this won't work if we see write-protected disks with
+	   * 4k sectors */
+	  if (m->read_only && m->block_size > 0x200)
 	    {
 	      add_device (&cd_devices, d);
 	    } else
@@ -253,11 +259,15 @@ grub_efidisk_read (struct grub_efidisk_data *d, grub_disk_addr_t sector,
   grub_efi_disk_io_t *dio;
   grub_efi_block_io_t *bio;
   grub_efi_status_t status;
-  grub_efi_uint64_t sector_size;
+  grub_efi_uint64_t sector_size = get_device_sector_size(d);
 
   dio = d->disk_io;
   bio = d->block_io;
-  sector_size = d->block_io->media->block_size;
+
+#if 0
+  grub_printf("read(%d, %d) -> read(%d, %d)\n", sector, size,
+  	sector * sector_size, size * sector_size);
+#endif
 
   status = Call_Service_5 (dio->read ,
 			   dio, bio->media->media_id,
@@ -278,11 +288,10 @@ grub_efidisk_write (struct grub_efidisk_data *d, grub_disk_addr_t sector,
   grub_efi_disk_io_t *dio;
   grub_efi_block_io_t *bio;
   grub_efi_status_t status;
-  grub_efi_uint64_t sector_size;
+  grub_efi_uint64_t sector_size = get_device_sector_size(d);
 
   dio = d->disk_io;
   bio = d->block_io;
-  sector_size = d->block_io->media->block_size;
 
   grub_dprintf ("efidisk",
 		"writing 0x%x sectors at the sector 0x%x to ??\n",
@@ -313,6 +322,47 @@ grub_efidisk_fini (void)
   free_devices (cd_devices);
 }
 
+static int
+get_device_sector_size(struct grub_efidisk_data *device)
+{
+	return device->block_io->media->block_size;
+}
+
+int
+get_sector_size(int drive)
+{
+	struct grub_efidisk_data *device = get_device_from_drive(drive);
+	return get_device_sector_size(device);
+}
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+static __inline__ unsigned int
+ffz (unsigned int word)
+{
+  __asm__ ("bsfl %1,%0"
+:	   "=r" (word)
+:	   "r" (~word));
+  return word;
+}
+#define log2(n) ffz(~(n))
+
+static int
+get_device_sector_bits(struct grub_efidisk_data *device)
+{
+	int sector_size = get_device_sector_size(device);
+	return log2(sector_size);
+}
+
+int
+get_sector_bits(int drive)
+{
+	int sector_size = get_sector_size(drive);
+	return log2(sector_size);
+}
+
 static struct grub_efidisk_data *
 get_device_from_drive (int drive)
 {
@@ -456,7 +506,6 @@ grub_get_drive_partition_from_bdev_handle (grub_efi_handle_t handle,
   unsigned long partition_start, partition_len, part_offset, part_extoffset;
   unsigned long gpt_offset;
   int gpt_count, gpt_size;
-  char buf[SECTOR_SIZE];
   auto int find_bdev (struct grub_efidisk_data *c);
 
   int find_bdev (struct grub_efidisk_data *c)
@@ -541,6 +590,7 @@ grub_get_drive_partition_from_bdev_handle (grub_efi_handle_t handle,
   if (! found)
     return 0;
 
+  char buf[get_sector_size(drv)];
   part = 0xFFFFFF;
   while (next_partition (drv, 0, &part, &part_type,
 			 &partition_start, &partition_len,
diff --git a/efi/ia32/loader/linux.c b/efi/ia32/loader/linux.c
index eb6b5de..eaaeb38 100644
--- a/efi/ia32/loader/linux.c
+++ b/efi/ia32/loader/linux.c
@@ -37,6 +37,13 @@
 
 #define PTR_HI(x) ((grub_uint32_t) ((unsigned long long)((unsigned long)(x)) >> 32))
 
+#ifndef SECTOR_SIZE
+#define SECTOR_SIZE 0x200
+#endif /* defined(SECTOR_SIZE) */
+#ifndef SECTOR_BITS
+#define SECTOR_BITS 9
+#endif /* defined(SECTOR_BITS) */
+
 static unsigned long linux_mem_size;
 static int loaded;
 static void *real_mode_mem;
@@ -499,7 +506,7 @@ grub_load_linux (char *kernel, char *arg)
 
   dest = grub_stpcpy ((char *) real_mode_mem + 0x1000, skip_to(0, arg));
 
-  grub_seek ((setup_sects << SECTOR_BITS) + SECTOR_SIZE);
+  grub_seek ((setup_sects << get_sector_bits(current_drive)) + get_sector_size(current_drive));
   len = prot_size;
   if (grub_read ((char *) GRUB_LINUX_BZIMAGE_ADDR, len) != len)
     grub_printf ("Couldn't read file");
diff --git a/efi/x86_64/loader/linux.c b/efi/x86_64/loader/linux.c
index 18746ea..93a0377 100644
--- a/efi/x86_64/loader/linux.c
+++ b/efi/x86_64/loader/linux.c
@@ -37,6 +37,13 @@
 
 #define PTR_HI(x) ((grub_uint32_t) ((unsigned long long)((unsigned long)(x)) >> 32))
 
+#ifndef SECTOR_SIZE
+#define SECTOR_SIZE 0x200
+#endif /* defined(SECTOR_SIZE) */
+#ifndef SECTOR_BITS
+#define SECTOR_BITS 9
+#endif /* defined(SECTOR_BITS) */
+
 static unsigned long linux_mem_size;
 static int loaded;
 static void *real_mode_mem;
@@ -447,7 +454,7 @@ grub_load_linux (char *kernel, char *arg)
 
   dest = grub_stpcpy ((char *) real_mode_mem + 0x1000, skip_to(0, arg));
 
-  grub_seek ((setup_sects << SECTOR_BITS) + SECTOR_SIZE);
+  grub_seek ((setup_sects << get_sector_bits(current_drive)) + get_sector_size(current_drive));
   len = prot_size;
   if (grub_read ((char *)prot_mode_mem, len) != len)
     grub_printf ("Couldn't read file");
diff --git a/grub/asmstub.c b/grub/asmstub.c
index f420074..818be75 100644
--- a/grub/asmstub.c
+++ b/grub/asmstub.c
@@ -107,6 +107,17 @@ static char *serial_device = 0;
 static unsigned int serial_speed;
 #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
 
+#ifdef GRUB_UTIL
+int get_sector_size (int drive)
+{
+  return 0x200;
+}
+int get_sector_bits (int drive)
+{
+  return 9;
+}
+#endif /* GRUB_UTIL */
+
 /* This allocates page-aligned storage of the specified size, which must be
  * a multiple of the page size as determined by calling sysconf(_SC_PAGESIZE)
  */
@@ -1063,13 +1074,13 @@ biosdisk (int subfunc, int drive, struct geometry *geometry,
     _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
 	       loff_t *, res, uint, wh);
 
-    offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
+    offset = (loff_t) sector * (loff_t) get_sector_size(drive);
     if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
       return -1;
   }
 #else
   {
-    off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
+    off_t offset = (off_t) sector * (off_t) get_sector_size(drive);
 
     if (lseek (fd, offset, SEEK_SET) != offset)
       return -1;
@@ -1088,13 +1099,13 @@ biosdisk (int subfunc, int drive, struct geometry *geometry,
 	     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, SECTOR_SIZE) != SECTOR_SIZE)
+	  if (nread (fd, buf, get_sector_size(drive)) != get_sector_size(drive))
 	    return -1;
-	  buf += SECTOR_SIZE;
+	  buf += get_sector_size(drive);
 	  nsec--;
 	}
 #endif
-      if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
+      if (nread (fd, buf, nsec * get_sector_size(drive)) != nsec * get_sector_size(drive))
 	return -1;
       break;
 
@@ -1104,10 +1115,10 @@ biosdisk (int subfunc, int drive, struct geometry *geometry,
 	  grub_printf ("Write %d sectors starting from %d sector"
 		       " to drive 0x%x (%s)\n",
 		       nsec, sector, drive, device_map[drive]);
-	  hex_dump (buf, nsec * SECTOR_SIZE);
+	  hex_dump (buf, nsec * get_sector_size(drive));
 	}
       if (! read_only)
-	if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
+	if (nwrite (fd, buf, nsec * get_sector_size(drive)) != nsec * get_sector_size(drive))
 	  return -1;
       break;
 
diff --git a/lib/device.c b/lib/device.c
index 45a300e..45e4001 100644
--- a/lib/device.c
+++ b/lib/device.c
@@ -36,6 +36,9 @@
 #include <limits.h>
 #include <stdarg.h>
 
+#define SECTOR_SIZE 0x200
+#define SECTOR_BITS 9
+
 #ifdef __linux__
 # if !defined(__GLIBC__) || \
         ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
diff --git a/stage2/boot.c b/stage2/boot.c
index 247b8c9..e30daf8 100644
--- a/stage2/boot.c
+++ b/stage2/boot.c
@@ -281,7 +281,7 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
 	setup_sects = LINUX_DEFAULT_SETUP_SECTS;
 
       data_len = setup_sects << 9;
-      text_len = filemax - data_len - SECTOR_SIZE;
+      text_len = filemax - data_len - get_sector_size(current_drive);
 
       linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
       
@@ -395,14 +395,15 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
       
 	  /* It is possible that DATA_LEN + SECTOR_SIZE is greater than
 	     MULTIBOOT_SEARCH, so the data may have been read partially.  */
-	  if (data_len + SECTOR_SIZE <= MULTIBOOT_SEARCH)
+	  if (data_len + get_sector_size(current_drive) <= MULTIBOOT_SEARCH)
 	    grub_memmove (linux_data_tmp_addr, buffer,
-			  data_len + SECTOR_SIZE);
+			  data_len + get_sector_size(current_drive));
 	  else
 	    {
 	      grub_memmove (linux_data_tmp_addr, buffer, MULTIBOOT_SEARCH);
 	      grub_read (linux_data_tmp_addr + MULTIBOOT_SEARCH,
-			 data_len + SECTOR_SIZE - MULTIBOOT_SEARCH);
+			 data_len + get_sector_size(current_drive)
+			 - MULTIBOOT_SEARCH);
 	    }
 	  
 	  if (lh->header != LINUX_MAGIC_SIGNATURE ||
@@ -461,7 +462,7 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
 	  }
       
 	  /* offset into file */
-	  grub_seek (data_len + SECTOR_SIZE);
+	  grub_seek (data_len + get_sector_size(current_drive));
       
 	  cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
 	  grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
diff --git a/stage2/builtins.c b/stage2/builtins.c
index c90c527..178c889 100644
--- a/stage2/builtins.c
+++ b/stage2/builtins.c
@@ -195,11 +195,12 @@ blocklist_read_helper (int sector, int offset, int length)
   int *num_sectors = &blocklist_func_context.num_sectors;
   int *num_entries = &blocklist_func_context.num_entries;
   int *last_length = &blocklist_func_context.last_length;
+  int sector_size = get_sector_size(current_drive);
 
   if (*num_sectors > 0)
   {
     if (*start_sector + *num_sectors == sector
-      && offset == 0 && *last_length == SECTOR_SIZE)
+      && offset == 0 && *last_length == sector_size)
     {
       *num_sectors++;
       *last_length = length;
@@ -207,7 +208,7 @@ blocklist_read_helper (int sector, int offset, int length)
     }
     else
     {
-      if (*last_length == SECTOR_SIZE)
+      if (*last_length == sector_size)
         grub_printf ("%s%d+%d", *num_entries ? "," : "",
           *start_sector - part_start, *num_sectors);
       else if (*num_sectors > 1)
@@ -1512,7 +1513,8 @@ find_func (char *arg, int flags)
       unsigned long part = 0xFFFFFF;
       unsigned long start, len, offset, ext_offset, gpt_offset;
       int type, entry, gpt_count, gpt_size;
-      char buf[SECTOR_SIZE];
+      int sector_size = get_sector_size(drive);
+      char buf[sector_size];
 
       current_drive = drive;
       while (next_partition (drive, 0xFFFFFF, &part, &type,
@@ -3012,7 +3014,6 @@ partnew_func (char *arg, int flags)
   int start_cl, start_ch, start_dh;
   int end_cl, end_ch, end_dh;
   int entry;
-  char mbr[512];
 
   /* Convert a LBA address to a CHS address in the INT 13 format.  */
   auto void lba_to_chs (int lba, int *cl, int *ch, int *dh);
@@ -3043,6 +3044,9 @@ partnew_func (char *arg, int flags)
       return 1;
     }
 
+  int sector_size = get_sector_size(current_drive);
+  char mbr[sector_size];
+
   /* The partition must a primary partition.  */
   if ((current_partition >> 16) > 3
       || (current_partition & 0xFFFF) != 0xFFFF)
@@ -3076,7 +3080,7 @@ partnew_func (char *arg, int flags)
     return 1;
 
   /* Read the MBR.  */
-  if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr))
+  if (! rawread (current_drive, 0, 0, sector_size, mbr))
     return 1;
 
   /* Check if the new partition will fit in the disk.  */
@@ -3131,7 +3135,6 @@ parttype_func (char *arg, int flags)
   unsigned long part = 0xFFFFFF;
   unsigned long start, len, offset, ext_offset, gpt_offset;
   int entry, type, gpt_count, gpt_size;
-  char mbr[512];
 
   /* Get the drive and the partition.  */
   if (! set_device (arg))
@@ -3143,6 +3146,9 @@ parttype_func (char *arg, int flags)
       errnum = ERR_BAD_ARGUMENT;
       return 1;
     }
+
+  int sector_size = get_sector_size(current_drive);
+  char mbr[sector_size];
   
   /* The partition must be a PC slice.  */
   if ((current_partition >> 16) == 0xFF
@@ -3597,6 +3603,7 @@ savedefault_helper(int new_default)
 #endif
 
 #if !defined(SUPPORT_DISKLESS) && defined(GRUB_UTIL)
+#define SECTOR_SIZE 0x200
 /*
  * Full implementation of new `savedefault' for GRUB shell.
  * XXX This needs fixing for stage2 files which aren't accessible
@@ -3694,6 +3701,7 @@ savedefault_shell(char *arg, int flags)
   fclose (fp);
   return 0;
 }
+#undef SECTOR_SIZE
 #endif
 
 /* savedefault */
diff --git a/stage2/disk_io.c b/stage2/disk_io.c
index d54864f..308b291 100644
--- a/stage2/disk_io.c
+++ b/stage2/disk_io.c
@@ -305,7 +305,7 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
    *  Check partition boundaries
    */
   if (sector < 0
-      || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS))
+      || ((sector + ((byte_offset + byte_len - 1) >> get_sector_bits(current_drive)))
 	  >= part_length))
     {
       errnum = ERR_OUTSIDE_PART;
@@ -315,8 +315,8 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
   /*
    *  Get the read to the beginning of a partition.
    */
-  sector += byte_offset >> SECTOR_BITS;
-  byte_offset &= SECTOR_SIZE - 1;
+  sector += byte_offset >> get_sector_bits(current_drive);
+  byte_offset &= get_sector_size(current_drive) - 1;
 
 #if !defined(STAGE1_5)
   if (disk_read_hook && debug)
@@ -355,7 +355,7 @@ rawwrite (int drive, int sector, char *buf)
 	sector = 1;
     }
   
-  memmove ((char *) SCRATCHADDR, buf, SECTOR_SIZE);
+  memmove ((char *) SCRATCHADDR, buf, get_sector_size(drive));
   if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom,
 		sector, 1, SCRATCHSEG))
     {
@@ -392,7 +392,7 @@ devwrite (int sector, int sector_count, char *buf)
       for (i = 0; i < sector_count; i++)
 	{
 	  if (! rawwrite (current_drive, part_start + sector + i, 
-			  buf + (i << SECTOR_BITS)))
+			  buf + (i << get_sector_bits(current_drive))))
 	      return 0;
 
 	}
@@ -466,7 +466,7 @@ make_saved_active (void)
 	}
 
       /* Read the MBR in the scratch space.  */
-      if (! rawread (saved_drive, 0, 0, SECTOR_SIZE, mbr))
+      if (! rawread (saved_drive, 0, 0, get_sector_size(saved_drive), mbr))
 	return 0;
 
       /* If the partition is an extended partition, setting the active
@@ -619,7 +619,7 @@ next_partition (unsigned long drive, unsigned long dest,
 
 	  /* Read the BSD label.  */
 	  if (! rawread (drive, *start + BSD_LABEL_SECTOR,
-			 0, SECTOR_SIZE, buf))
+			 0, get_sector_size(drive), buf))
 	    return 0;
 
 	  /* Check if it is valid.  */
@@ -674,7 +674,7 @@ next_partition (unsigned long drive, unsigned long dest,
 	}
 
       /* Read the MBR or the boot sector of the extended partition.  */
-      if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
+      if (! rawread (drive, *offset, 0, get_sector_size(drive), buf))
 	return 0;
 
       /* Check if it is valid.  */
@@ -690,7 +690,7 @@ next_partition (unsigned long drive, unsigned long dest,
          struct grub_gpt_header *hdr = (struct grub_gpt_header *) buf;
 
          /* Read in the GPT Partition table header.  */
-         if (! rawread (drive, 1, 0, SECTOR_SIZE, buf))
+         if (! rawread (drive, 1, 0, get_sector_size(drive), buf))
            return 0;
 
          if (hdr->magic == GPT_HEADER_MAGIC && hdr->version == 0x10000)
@@ -710,7 +710,7 @@ next_partition (unsigned long drive, unsigned long dest,
              /* This is not a valid header for a GPT partition table.
                 Re-read the MBR or the boot sector of the extended
                 partition.  */
-             if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
+             if (! rawread (drive, *offset, 0, get_sector_size(drive), buf))
                return 0;
            }
        }
@@ -785,7 +785,7 @@ next_partition (unsigned long drive, unsigned long dest,
            return 0;
          }
        /* Read in the GPT Partition table entry.  */
-       if (! rawread (drive, (*gpt_offset) + GPT_ENTRY_SECTOR (*gpt_size, *entry), GPT_ENTRY_INDEX (*gpt_size, *entry), *gpt_size, buf))
+       if (! rawread (drive, (*gpt_offset) + GPT_ENTRY_SECTOR (drive, *gpt_size, *entry), GPT_ENTRY_INDEX (drive, *gpt_size, *entry), *gpt_size, buf))
          return 0;
       } while (! (gptentry->type1 && gptentry->type2));
 
@@ -851,7 +851,7 @@ real_open_partition (int flags)
   int gpt_count;
   int gpt_size;
   int entry;
-  char buf[SECTOR_SIZE];
+  char buf[4096];
   int bsd_part, pc_slice;
 
   /* For simplicity.  */
@@ -1022,6 +1022,17 @@ open_partition (void)
   return real_open_partition (0);
 }
 
+#if !defined(PLATFORM_EFI) && !defined(GRUB_UTIL)
+int get_sector_size (int drive)
+{
+  return SECTOR_SIZE;
+}
+int get_sector_bits (int drive)
+{
+  return SECTOR_BITS;
+}
+#endif /* !defined(PLATFORM_EFI) && !defined(GRUB_UTIL) */
+
 
 #ifndef STAGE1_5
 /* XX used for device completion in 'set_device' and 'print_completions' */
@@ -1227,7 +1238,7 @@ set_bootdev (int hdbias)
   if ((saved_drive & 0x80) && cur_part_addr)
     {
       if (rawread (saved_drive, cur_part_offset,
-		   0, SECTOR_SIZE, (char *) SCRATCHADDR))
+		   0, get_sector_size(saved_drive), (char *) SCRATCHADDR))
 	{
 	  char *dst, *src;
       
@@ -1692,7 +1703,7 @@ grub_open (char *filename)
 
 	  BLK_BLKLENGTH (list_addr) = tmp;
 
-	  filemax += (tmp * SECTOR_SIZE);
+	  filemax += (tmp * get_sector_size(current_drive));
 	  list_addr += BLK_BLKLIST_INC_VAL;
 
 	  if (*ptr != ',')
@@ -1769,6 +1780,7 @@ grub_read (char *buf, int len)
   if (block_file)
     {
       int size, off, ret = 0;
+      int sector_size = get_sector_size(current_drive);
 
       while (len && !errnum)
 	{
@@ -1783,10 +1795,10 @@ grub_read (char *buf, int len)
 	  /* run BLK_CUR_FILEPOS up to filepos */
 	  while (filepos > BLK_CUR_FILEPOS)
 	    {
-	      if ((filepos - (BLK_CUR_FILEPOS & ~(SECTOR_SIZE - 1)))
-		  >= SECTOR_SIZE)
+	      if ((filepos - (BLK_CUR_FILEPOS & ~(sector_size - 1)))
+		  >= sector_size)
 		{
-		  BLK_CUR_FILEPOS += SECTOR_SIZE;
+		  BLK_CUR_FILEPOS += sector_size;
 		  BLK_CUR_BLKNUM++;
 
 		  if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST))
@@ -1799,9 +1811,9 @@ grub_read (char *buf, int len)
 		BLK_CUR_FILEPOS = filepos;
 	    }
 
-	  off = filepos & (SECTOR_SIZE - 1);
+	  off = filepos & (sector_size - 1);
 	  size = ((BLK_BLKLENGTH (BLK_CUR_BLKLIST) - BLK_CUR_BLKNUM)
-		  * SECTOR_SIZE) - off;
+		  * sector_size) - off;
 	  if (size > len)
 	    size = len;
 
diff --git a/stage2/fsys_ext2fs.c b/stage2/fsys_ext2fs.c
index 810ac5f..01386d1 100644
--- a/stage2/fsys_ext2fs.c
+++ b/stage2/fsys_ext2fs.c
@@ -25,7 +25,7 @@
 static int mapblock1, mapblock2;
 
 /* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
-#define DEV_BSIZE 512
+#define DEV_BSIZE get_sector_size(current_drive)
 
 /* include/linux/fs.h */
 #define BLOCK_SIZE 1024		/* initial block size for superblock read */
@@ -33,6 +33,7 @@ static int mapblock1, mapblock2;
 #define WHICH_SUPER 1
 /* kind of from fs/ext2/super.c */
 #define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)	/* = 2 */
+#define SBOFF ((WHICH_SUPER * BLOCK_SIZE) % DEV_BSIZE)
 
 /* include/asm-i386/types.h */
 typedef __signed__ char __s8;
@@ -413,7 +414,7 @@ ext2fs_mount (void)
        && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
        && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))
       || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE))
-      || !devread (SBLOCK, 0, sizeof (struct ext2_super_block),
+      || !devread (SBLOCK, SBOFF, sizeof (struct ext2_super_block),
 		   (char *) SUPERBLOCK)
       || SUPERBLOCK->s_magic != EXT2_SUPER_MAGIC)
       retval = 0;
diff --git a/stage2/fsys_fat.c b/stage2/fsys_fat.c
index 266ec03..7e82266 100644
--- a/stage2/fsys_fat.c
+++ b/stage2/fsys_fat.c
@@ -49,10 +49,10 @@ struct fat_superblock
 /* pointer(s) into filesystem info buffer for DOS stuff */
 #define FAT_SUPER ( (struct fat_superblock *) \
  		    ( FSYS_BUF + 32256) )/* 512 bytes long */
-#define FAT_BUF   ( FSYS_BUF + 30208 )	/* 4 sector FAT buffer */
-#define NAME_BUF  ( FSYS_BUF + 29184 )	/* Filename buffer (833 bytes) */
+#define FAT_BUF   ( FSYS_BUF + 28160 )	/* 4 sector FAT buffer */
+#define NAME_BUF  ( FSYS_BUF + 27136 )	/* Filename buffer (833 bytes) */
 
-#define FAT_CACHE_SIZE 2048
+#define FAT_CACHE_SIZE 4096
 
 static __inline__ unsigned int
 grub_log2 (unsigned int word)
@@ -68,6 +68,7 @@ fat_mount (void)
 {
   struct fat_bpb bpb;
   __u32 magic, first_fat;
+  int sector_size;
   
   /* Check partition type for harddisk */
   if (((current_drive & 0x80) || (current_slice != 0))
@@ -81,6 +82,8 @@ fat_mount (void)
   if (! devread (0, 0, sizeof (bpb), (char *) &bpb))
     return 0;
 
+  sector_size = get_sector_size(current_drive);
+
   /* Check if the number of sectors per cluster is zero here, to avoid
      zero division.  */
   if (bpb.sects_per_clust == 0)
@@ -155,11 +158,11 @@ fat_mount (void)
   /* Now do some sanity checks */
   
   if (FAT_CVT_U16(bpb.bytes_per_sect) != (1 << FAT_SUPER->sectsize_bits)
-      || FAT_CVT_U16(bpb.bytes_per_sect) != SECTOR_SIZE
+      || FAT_CVT_U16(bpb.bytes_per_sect) != sector_size
       || bpb.sects_per_clust != (1 << (FAT_SUPER->clustsize_bits
  				       - FAT_SUPER->sectsize_bits))
       || FAT_SUPER->num_clust <= 2
-      || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE)
+      || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * sector_size)
  	  > FAT_SUPER->fat_length))
     return 0;
   
@@ -203,6 +206,7 @@ fat_read (char *buf, int len)
   int offset;
   int ret = 0;
   int size;
+  int sector_size = get_sector_size(current_drive);
   
   if (FAT_SUPER->file_cluster < 0)
     {
@@ -238,10 +242,10 @@ fat_read (char *buf, int len)
 	  if (cached_pos < 0 || 
 	      (cached_pos + FAT_SUPER->fat_size) > 2*FAT_CACHE_SIZE)
 	    {
-	      FAT_SUPER->cached_fat = (fat_entry & ~(2*SECTOR_SIZE - 1));
+	      FAT_SUPER->cached_fat = (fat_entry & ~(2*sector_size - 1));
 	      cached_pos = (fat_entry - FAT_SUPER->cached_fat);
 	      sector = FAT_SUPER->fat_offset
-		+ FAT_SUPER->cached_fat / (2*SECTOR_SIZE);
+		+ FAT_SUPER->cached_fat / (2*sector_size);
 	      if (!devread (sector, 0, FAT_CACHE_SIZE, (char*) FAT_BUF))
 		return 0;
 	    }
@@ -259,6 +263,8 @@ fat_read (char *buf, int len)
 	    return ret;
 	  if (next_cluster < 2 || next_cluster >= FAT_SUPER->num_clust)
 	    {
+	      grub_printf("next_cluster: %d FAT_SUPER->num_clust: %d\n",
+	      	next_cluster, FAT_SUPER->num_clust);
 	      errnum = ERR_FSYS_CORRUPT;
 	      return 0;
 	    }
diff --git a/stage2/fsys_jfs.c b/stage2/fsys_jfs.c
index 307f836..d63b1de 100644
--- a/stage2/fsys_jfs.c
+++ b/stage2/fsys_jfs.c
@@ -207,19 +207,20 @@ int
 jfs_mount (void)
 {
 	struct jfs_superblock super;
+	int sector_bits = get_sector_bits(current_drive);
 
-	if (part_length < MINJFS >> SECTOR_BITS
-	    || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
+	if (part_length < MINJFS >> sector_bits
+	    || !devread (SUPER1_OFF >> sector_bits, 0,
 			 sizeof(struct jfs_superblock), (char *)&super)
 	    || (super.s_magic != JFS_MAGIC)
-	    || !devread ((AITBL_OFF >> SECTOR_BITS) + FILESYSTEM_I,
+	    || !devread ((AITBL_OFF >> sector_bits) + FILESYSTEM_I,
 			 0, DISIZE, (char*)fileset)) {
 		return 0;
 	}
 
 	jfs.bsize = super.s_bsize;
 	jfs.l2bsize = super.s_l2bsize;
-	jfs.bdlog = jfs.l2bsize - SECTOR_BITS;
+	jfs.bdlog = jfs.l2bsize - sector_bits;
 
 	return 1;
 }
@@ -387,9 +388,10 @@ int
 jfs_embed (int *start_sector, int needed_sectors)
 {
 	struct jfs_superblock super;
+	int sector_bits = get_sector_bits(current_drive);
 
 	if (needed_sectors > 63
-	    || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
+	    || !devread (SUPER1_OFF >> sector_bits, 0,
 			 sizeof (struct jfs_superblock),
 			 (char *)&super)
 	    || (super.s_magic != JFS_MAGIC)) {
diff --git a/stage2/fsys_reiserfs.c b/stage2/fsys_reiserfs.c
index 441cb3f..aebd716 100644
--- a/stage2/fsys_reiserfs.c
+++ b/stage2/fsys_reiserfs.c
@@ -292,7 +292,6 @@ struct reiserfs_de_head
 
 /* The size of the node cache */
 #define FSYSREISER_CACHE_SIZE 24*1024
-#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
 #define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
 
 /* Info about currently opened file */
@@ -569,9 +568,11 @@ int
 reiserfs_mount (void)
 {
   struct reiserfs_super_block super;
-  int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
+  int sector_bits = get_sector_bits(current_drive);
+  int sector_size = get_sector_size(current_drive);
+  int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> sector_bits;
 
-  if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
+  if (part_length < superblock + (sizeof (super) >> sector_bits)
       || ! devread (superblock, 0, sizeof (struct reiserfs_super_block), 
 		(char *) &super)
       || (substring (REISER3FS_SUPER_MAGIC_STRING, super.s_magic) > 0
@@ -582,8 +583,8 @@ reiserfs_mount (void)
 	  <= REISERFS_DISK_OFFSET_IN_BYTES))
     {
       /* Try old super block position */
-      superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
-      if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
+      superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> sector_bits;
+      if (part_length < superblock + (sizeof (super) >> sector_bits)
 	  || ! devread (superblock, 0, sizeof (struct reiserfs_super_block), 
 			(char *) &super))
 	return 0;
@@ -610,7 +611,7 @@ reiserfs_mount (void)
   INFO->version = super.s_version;
   INFO->blocksize = super.s_blocksize;
   INFO->fullblocksize_shift = grub_log2 (super.s_blocksize);
-  INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
+  INFO->blocksize_shift = INFO->fullblocksize_shift - sector_bits;
   INFO->cached_slots = 
     (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
 
@@ -622,9 +623,9 @@ reiserfs_mount (void)
   /* Clear node cache. */
   memset (INFO->blocks, 0, sizeof (INFO->blocks));
 
-  if (super.s_blocksize < FSYSREISER_MIN_BLOCKSIZE
+  if (super.s_blocksize < get_sector_size(current_drive)
       || super.s_blocksize > FSYSREISER_MAX_BLOCKSIZE
-      || (SECTOR_SIZE << INFO->blocksize_shift) != super.s_blocksize)
+      || (sector_size << INFO->blocksize_shift) != super.s_blocksize)
     return 0;
 
   /* Initialize journal code.  If something fails we end with zero
@@ -1215,9 +1216,10 @@ int
 reiserfs_embed (int *start_sector, int needed_sectors)
 {
   struct reiserfs_super_block super;
+  int sector_bits = get_sector_bits(current_drive);
   int num_sectors;
   
-  if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0, 
+  if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> sector_bits, 0, 
 		 sizeof (struct reiserfs_super_block), (char *) &super))
     return 0;
   
@@ -1229,9 +1231,9 @@ reiserfs_embed (int *start_sector, int needed_sectors)
 	   * the journal log */
 	  super.s_journal_block * super.s_blocksize 
 	  > REISERFS_DISK_OFFSET_IN_BYTES))
-    num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
+    num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> sector_bits) - 1;
   else
-    num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
+    num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> sector_bits) - 1;
   
   return (needed_sectors <= num_sectors);
 }
diff --git a/stage2/fsys_xfs.c b/stage2/fsys_xfs.c
index d5214d3..226e343 100644
--- a/stage2/fsys_xfs.c
+++ b/stage2/fsys_xfs.c
@@ -469,7 +469,7 @@ xfs_mount (void)
 
 	xfs.bsize = le32 (super.sb_blocksize);
 	xfs.blklog = super.sb_blocklog;
-	xfs.bdlog = xfs.blklog - SECTOR_BITS;
+	xfs.bdlog = xfs.blklog - get_sector_bits(current_drive);
 	xfs.rootino = le64 (super.sb_rootino);
 	xfs.isize = le16 (super.sb_inodesize);
 	xfs.agblocks = le32 (super.sb_agblocks);
diff --git a/stage2/gpt.h b/stage2/gpt.h
index 71ed0b8..ad6d8f1 100644
--- a/stage2/gpt.h
+++ b/stage2/gpt.h
@@ -60,9 +60,10 @@ struct grub_gpt_partentry
 
 #define GPT_HEADER_MAGIC       0x5452415020494645ULL
 
-#define        GPT_ENTRY_SECTOR(size,entry)                                    \
-       ((((entry) * (size) + 1) & ~(SECTOR_SIZE - 1)) >> SECTOR_BITS)
-#define        GPT_ENTRY_INDEX(size,entry)                                     \
-       ((((entry) * (size) + 1) & (SECTOR_SIZE - 1)) - 1)
+#define        GPT_ENTRY_SECTOR(drive,size,entry)                      \
+       ((((entry) * (size) + 1) & ~(get_sector_size(drive) - 1))       \
+       >> get_sector_bits(drive))
+#define        GPT_ENTRY_INDEX(drive, size,entry)                      \
+       ((((entry) * (size) + 1) & (get_sector_size(drive) - 1)) - 1)
 
 #endif /* _GPT_H */
diff --git a/stage2/shared.h b/stage2/shared.h
index 9405556..7a77744 100644
--- a/stage2/shared.h
+++ b/stage2/shared.h
@@ -57,15 +57,15 @@ extern void *grub_scratch_mem;
 #define NEW_HEAPSIZE 1500
 
 /* 512-byte scratch area */
-#define SCRATCHADDR  RAW_ADDR (0x77e00)
-#define SCRATCHSEG   RAW_SEG (0x77e0)
+#define SCRATCHADDR  RAW_ADDR (0x77000)
+#define SCRATCHSEG   RAW_SEG (0x7700)
 
 /*
- *  This is the location of the raw device buffer.  It is 31.5K
+ *  This is the location of the raw device buffer.  It is 28K
  *  in size.
  */
 
-#define BUFFERLEN   0x7e00
+#define BUFFERLEN   0x7000
 #define BUFFERADDR  RAW_ADDR (0x70000)
 #define BUFFERSEG   RAW_SEG (0x7000)
 
@@ -169,8 +169,10 @@ extern void *grub_scratch_mem;
  *  General disk stuff
  */
 
+#ifndef PLATFORM_EFI
 #define SECTOR_SIZE		0x200
 #define SECTOR_BITS		9
+#endif /* PLATFORM_EFI */
 #define BIOS_FLAG_FIXED_DISK	0x80
 
 #define BOOTSEC_LOCATION		RAW_ADDR (0x7C00)
@@ -840,6 +842,8 @@ int get_diskinfo (int drive, struct geometry *geometry);
 int biosdisk (int subfunc, int drive, struct geometry *geometry,
 	      int sector, int nsec, int segment);
 void stop_floppy (void);
+int get_sector_size (int drive);
+int get_sector_bits (int drive);
 
 /* Command-line interface functions. */
 #ifndef STAGE1_5
-- 
1.7.2.2