aboutsummaryrefslogtreecommitdiffstats
path: root/com32
diff options
context:
space:
mode:
authorRaphael S.Carvalho <raphael.scarv@gmail.com>2013-09-17 16:45:34 -0300
committerMatt Fleming <matt.fleming@intel.com>2013-09-30 14:24:14 +0100
commit09f4ac33d598156c65f88a329a576af7e53dfb85 (patch)
tree4c3ef95ee6a09ef89b3bba2020b63b437a8116e2 /com32
parent47179ebc03dcb3177312d97cd912605704c40686 (diff)
downloadsyslinux-09f4ac33d598156c65f88a329a576af7e53dfb85.tar.gz
syslinux-09f4ac33d598156c65f88a329a576af7e53dfb85.tar.xz
syslinux-09f4ac33d598156c65f88a329a576af7e53dfb85.zip
com32/disk: Code cleanup at disk_write_sectors and disk_read_sectors.
Pulled common code out of these functions into new ones. The functions chs_setup and ebios_setup were created for this purpose. Signed-off-by: Raphael S.Carvalho <raphael.scarv@gmail.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'com32')
-rw-r--r--com32/include/syslinux/disk.h7
-rw-r--r--com32/lib/syslinux/disk.c173
2 files changed, 97 insertions, 83 deletions
diff --git a/com32/include/syslinux/disk.h b/com32/include/syslinux/disk.h
index f96ca686..b8361fe4 100644
--- a/com32/include/syslinux/disk.h
+++ b/com32/include/syslinux/disk.h
@@ -41,6 +41,13 @@
#define SECTOR 512u /* bytes/sector */
+enum disk_op_codes {
+ EBIOS_READ_CODE = 0x42, /* Extended read */
+ EBIOS_WRITE_CODE = 0x43, /* Extended write */
+ CHS_READ_CODE = 0x02,
+ CHS_WRITE_CODE = 0x03,
+};
+
struct disk_info {
int disk;
int ebios; /* EBIOS supported on this disk */
diff --git a/com32/lib/syslinux/disk.c b/com32/lib/syslinux/disk.c
index 093751ac..0b0c737e 100644
--- a/com32/lib/syslinux/disk.c
+++ b/com32/lib/syslinux/disk.c
@@ -33,6 +33,7 @@
* Deal with disks and partitions
*/
+#include <core.h>
#include <dprintf.h>
#include <stdio.h>
#include <stdlib.h>
@@ -158,6 +159,83 @@ out:
}
/**
+ * Fill inreg based on EBIOS addressing properties.
+ *
+ * @v diskinfo The disk drive to read from
+ * @v inreg Register data structure to be filled.
+ * @v lba The logical block address to begin reading at
+ * @v count The number of sectors to read
+ * @v op_code Code to write/read operation
+ * @ret lmalloc'd buf upon success, NULL upon failure
+ */
+static void *ebios_setup(const struct disk_info *const diskinfo, com32sys_t *inreg,
+ uint64_t lba, uint8_t count, uint8_t op_code)
+{
+ static __lowmem struct disk_ebios_dapa dapa;
+ void *buf;
+
+ buf = lmalloc(count * diskinfo->bps);
+ if (!buf)
+ return NULL;
+
+ dapa.len = sizeof(dapa);
+ dapa.count = count;
+ dapa.off = OFFS(buf);
+ dapa.seg = SEG(buf);
+ dapa.lba = lba;
+
+ inreg->eax.b[1] = op_code;
+ inreg->esi.w[0] = OFFS(&dapa);
+ inreg->ds = SEG(&dapa);
+ inreg->edx.b[0] = diskinfo->disk;
+
+ return buf;
+}
+
+/**
+ * Fill inreg based on CHS addressing properties.
+ *
+ * @v diskinfo The disk drive to read from
+ * @v inreg Register data structure to be filled.
+ * @v lba The logical block address to begin reading at
+ * @v count The number of sectors to read
+ * @v op_code Code to write/read operation
+ * @ret lmalloc'd buf upon success, NULL upon failure
+ */
+static void *chs_setup(const struct disk_info *const diskinfo, com32sys_t *inreg,
+ uint64_t lba, uint8_t count, uint8_t op_code)
+{
+ unsigned int c, h, s, t;
+ void *buf;
+
+ buf = lmalloc(count * diskinfo->bps);
+ if (!buf)
+ return NULL;
+
+ /*
+ * if we passed lba + count check and we get here, that means that
+ * lbacnt was calculated from chs geometry (or faked from 1/1/1), thus
+ * 32bits are perfectly enough and lbacnt corresponds to cylinder
+ * boundary
+ */
+ s = lba % diskinfo->spt;
+ t = lba / diskinfo->spt;
+ h = t % diskinfo->head;
+ c = t / diskinfo->head;
+
+ inreg->eax.b[0] = count;
+ inreg->eax.b[1] = op_code;
+ inreg->ecx.b[1] = c;
+ inreg->ecx.b[0] = ((c & 0x300) >> 2) | (s+1);
+ inreg->edx.b[1] = h;
+ inreg->edx.b[0] = diskinfo->disk;
+ inreg->ebx.w[0] = OFFS(buf);
+ inreg->es = SEG(buf);
+
+ return buf;
+}
+
+/**
* Get disk block(s) and return a malloc'd buffer.
*
* @v diskinfo The disk drive to read from
@@ -172,7 +250,6 @@ void *disk_read_sectors(const struct disk_info *const diskinfo, uint64_t lba,
uint8_t count)
{
com32sys_t inreg;
- struct disk_ebios_dapa *dapa;
void *buf;
void *data = NULL;
uint32_t maxcnt;
@@ -184,48 +261,14 @@ void *disk_read_sectors(const struct disk_info *const diskinfo, uint64_t lba,
memset(&inreg, 0, sizeof inreg);
- buf = lmalloc(count * diskinfo->bps);
+ if (diskinfo->ebios)
+ buf = ebios_setup(diskinfo, &inreg, lba, count, EBIOS_READ_CODE);
+ else
+ buf = chs_setup(diskinfo, &inreg, lba, count, CHS_READ_CODE);
+
if (!buf)
return NULL;
- dapa = lmalloc(sizeof(*dapa));
- if (!dapa)
- goto out;
-
- if (diskinfo->ebios) {
- dapa->len = sizeof(*dapa);
- dapa->count = count;
- dapa->off = OFFS(buf);
- dapa->seg = SEG(buf);
- dapa->lba = lba;
-
- inreg.esi.w[0] = OFFS(dapa);
- inreg.ds = SEG(dapa);
- inreg.edx.b[0] = diskinfo->disk;
- inreg.eax.b[1] = 0x42; /* Extended read */
- } else {
- unsigned int c, h, s, t;
- /*
- * if we passed lba + count check and we get here, that means that
- * lbacnt was calculated from chs geometry (or faked from 1/1/1), thus
- * 32bits are perfectly enough and lbacnt corresponds to cylinder
- * boundary
- */
- s = lba % diskinfo->spt;
- t = lba / diskinfo->spt;
- h = t % diskinfo->head;
- c = t / diskinfo->head;
-
- inreg.eax.b[0] = count;
- inreg.eax.b[1] = 0x02; /* Read */
- inreg.ecx.b[1] = c;
- inreg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1);
- inreg.edx.b[1] = h;
- inreg.edx.b[0] = diskinfo->disk;
- inreg.ebx.w[0] = OFFS(buf);
- inreg.es = SEG(buf);
- }
-
if (disk_int13_retry(&inreg, NULL))
goto out;
@@ -233,7 +276,6 @@ void *disk_read_sectors(const struct disk_info *const diskinfo, uint64_t lba,
if (data)
memcpy(data, buf, count * diskinfo->bps);
out:
- lfree(dapa);
lfree(buf);
return data;
}
@@ -254,7 +296,6 @@ int disk_write_sectors(const struct disk_info *const diskinfo, uint64_t lba,
const void *data, uint8_t count)
{
com32sys_t inreg;
- struct disk_ebios_dapa *dapa;
void *buf;
uint32_t maxcnt;
uint32_t size = 65536;
@@ -264,57 +305,23 @@ int disk_write_sectors(const struct disk_info *const diskinfo, uint64_t lba,
if (!count || count > maxcnt || lba + count > diskinfo->lbacnt)
return -1;
- buf = lmalloc(count * diskinfo->bps);
+ memset(&inreg, 0, sizeof inreg);
+
+ if (diskinfo->ebios)
+ buf = ebios_setup(diskinfo, &inreg, lba, count, EBIOS_WRITE_CODE);
+ else
+ buf = chs_setup(diskinfo, &inreg, lba, count, CHS_WRITE_CODE);
+
if (!buf)
return -1;
memcpy(buf, data, count * diskinfo->bps);
- memset(&inreg, 0, sizeof inreg);
-
- dapa = lmalloc(sizeof(*dapa));
- if (!dapa)
- goto out;
-
- if (diskinfo->ebios) {
- dapa->len = sizeof(*dapa);
- dapa->count = count;
- dapa->off = OFFS(buf);
- dapa->seg = SEG(buf);
- dapa->lba = lba;
-
- inreg.esi.w[0] = OFFS(dapa);
- inreg.ds = SEG(dapa);
- inreg.edx.b[0] = diskinfo->disk;
- inreg.eax.b[1] = 0x43; /* Extended write */
- } else {
- unsigned int c, h, s, t;
- /*
- * if we passed lba + count check and we get here, that means that
- * lbacnt was calculated from chs geometry (or faked from 1/1/1), thus
- * 32bits are perfectly enough and lbacnt corresponds to cylinder
- * boundary
- */
- s = lba % diskinfo->spt;
- t = lba / diskinfo->spt;
- h = t % diskinfo->head;
- c = t / diskinfo->head;
-
- inreg.eax.b[0] = count;
- inreg.eax.b[1] = 0x03; /* Write */
- inreg.ecx.b[1] = c;
- inreg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1);
- inreg.edx.b[1] = h;
- inreg.edx.b[0] = diskinfo->disk;
- inreg.ebx.w[0] = OFFS(buf);
- inreg.es = SEG(buf);
- }
if (disk_int13_retry(&inreg, NULL))
goto out;
rv = 0; /* ok */
out:
- lfree(dapa);
lfree(buf);
return rv;
}