[syslinux] [PATCH] disklib: small fixes / addons

Michal Soltys soltys at ziu.info
Thu Aug 19 06:07:05 PDT 2010


Functions disk_write_sector() and disk_write_verify_sector()
take 64bit lba as an argument now - similary to disk_read_sectors().

Structure disk_info additionally provides cylinders, besides head and sector.
Sanity checks during lba -> chs conversions have been adjusted to use
cylinders.

CX in cbios read/write code was not calculated properly.

Minor signed/unsigned changes.

Signed-off-by: Michal Soltys <soltys at ziu.info>
---
 com32/include/syslinux/disk.h |   11 ++++++-----
 com32/lib/syslinux/disk.c     |   22 ++++++++++++----------
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/com32/include/syslinux/disk.h b/com32/include/syslinux/disk.h
index ff80532..4e8de4f 100644
--- a/com32/include/syslinux/disk.h
+++ b/com32/include/syslinux/disk.h
@@ -39,14 +39,15 @@
 #include <com32.h>
 #include <stdint.h>
 
-#define SECTOR 512		/* bytes/sector */
+#define SECTOR 512u		/* bytes/sector */
 
 struct disk_info {
     int disk;
     int ebios;			/* EBIOS supported on this disk */
     int cbios;			/* CHS geometry is valid */
-    int head;
-    int sect;
+    unsigned int head;
+    unsigned int sect;
+    unsigned int cyl;
 };
 
 struct disk_ebios_dapa {
@@ -144,9 +145,9 @@ extern int disk_get_params(int disk, struct disk_info *const diskinfo);
 extern void *disk_read_sectors(const struct disk_info *const diskinfo,
 			       uint64_t lba, uint8_t count);
 extern int disk_write_sector(const struct disk_info *const diskinfo,
-			     unsigned int lba, const void *data);
+			     uint64_t lba, const void *data);
 extern int disk_write_verify_sector(const struct disk_info *const diskinfo,
-				    unsigned int lba, const void *buf);
+				    uint64_t lba, const void *buf);
 extern void disk_dos_part_dump(const struct disk_dos_part_entry *const part);
 extern void guid_to_str(char *buf, const struct guid *const id);
 extern int str_to_guid(const char *buf, struct guid *const id);
diff --git a/com32/lib/syslinux/disk.c b/com32/lib/syslinux/disk.c
index 678e4bd..1efd1ec 100644
--- a/com32/lib/syslinux/disk.c
+++ b/com32/lib/syslinux/disk.c
@@ -103,6 +103,8 @@ int disk_get_params(int disk, struct disk_info *const diskinfo)
 
     diskinfo->head = parm.edx.b[1] + 1;
     diskinfo->sect = parm.ecx.b[0] & 0x3f;
+    diskinfo->cyl  = (parm.ecx.b[1] |
+		     ((parm.ecx.b[0] & 0xc0u) << 2)) + 1;
     if (diskinfo->sect == 0) {
 	diskinfo->sect = 1;
     } else {
@@ -161,19 +163,19 @@ void *disk_read_sectors(const struct disk_info *const diskinfo, uint64_t lba,
 	    h = 0;
 	    c = 0;
 	} else {
+	    if (lba + count > diskinfo->cyl * diskinfo->head * diskinfo->sect)
+		/* beyond acceptable geometry */
+		return NULL;
 	    s = (lba % diskinfo->sect) + 1;
 	    t = lba / diskinfo->sect;	/* Track = head*cyl */
 	    h = t % diskinfo->head;
 	    c = t / diskinfo->head;
 	}
 
-	if (s > 63 || h > 256 || c > 1023)
-	    return NULL;
-
 	inreg.eax.b[0] = count;
 	inreg.eax.b[1] = 0x02;	/* Read */
 	inreg.ecx.b[1] = c & 0xff;
-	inreg.ecx.b[0] = s + (c >> 6);
+	inreg.ecx.b[0] = ((c >> 2) & 0xc0u) | s;
 	inreg.edx.b[1] = h;
 	inreg.edx.b[0] = diskinfo->disk;
 	inreg.ebx.w[0] = OFFS(buf);
@@ -200,7 +202,7 @@ void *disk_read_sectors(const struct disk_info *const diskinfo, uint64_t lba,
  * Uses the disk number and information from diskinfo.
  * Write a sector to a disk drive, starting at lba.
  */
-int disk_write_sector(const struct disk_info *const diskinfo, unsigned int lba,
+int disk_write_sector(const struct disk_info *const diskinfo, uint64_t lba,
 		      const void *data)
 {
     com32sys_t inreg;
@@ -234,18 +236,18 @@ int disk_write_sector(const struct disk_info *const diskinfo, unsigned int lba,
 	    h = 0;
 	    c = 0;
 	} else {
+	    if (lba >= diskinfo->cyl * diskinfo->head * diskinfo->sect)
+		/* beyond acceptable geometry */
+		return -1;
 	    s = (lba % diskinfo->sect) + 1;
 	    t = lba / diskinfo->sect;	/* Track = head*cyl */
 	    h = t % diskinfo->head;
 	    c = t / diskinfo->head;
 	}
 
-	if (s > 63 || h > 256 || c > 1023)
-	    return -1;
-
 	inreg.eax.w[0] = 0x0301;	/* Write one sector */
 	inreg.ecx.b[1] = c & 0xff;
-	inreg.ecx.b[0] = s + (c >> 6);
+	inreg.ecx.b[0] = ((c >> 2) & 0xc0u) | s;
 	inreg.edx.b[1] = h;
 	inreg.edx.b[0] = diskinfo->disk;
 	inreg.ebx.w[0] = OFFS(buf);
@@ -271,7 +273,7 @@ int disk_write_sector(const struct disk_info *const diskinfo, unsigned int lba,
  * to verify it was written correctly.
  */
 int disk_write_verify_sector(const struct disk_info *const diskinfo,
-			     unsigned int lba, const void *buf)
+			     uint64_t lba, const void *buf)
 {
     char *rb;
     int rv;
-- 
1.7.2.1




More information about the Syslinux mailing list