aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--com32/include/syslinux/disk.h157
-rw-r--r--com32/lib/Makefile4
-rw-r--r--com32/lib/syslinux/disk.c507
-rw-r--r--com32/modules/chain.c630
4 files changed, 738 insertions, 560 deletions
diff --git a/com32/include/syslinux/disk.h b/com32/include/syslinux/disk.h
new file mode 100644
index 00000000..ff805325
--- /dev/null
+++ b/com32/include/syslinux/disk.h
@@ -0,0 +1,157 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright (C) 2010 Shao Miller
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file syslinux/disk.h
+ *
+ * Deal with disks and partitions
+ */
+
+#ifndef _SYSLINUX_DISK_H
+#define _SYSLINUX_DISK_H
+
+#include <com32.h>
+#include <stdint.h>
+
+#define SECTOR 512 /* bytes/sector */
+
+struct disk_info {
+ int disk;
+ int ebios; /* EBIOS supported on this disk */
+ int cbios; /* CHS geometry is valid */
+ int head;
+ int sect;
+};
+
+struct disk_ebios_dapa {
+ uint16_t len;
+ uint16_t count;
+ uint16_t off;
+ uint16_t seg;
+ uint64_t lba;
+};
+
+/**
+ * CHS (cylinder, head, sector) value extraction macros.
+ * Taken from WinVBlock. None expand to an lvalue.
+*/
+#define chs_head(chs) chs[0]
+#define chs_sector(chs) (chs[1] & 0x3F)
+#define chs_cyl_high(chs) (((uint16_t)(chs[1] & 0xC0)) << 2)
+#define chs_cyl_low(chs) ((uint16_t)chs[2])
+#define chs_cylinder(chs) (chs_cyl_high(chs) | chs_cyl_low(chs))
+typedef uint8_t disk_chs[3];
+
+/* A DOS partition table entry */
+struct disk_dos_part_entry {
+ uint8_t active_flag; /* 0x80 if "active" */
+ disk_chs start;
+ uint8_t ostype;
+ disk_chs end;
+ uint32_t start_lba;
+ uint32_t length;
+} __attribute__ ((packed));
+
+/* A DOS MBR */
+struct disk_dos_mbr {
+ char code[440];
+ uint32_t disk_sig;
+ char pad[2];
+ struct disk_dos_part_entry table[4];
+ uint16_t sig;
+} __attribute__ ((packed));
+#define disk_mbr_sig_magic 0xAA55
+
+/**
+ * A GPT disk/partition GUID
+ *
+ * Be careful with endianness, you must adjust it yourself
+ * iff you are directly using the fourth data chunk.
+ * There might be a better header for this...
+ */
+struct guid {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint64_t data4;
+} __attribute__ ((packed));
+
+/* A GPT partition */
+struct disk_gpt_part_entry {
+ struct guid type;
+ struct guid uid;
+ uint64_t lba_first;
+ uint64_t lba_last;
+ uint64_t attribs;
+ char name[72];
+} __attribute__ ((packed));
+
+/* A GPT header */
+struct disk_gpt_header {
+ char sig[8];
+ union {
+ struct {
+ uint16_t minor;
+ uint16_t major;
+ } fields __attribute__ ((packed));
+ uint32_t uint32;
+ char raw[4];
+ } rev __attribute__ ((packed));
+ uint32_t hdr_size;
+ uint32_t chksum;
+ char reserved1[4];
+ uint64_t lba_cur;
+ uint64_t lba_alt;
+ uint64_t lba_first_usable;
+ uint64_t lba_last_usable;
+ struct guid disk_guid;
+ uint64_t lba_table;
+ uint32_t part_count;
+ uint32_t part_size;
+ uint32_t table_chksum;
+ char reserved2[1];
+} __attribute__ ((packed));
+static const char disk_gpt_sig_magic[] = "EFI PART";
+
+extern int disk_int13_retry(const com32sys_t * inreg, com32sys_t * outreg);
+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);
+extern int disk_write_verify_sector(const struct disk_info *const diskinfo,
+ unsigned int 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);
+extern void disk_gpt_part_dump(const struct disk_gpt_part_entry *const
+ gpt_part);
+extern void disk_gpt_header_dump(const struct disk_gpt_header *const gpt);
+
+#endif /* _SYSLINUX_DISK_H */
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 2035df22..ed4bb31e 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -119,7 +119,9 @@ LIBOBJS = \
syslinux/setadv.o \
\
syslinux/video/fontquery.o syslinux/video/forcetext.o \
- syslinux/video/reportmode.o
+ syslinux/video/reportmode.o \
+ \
+ syslinux/disk.o
# These are the objects which are also imported into the core
LIBCOREOBJS = \
diff --git a/com32/lib/syslinux/disk.c b/com32/lib/syslinux/disk.c
new file mode 100644
index 00000000..678e4bd2
--- /dev/null
+++ b/com32/lib/syslinux/disk.c
@@ -0,0 +1,507 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright (C) 2010 Shao Miller
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file disk.c
+ *
+ * Deal with disks and partitions
+ */
+
+#include <dprintf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslinux/disk.h>
+
+/**
+ * Call int 13h, but with retry on failure. Especially floppies need this.
+ *
+ * @v inreg CPU register settings upon INT call
+ * @v outreg CPU register settings returned by INT call
+ * @ret (int) 0 upon success, -1 upon failure
+ */
+int disk_int13_retry(const com32sys_t * inreg, com32sys_t * outreg)
+{
+ int retry = 6; /* Number of retries */
+ com32sys_t tmpregs;
+
+ if (!outreg)
+ outreg = &tmpregs;
+
+ while (retry--) {
+ __intcall(0x13, inreg, outreg);
+ if (!(outreg->eflags.l & EFLAGS_CF))
+ return 0; /* CF=0, OK */
+ }
+
+ return -1; /* Error */
+}
+
+/**
+ * Query disk parameters and EBIOS availability for a particular disk.
+ *
+ * @v disk The INT 0x13 disk drive number to process
+ * @v diskinfo The structure to save the queried params to
+ * @ret (int) 0 upon success, -1 upon failure
+ */
+int disk_get_params(int disk, struct disk_info *const diskinfo)
+{
+ static com32sys_t getparm, parm, getebios, ebios;
+
+ diskinfo->disk = disk;
+ diskinfo->ebios = diskinfo->cbios = 0;
+
+ /* Get EBIOS support */
+ getebios.eax.w[0] = 0x4100;
+ getebios.ebx.w[0] = 0x55aa;
+ getebios.edx.b[0] = disk;
+ getebios.eflags.b[0] = 0x3; /* CF set */
+
+ __intcall(0x13, &getebios, &ebios);
+
+ if (!(ebios.eflags.l & EFLAGS_CF) &&
+ ebios.ebx.w[0] == 0xaa55 && (ebios.ecx.b[0] & 1)) {
+ diskinfo->ebios = 1;
+ }
+
+ /* Get disk parameters -- really only useful for
+ hard disks, but if we have a partitioned floppy
+ it's actually our best chance... */
+ getparm.eax.b[1] = 0x08;
+ getparm.edx.b[0] = disk;
+
+ __intcall(0x13, &getparm, &parm);
+
+ if (parm.eflags.l & EFLAGS_CF)
+ return diskinfo->ebios ? 0 : -1;
+
+ diskinfo->head = parm.edx.b[1] + 1;
+ diskinfo->sect = parm.ecx.b[0] & 0x3f;
+ if (diskinfo->sect == 0) {
+ diskinfo->sect = 1;
+ } else {
+ diskinfo->cbios = 1; /* Valid geometry */
+ }
+
+ return 0;
+}
+
+/**
+ * Get disk block(s) and return a malloc'd buffer.
+ *
+ * @v diskinfo The disk drive to read from
+ * @v lba The logical block address to begin reading at
+ * @v count The number of sectors to read
+ * @ret data An allocated buffer with the read data
+ *
+ * Uses the disk number and information from diskinfo. Read count sectors
+ * from drive, starting at lba. Return a new buffer, or NULL upon failure.
+ */
+void *disk_read_sectors(const struct disk_info *const diskinfo, uint64_t lba,
+ uint8_t count)
+{
+ com32sys_t inreg;
+ struct disk_ebios_dapa *dapa = __com32.cs_bounce;
+ void *buf = (char *)__com32.cs_bounce + SECTOR;
+ void *data;
+
+ if (!count)
+ /* Silly */
+ return NULL;
+
+ memset(&inreg, 0, sizeof inreg);
+
+ 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 (!diskinfo->cbios) {
+ /* We failed to get the geometry */
+
+ if (lba)
+ return NULL; /* Can only read MBR */
+
+ s = 1;
+ h = 0;
+ c = 0;
+ } else {
+ 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.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))
+ return NULL;
+
+ data = malloc(count * SECTOR);
+ if (data)
+ memcpy(data, buf, count * SECTOR);
+ return data;
+}
+
+/**
+ * Write a disk block.
+ *
+ * @v diskinfo The disk drive to write to
+ * @v lba The logical block address to begin writing at
+ * @v data The data to write
+ * @ret (int) 0 upon success, -1 upon failure
+ *
+ * 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,
+ const void *data)
+{
+ com32sys_t inreg;
+ struct disk_ebios_dapa *dapa = __com32.cs_bounce;
+ void *buf = (char *)__com32.cs_bounce + SECTOR;
+
+ memcpy(buf, data, SECTOR);
+ memset(&inreg, 0, sizeof inreg);
+
+ if (diskinfo->ebios) {
+ dapa->len = sizeof(*dapa);
+ dapa->count = 1; /* 1 sector */
+ 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.w[0] = 0x4300; /* Extended write */
+ } else {
+ unsigned int c, h, s, t;
+
+ if (!diskinfo->cbios) {
+ /* We failed to get the geometry */
+
+ if (lba)
+ return -1; /* Can only write MBR */
+
+ s = 1;
+ h = 0;
+ c = 0;
+ } else {
+ 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.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))
+ return -1;
+
+ return 0; /* ok */
+}
+
+/**
+ * Write a disk block and verify it was written.
+ *
+ * @v diskinfo The disk drive to write to
+ * @v lba The logical block address to begin writing at
+ * @v buf The data to write
+ * @ret rv 0 upon success, -1 upon failure
+ *
+ * Uses the disk number and information from diskinfo.
+ * Writes a sector to a disk drive starting at lba, then reads it back
+ * to verify it was written correctly.
+ */
+int disk_write_verify_sector(const struct disk_info *const diskinfo,
+ unsigned int lba, const void *buf)
+{
+ char *rb;
+ int rv;
+
+ rv = disk_write_sector(diskinfo, lba, buf);
+ if (rv)
+ return rv; /* Write failure */
+ rb = disk_read_sectors(diskinfo, lba, 1);
+ if (!rb)
+ return -1; /* Readback failure */
+ rv = memcmp(buf, rb, SECTOR);
+ free(rb);
+ return rv ? -1 : 0;
+}
+
+/**
+ * Dump info about a DOS partition entry
+ *
+ * @v part The 16-byte partition entry to examine
+ */
+void disk_dos_part_dump(const struct disk_dos_part_entry *const part)
+{
+ (void)part;
+ dprintf("Partition status _____ : 0x%.2x\n"
+ "Partition CHS start\n"
+ " Cylinder ___________ : 0x%.4x (%u)\n"
+ " Head _______________ : 0x%.2x (%u)\n"
+ " Sector _____________ : 0x%.2x (%u)\n"
+ "Partition type _______ : 0x%.2x\n"
+ "Partition CHS end\n"
+ " Cylinder ___________ : 0x%.4x (%u)\n"
+ " Head _______________ : 0x%.2x (%u)\n"
+ " Sector _____________ : 0x%.2x (%u)\n"
+ "Partition LBA start __ : 0x%.8x (%u)\n"
+ "Partition LBA count __ : 0x%.8x (%u)\n"
+ "-------------------------------\n",
+ part->active_flag,
+ chs_cylinder(part->start),
+ chs_cylinder(part->start),
+ chs_head(part->start),
+ chs_head(part->start),
+ chs_sector(part->start),
+ chs_sector(part->start),
+ part->ostype,
+ chs_cylinder(part->end),
+ chs_cylinder(part->end),
+ chs_head(part->end),
+ chs_head(part->end),
+ chs_sector(part->end),
+ chs_sector(part->end),
+ part->start_lba, part->start_lba, part->length, part->length);
+}
+
+/* Trivial error message output */
+static inline void error(const char *msg)
+{
+ fputs(msg, stderr);
+}
+
+/**
+ * This walk-map effectively reverses the little-endian
+ * portions of a GPT disk/partition GUID for a string representation.
+ * There might be a better header for this...
+ */
+static const char guid_le_walk_map[] = {
+ 3, -1, -1, -1, 0,
+ 5, -1, 0,
+ 3, -1, 0,
+ 2, 1, 0,
+ 1, 1, 1, 1, 1, 1
+};
+
+/**
+ * Fill a buffer with a textual GUID representation.
+ *
+ * @v buf Points to a minimum array of 37 chars
+ * @v id The GUID to represent as text
+ *
+ * The buffer must be >= char[37] and will be populated
+ * with an ASCII NUL C string terminator.
+ * Example: 11111111-2222-3333-4444-444444444444
+ * Endian: LLLLLLLL-LLLL-LLLL-BBBB-BBBBBBBBBBBB
+ */
+void guid_to_str(char *buf, const struct guid *const id)
+{
+ unsigned int i = 0;
+ const char *walker = (const char *)id;
+
+ while (i < sizeof(guid_le_walk_map)) {
+ walker += guid_le_walk_map[i];
+ if (!guid_le_walk_map[i])
+ *buf = '-';
+ else {
+ *buf = ((*walker & 0xF0) >> 4) + '0';
+ if (*buf > '9')
+ *buf += 'A' - '9' - 1;
+ buf++;
+ *buf = (*walker & 0x0F) + '0';
+ if (*buf > '9')
+ *buf += 'A' - '9' - 1;
+ }
+ buf++;
+ i++;
+ }
+ *buf = 0;
+}
+
+/**
+ * Create a GUID structure from a textual GUID representation.
+ *
+ * @v buf Points to a GUID string to parse
+ * @v id Points to a GUID to be populated
+ * @ret (int) Returns 0 upon success, -1 upon failure
+ *
+ * The input buffer must be >= 32 hexadecimal chars and be
+ * terminated with an ASCII NUL. Returns non-zero on failure.
+ * Example: 11111111-2222-3333-4444-444444444444
+ * Endian: LLLLLLLL-LLLL-LLLL-BBBB-BBBBBBBBBBBB
+ */
+int str_to_guid(const char *buf, struct guid *const id)
+{
+ char guid_seq[sizeof(struct guid) * 2];
+ unsigned int i = 0;
+ char *walker = (char *)id;
+
+ while (*buf && i < sizeof(guid_seq)) {
+ switch (*buf) {
+ /* Skip these three characters */
+ case '{':
+ case '}':
+ case '-':
+ break;
+ default:
+ /* Copy something useful to the temp. sequence */
+ if ((*buf >= '0') && (*buf <= '9'))
+ guid_seq[i] = *buf - '0';
+ else if ((*buf >= 'A') && (*buf <= 'F'))
+ guid_seq[i] = *buf - 'A' + 10;
+ else if ((*buf >= 'a') && (*buf <= 'f'))
+ guid_seq[i] = *buf - 'a' + 10;
+ else {
+ /* Or not */
+ error("Illegal character in GUID!\n");
+ return -1;
+ }
+ i++;
+ }
+ buf++;
+ }
+ /* Check for insufficient valid characters */
+ if (i < sizeof(guid_seq)) {
+ error("Too few GUID characters!\n");
+ return -1;
+ }
+ buf = guid_seq;
+ i = 0;
+ while (i < sizeof(guid_le_walk_map)) {
+ if (!guid_le_walk_map[i])
+ i++;
+ walker += guid_le_walk_map[i];
+ *walker = *buf << 4;
+ buf++;
+ *walker |= *buf;
+ buf++;
+ i++;
+ }
+ return 0;
+}
+
+/**
+ * Display GPT partition details.
+ *
+ * @v gpt_part The GPT partition entry to display
+ */
+void disk_gpt_part_dump(const struct disk_gpt_part_entry *const gpt_part)
+{
+ unsigned int i;
+ char guid_text[37];
+
+ dprintf("----------------------------------\n"
+ "GPT part. LBA first __ : 0x%.16llx\n"
+ "GPT part. LBA last ___ : 0x%.16llx\n"
+ "GPT part. attribs ____ : 0x%.16llx\n"
+ "GPT part. name _______ : '",
+ gpt_part->lba_first, gpt_part->lba_last, gpt_part->attribs);
+ for (i = 0; i < sizeof(gpt_part->name); i++) {
+ if (gpt_part->name[i])
+ dprintf("%c", gpt_part->name[i]);
+ }
+ dprintf("'");
+ guid_to_str(guid_text, &gpt_part->type);
+ dprintf("GPT part. type GUID __ : {%s}\n", guid_text);
+ guid_to_str(guid_text, &gpt_part->uid);
+ dprintf("GPT part. unique ID __ : {%s}\n", guid_text);
+}
+
+/**
+ * Display GPT header details.
+ *
+ * @v gpt The GPT header to display
+ */
+void disk_gpt_header_dump(const struct disk_gpt_header *const gpt)
+{
+ char guid_text[37];
+
+ printf("GPT sig ______________ : '%8.8s'\n"
+ "GPT major revision ___ : 0x%.4x\n"
+ "GPT minor revision ___ : 0x%.4x\n"
+ "GPT header size ______ : 0x%.8x\n"
+ "GPT header checksum __ : 0x%.8x\n"
+ "GPT reserved _________ : '%4.4s'\n"
+ "GPT LBA current ______ : 0x%.16llx\n"
+ "GPT LBA alternative __ : 0x%.16llx\n"
+ "GPT LBA first usable _ : 0x%.16llx\n"
+ "GPT LBA last usable __ : 0x%.16llx\n"
+ "GPT LBA part. table __ : 0x%.16llx\n"
+ "GPT partition count __ : 0x%.8x\n"
+ "GPT partition size ___ : 0x%.8x\n"
+ "GPT part. table chksum : 0x%.8x\n",
+ gpt->sig,
+ gpt->rev.fields.major,
+ gpt->rev.fields.minor,
+ gpt->hdr_size,
+ gpt->chksum,
+ gpt->reserved1,
+ gpt->lba_cur,
+ gpt->lba_alt,
+ gpt->lba_first_usable,
+ gpt->lba_last_usable,
+ gpt->lba_table, gpt->part_count, gpt->part_size, gpt->table_chksum);
+ guid_to_str(guid_text, &gpt->disk_guid);
+ printf("GPT disk GUID ________ : {%s}\n", guid_text);
+}
diff --git a/com32/modules/chain.c b/com32/modules/chain.c
index 6a5b1151..b22caa14 100644
--- a/com32/modules/chain.c
+++ b/com32/modules/chain.c
@@ -117,10 +117,9 @@
#include <syslinux/loadfile.h>
#include <syslinux/bootrm.h>
#include <syslinux/config.h>
+#include <syslinux/disk.h>
#include <syslinux/video.h>
-#define SECTOR 512 /* bytes/sector */
-
static struct options {
const char *loadfile;
uint16_t keeppxe;
@@ -147,308 +146,19 @@ static inline void error(const char *msg)
fputs(msg, stderr);
}
-/*
- * Call int 13h, but with retry on failure. Especially floppies need this.
- */
-static int int13_retry(const com32sys_t * inreg, com32sys_t * outreg)
-{
- int retry = 6; /* Number of retries */
- com32sys_t tmpregs;
-
- if (!outreg)
- outreg = &tmpregs;
-
- while (retry--) {
- __intcall(0x13, inreg, outreg);
- if (!(outreg->eflags.l & EFLAGS_CF))
- return 0; /* CF=0, OK */
- }
-
- return -1; /* Error */
-}
-
-/*
- * Query disk parameters and EBIOS availability for a particular disk.
- */
-struct diskinfo {
- int disk;
- int ebios; /* EBIOS supported on this disk */
- int cbios; /* CHS geometry is valid */
- int head;
- int sect;
-} disk_info;
-
-static int get_disk_params(int disk)
-{
- static com32sys_t getparm, parm, getebios, ebios;
-
- disk_info.disk = disk;
- disk_info.ebios = disk_info.cbios = 0;
-
- /* Get EBIOS support */
- getebios.eax.w[0] = 0x4100;
- getebios.ebx.w[0] = 0x55aa;
- getebios.edx.b[0] = disk;
- getebios.eflags.b[0] = 0x3; /* CF set */
-
- __intcall(0x13, &getebios, &ebios);
-
- if (!(ebios.eflags.l & EFLAGS_CF) &&
- ebios.ebx.w[0] == 0xaa55 && (ebios.ecx.b[0] & 1)) {
- disk_info.ebios = 1;
- }
-
- /* Get disk parameters -- really only useful for
- hard disks, but if we have a partitioned floppy
- it's actually our best chance... */
- getparm.eax.b[1] = 0x08;
- getparm.edx.b[0] = disk;
-
- __intcall(0x13, &getparm, &parm);
-
- if (parm.eflags.l & EFLAGS_CF)
- return disk_info.ebios ? 0 : -1;
-
- disk_info.head = parm.edx.b[1] + 1;
- disk_info.sect = parm.ecx.b[0] & 0x3f;
- if (disk_info.sect == 0) {
- disk_info.sect = 1;
- } else {
- disk_info.cbios = 1; /* Valid geometry */
- }
-
- return 0;
-}
-
-/*
- * Get a disk block and return a malloc'd buffer.
- * Uses the disk number and information from disk_info.
- */
-struct ebios_dapa {
- uint16_t len;
- uint16_t count;
- uint16_t off;
- uint16_t seg;
- uint64_t lba;
-};
-
-/* Read count sectors from drive, starting at lba. Return a new buffer */
-static void *read_sectors(uint64_t lba, uint8_t count)
-{
- com32sys_t inreg;
- struct ebios_dapa *dapa = __com32.cs_bounce;
- void *buf = (char *)__com32.cs_bounce + SECTOR;
- void *data;
-
- if (!count)
- /* Silly */
- return NULL;
-
- memset(&inreg, 0, sizeof inreg);
-
- if (disk_info.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] = disk_info.disk;
- inreg.eax.b[1] = 0x42; /* Extended read */
- } else {
- unsigned int c, h, s, t;
-
- if (!disk_info.cbios) {
- /* We failed to get the geometry */
-
- if (lba)
- return NULL; /* Can only read MBR */
-
- s = 1;
- h = 0;
- c = 0;
- } else {
- s = (lba % disk_info.sect) + 1;
- t = lba / disk_info.sect; /* Track = head*cyl */
- h = t % disk_info.head;
- c = t / disk_info.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.edx.b[1] = h;
- inreg.edx.b[0] = disk_info.disk;
- inreg.ebx.w[0] = OFFS(buf);
- inreg.es = SEG(buf);
- }
-
- if (int13_retry(&inreg, NULL))
- return NULL;
-
- data = malloc(count * SECTOR);
- if (data)
- memcpy(data, buf, count * SECTOR);
- return data;
-}
-
-static int write_sector(unsigned int lba, const void *data)
-{
- com32sys_t inreg;
- struct ebios_dapa *dapa = __com32.cs_bounce;
- void *buf = (char *)__com32.cs_bounce + SECTOR;
-
- memcpy(buf, data, SECTOR);
- memset(&inreg, 0, sizeof inreg);
-
- if (disk_info.ebios) {
- dapa->len = sizeof(*dapa);
- dapa->count = 1; /* 1 sector */
- 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] = disk_info.disk;
- inreg.eax.w[0] = 0x4300; /* Extended write */
- } else {
- unsigned int c, h, s, t;
-
- if (!disk_info.cbios) {
- /* We failed to get the geometry */
-
- if (lba)
- return -1; /* Can only write MBR */
-
- s = 1;
- h = 0;
- c = 0;
- } else {
- s = (lba % disk_info.sect) + 1;
- t = lba / disk_info.sect; /* Track = head*cyl */
- h = t % disk_info.head;
- c = t / disk_info.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.edx.b[1] = h;
- inreg.edx.b[0] = disk_info.disk;
- inreg.ebx.w[0] = OFFS(buf);
- inreg.es = SEG(buf);
- }
-
- if (int13_retry(&inreg, NULL))
- return -1;
-
- return 0; /* ok */
-}
-
-static int write_verify_sector(unsigned int lba, const void *buf)
-{
- char *rb;
- int rv;
-
- rv = write_sector(lba, buf);
- if (rv)
- return rv; /* Write failure */
- rb = read_sectors(lba, 1);
- if (!rb)
- return -1; /* Readback failure */
- rv = memcmp(buf, rb, SECTOR);
- free(rb);
- return rv ? -1 : 0;
-}
-
-/*
- * CHS (cylinder, head, sector) value extraction macros.
- * Taken from WinVBlock. Does not expand to an lvalue
-*/
-#define chs_head(chs) chs[0]
-#define chs_sector(chs) (chs[1] & 0x3F)
-#define chs_cyl_high(chs) (((uint16_t)(chs[1] & 0xC0)) << 2)
-#define chs_cyl_low(chs) ((uint16_t)chs[2])
-#define chs_cylinder(chs) (chs_cyl_high(chs) | chs_cyl_low(chs))
-typedef uint8_t chs[3];
-
-/* A DOS partition table entry */
-struct part_entry {
- uint8_t active_flag; /* 0x80 if "active" */
- chs start;
- uint8_t ostype;
- chs end;
- uint32_t start_lba;
- uint32_t length;
-} __attribute__ ((packed));
-
-static void mbr_part_dump(const struct part_entry *part)
-{
- (void)part;
- dprintf("Partition status _____ : 0x%.2x\n"
- "Partition CHS start\n"
- " Cylinder ___________ : 0x%.4x (%u)\n"
- " Head _______________ : 0x%.2x (%u)\n"
- " Sector _____________ : 0x%.2x (%u)\n"
- "Partition type _______ : 0x%.2x\n"
- "Partition CHS end\n"
- " Cylinder ___________ : 0x%.4x (%u)\n"
- " Head _______________ : 0x%.2x (%u)\n"
- " Sector _____________ : 0x%.2x (%u)\n"
- "Partition LBA start __ : 0x%.8x (%u)\n"
- "Partition LBA count __ : 0x%.8x (%u)\n"
- "-------------------------------\n",
- part->active_flag,
- chs_cylinder(part->start),
- chs_cylinder(part->start),
- chs_head(part->start),
- chs_head(part->start),
- chs_sector(part->start),
- chs_sector(part->start),
- part->ostype,
- chs_cylinder(part->end),
- chs_cylinder(part->end),
- chs_head(part->end),
- chs_head(part->end),
- chs_sector(part->end),
- chs_sector(part->end),
- part->start_lba,
- part->start_lba,
- part->length,
- part->length);
-}
-
-/* A DOS MBR */
-struct mbr {
- char code[440];
- uint32_t disk_sig;
- char pad[2];
- struct part_entry table[4];
- uint16_t sig;
-} __attribute__ ((packed));
-static const uint16_t mbr_sig_magic = 0xAA55;
+static struct disk_info diskinfo;
/* Search for a specific drive, based on the MBR signature; bytes 440-443 */
static int find_disk(uint32_t mbr_sig)
{
int drive;
bool is_me;
- struct mbr *mbr;
+ struct disk_dos_mbr *mbr;
for (drive = 0x80; drive <= 0xff; drive++) {
- if (get_disk_params(drive))
+ if (disk_get_params(drive, &diskinfo))
continue; /* Drive doesn't exist */
- if (!(mbr = read_sectors(0, 1)))
+ if (!(mbr = disk_read_sectors(&diskinfo, 0, 1)))
continue; /* Cannot read sector */
is_me = (mbr->disk_sig == mbr_sig);
free(mbr);
@@ -474,7 +184,7 @@ struct disk_part_iter {
/* The partition number, as determined by our heuristic */
int index;
/* The DOS partition record to pass, if applicable */
- const struct part_entry *record;
+ const struct disk_dos_part_entry *record;
/* Function returning the next available partition */
disk_part_iter_func next;
/* Partition-/scheme-specific details */
@@ -508,16 +218,16 @@ struct disk_part_iter {
static struct disk_part_iter *next_ebr_part(struct disk_part_iter *part)
{
- const struct part_entry *ebr_table;
- const struct part_entry *parent_table =
- ((const struct mbr *)part->private.ebr.parent->block)->table;
- static const struct part_entry phony = {.start_lba = 0 };
+ const struct disk_dos_part_entry *ebr_table;
+ const struct disk_dos_part_entry *parent_table =
+ ((const struct disk_dos_mbr *)part->private.ebr.parent->block)->table;
+ static const struct disk_dos_part_entry phony = {.start_lba = 0 };
uint64_t ebr_lba;
/* Don't look for a "next EBR" the first time around */
if (part->private.ebr.parent_index >= 0)
/* Look at the linked list */
- ebr_table = ((const struct mbr *)part->block)->table + 1;
+ ebr_table = ((const struct disk_dos_mbr *)part->block)->table + 1;
/* Do we need to look for an extended partition? */
if (part->private.ebr.parent_index < 0 || !ebr_table->start_lba) {
/* Start looking for an extended partition in the MBR */
@@ -537,14 +247,14 @@ static struct disk_part_iter *next_ebr_part(struct disk_part_iter *part)
/* Load next EBR */
ebr_lba = ebr_table->start_lba + part->private.ebr.lba_extended;
free(part->block);
- part->block = read_sectors(ebr_lba, 1);
+ part->block = disk_read_sectors(&diskinfo, ebr_lba, 1);
if (!part->block) {
error("Could not load EBR!\n");
goto err_ebr;
}
- ebr_table = ((const struct mbr *)part->block)->table;
+ ebr_table = ((const struct disk_dos_mbr *)part->block)->table;
dprintf("next_ebr_part:\n");
- mbr_part_dump(ebr_table);
+ disk_dos_part_dump(ebr_table);
/*
* Sanity check entry: must not extend outside the
@@ -552,9 +262,9 @@ static struct disk_part_iter *next_ebr_part(struct disk_part_iter *part)
* put crap in some entries.
*/
{
- const struct mbr *mbr =
- (const struct mbr *)part->private.ebr.parent->block;
- const struct part_entry *extended =
+ const struct disk_dos_mbr *mbr =
+ (const struct disk_dos_mbr *)part->private.ebr.parent->block;
+ const struct disk_dos_part_entry *extended =
mbr->table + part->private.ebr.parent_index;
if (ebr_table[0].start_lba >= extended->start_lba + extended->length) {
@@ -587,7 +297,8 @@ static struct disk_part_iter *next_mbr_part(struct disk_part_iter *part)
{
struct disk_part_iter *ebr_part;
/* Look at the partition table */
- struct part_entry *table = ((struct mbr *)part->block)->table;
+ struct disk_dos_part_entry *table =
+ ((struct disk_dos_mbr *)part->block)->table;
/* Look for data partitions */
while (++part->private.mbr_index < 4) {
@@ -621,7 +332,7 @@ static struct disk_part_iter *next_mbr_part(struct disk_part_iter *part)
return next_ebr_part(ebr_part);
}
dprintf("next_mbr_part:\n");
- mbr_part_dump(table + part->private.mbr_index);
+ disk_dos_part_dump(table + part->private.mbr_index);
/* Update parameters to reflect this new partition. Re-use iterator */
part->lba_data = table[part->private.mbr_index].start_lba;
@@ -638,226 +349,15 @@ err_alloc:
return NULL;
}
-/*
- * GUID
- * Be careful with endianness, you must adjust it yourself
- * iff you are directly using the fourth data chunk
- */
-struct guid {
- uint32_t data1;
- uint16_t data2;
- uint16_t data3;
- uint64_t data4;
-} __attribute__ ((packed));
-
- /*
- * This walk-map effectively reverses the little-endian
- * portions of the GUID in the output text
- */
-static const char guid_le_walk_map[] = {
- 3, -1, -1, -1, 0,
- 5, -1, 0,
- 3, -1, 0,
- 2, 1, 0,
- 1, 1, 1, 1, 1, 1
-};
-
-#if DEBUG
-/*
- * Fill a buffer with a textual GUID representation.
- * The buffer must be >= char[37] and will be populated
- * with an ASCII NUL C string terminator.
- * Example: 11111111-2222-3333-4444-444444444444
- * Endian: LLLLLLLL-LLLL-LLLL-BBBB-BBBBBBBBBBBB
- */
-static void guid_to_str(char *buf, const struct guid *id)
-{
- unsigned int i = 0;
- const char *walker = (const char *)id;
-
- while (i < sizeof(guid_le_walk_map)) {
- walker += guid_le_walk_map[i];
- if (!guid_le_walk_map[i])
- *buf = '-';
- else {
- *buf = ((*walker & 0xF0) >> 4) + '0';
- if (*buf > '9')
- *buf += 'A' - '9' - 1;
- buf++;
- *buf = (*walker & 0x0F) + '0';
- if (*buf > '9')
- *buf += 'A' - '9' - 1;
- }
- buf++;
- i++;
- }
- *buf = 0;
-}
-#endif
-
-/*
- * Create a GUID structure from a textual GUID representation.
- * The input buffer must be >= 32 hexadecimal chars and be
- * terminated with an ASCII NUL. Returns non-zero on failure.
- * Example: 11111111-2222-3333-4444-444444444444
- * Endian: LLLLLLLL-LLLL-LLLL-BBBB-BBBBBBBBBBBB
- */
-static int str_to_guid(const char *buf, struct guid *id)
-{
- char guid_seq[sizeof(struct guid) * 2];
- unsigned int i = 0;
- char *walker = (char *)id;
-
- while (*buf && i < sizeof(guid_seq)) {
- switch (*buf) {
- /* Skip these three characters */
- case '{':
- case '}':
- case '-':
- break;
- default:
- /* Copy something useful to the temp. sequence */
- if ((*buf >= '0') && (*buf <= '9'))
- guid_seq[i] = *buf - '0';
- else if ((*buf >= 'A') && (*buf <= 'F'))
- guid_seq[i] = *buf - 'A' + 10;
- else if ((*buf >= 'a') && (*buf <= 'f'))
- guid_seq[i] = *buf - 'a' + 10;
- else {
- /* Or not */
- error("Illegal character in GUID!\n");
- return -1;
- }
- i++;
- }
- buf++;
- }
- /* Check for insufficient valid characters */
- if (i < sizeof(guid_seq)) {
- error("Too few GUID characters!\n");
- return -1;
- }
- buf = guid_seq;
- i = 0;
- while (i < sizeof(guid_le_walk_map)) {
- if (!guid_le_walk_map[i])
- i++;
- walker += guid_le_walk_map[i];
- *walker = *buf << 4;
- buf++;
- *walker |= *buf;
- buf++;
- i++;
- }
- return 0;
-}
-
-/* A GPT partition */
-struct gpt_part {
- struct guid type;
- struct guid uid;
- uint64_t lba_first;
- uint64_t lba_last;
- uint64_t attribs;
- char name[72];
-} __attribute__ ((packed));
-
-static void gpt_part_dump(const struct gpt_part *gpt_part)
-{
-#ifdef DEBUG
- unsigned int i;
- char guid_text[37];
-
- dprintf("----------------------------------\n"
- "GPT part. LBA first __ : 0x%.16llx\n"
- "GPT part. LBA last ___ : 0x%.16llx\n"
- "GPT part. attribs ____ : 0x%.16llx\n"
- "GPT part. name _______ : '",
- gpt_part->lba_first, gpt_part->lba_last, gpt_part->attribs);
- for (i = 0; i < sizeof(gpt_part->name); i++) {
- if (gpt_part->name[i])
- dprintf("%c", gpt_part->name[i]);
- }
- dprintf("'");
- guid_to_str(guid_text, &gpt_part->type);
- dprintf("GPT part. type GUID __ : {%s}\n", guid_text);
- guid_to_str(guid_text, &gpt_part->uid);
- dprintf("GPT part. unique ID __ : {%s}\n", guid_text);
-#endif
- (void)gpt_part;
-}
-
-/* A GPT header */
-struct gpt {
- char sig[8];
- union {
- struct {
- uint16_t minor;
- uint16_t major;
- } fields __attribute__ ((packed));
- uint32_t uint32;
- char raw[4];
- } rev __attribute__ ((packed));
- uint32_t hdr_size;
- uint32_t chksum;
- char reserved1[4];
- uint64_t lba_cur;
- uint64_t lba_alt;
- uint64_t lba_first_usable;
- uint64_t lba_last_usable;
- struct guid disk_guid;
- uint64_t lba_table;
- uint32_t part_count;
- uint32_t part_size;
- uint32_t table_chksum;
- char reserved2[1];
-} __attribute__ ((packed));
-static const char gpt_sig_magic[] = "EFI PART";
-
-#if DEBUG
-static void gpt_dump(const struct gpt *gpt)
-{
- char guid_text[37];
-
- printf("GPT sig ______________ : '%8.8s'\n"
- "GPT major revision ___ : 0x%.4x\n"
- "GPT minor revision ___ : 0x%.4x\n"
- "GPT header size ______ : 0x%.8x\n"
- "GPT header checksum __ : 0x%.8x\n"
- "GPT reserved _________ : '%4.4s'\n"
- "GPT LBA current ______ : 0x%.16llx\n"
- "GPT LBA alternative __ : 0x%.16llx\n"
- "GPT LBA first usable _ : 0x%.16llx\n"
- "GPT LBA last usable __ : 0x%.16llx\n"
- "GPT LBA part. table __ : 0x%.16llx\n"
- "GPT partition count __ : 0x%.8x\n"
- "GPT partition size ___ : 0x%.8x\n"
- "GPT part. table chksum : 0x%.8x\n",
- gpt->sig,
- gpt->rev.fields.major,
- gpt->rev.fields.minor,
- gpt->hdr_size,
- gpt->chksum,
- gpt->reserved1,
- gpt->lba_cur,
- gpt->lba_alt,
- gpt->lba_first_usable,
- gpt->lba_last_usable,
- gpt->lba_table, gpt->part_count, gpt->part_size, gpt->table_chksum);
- guid_to_str(guid_text, &gpt->disk_guid);
- printf("GPT disk GUID ________ : {%s}\n", guid_text);
-}
-#endif
-
static struct disk_part_iter *next_gpt_part(struct disk_part_iter *part)
{
- const struct gpt_part *gpt_part = NULL;
+ const struct disk_gpt_part_entry *gpt_part = NULL;
while (++part->private.gpt.index < part->private.gpt.parts) {
gpt_part =
- (const struct gpt_part *)(part->block +
- (part->private.gpt.index *
- part->private.gpt.size));
+ (const struct disk_gpt_part_entry *)(part->block +
+ (part->private.gpt.index *
+ part->private.gpt.size));
if (!gpt_part->lba_first)
continue;
break;
@@ -871,7 +371,9 @@ static struct disk_part_iter *next_gpt_part(struct disk_part_iter *part)
part->private.gpt.part_label = gpt_part->name;
/* Update our index */
part->index = part->private.gpt.index + 1;
- gpt_part_dump(gpt_part);
+#ifdef DEBUG
+ disk_gpt_part_dump(gpt_part);
+#endif
/* In a GPT scheme, we re-use the iterator */
return part;
@@ -885,7 +387,7 @@ err_last:
static struct disk_part_iter *get_first_partition(struct disk_part_iter *part)
{
- const struct gpt *gpt_candidate;
+ const struct disk_gpt_header *gpt_candidate;
/*
* Ignore any passed partition iterator. The caller should
@@ -897,13 +399,13 @@ static struct disk_part_iter *get_first_partition(struct disk_part_iter *part)
goto err_alloc_iter;
}
/* Read MBR */
- part->block = read_sectors(0, 2);
+ part->block = disk_read_sectors(&diskinfo, 0, 2);
if (!part->block) {
error("Could not read two sectors!\n");
goto err_read_mbr;
}
/* Check for an MBR */
- if (((struct mbr *)part->block)->sig != mbr_sig_magic) {
+ if (((struct disk_dos_mbr *)part->block)->sig != disk_mbr_sig_magic) {
error("No MBR magic!\n");
goto err_mbr;
}
@@ -913,8 +415,9 @@ static struct disk_part_iter *get_first_partition(struct disk_part_iter *part)
part->private.mbr_index = -1;
part->next = next_mbr_part;
/* Check for a GPT disk */
- gpt_candidate = (const struct gpt *)(part->block + SECTOR);
- if (!memcmp(gpt_candidate->sig, gpt_sig_magic, sizeof(gpt_sig_magic))) {
+ gpt_candidate = (const struct disk_gpt_header *)(part->block + SECTOR);
+ if (!memcmp
+ (gpt_candidate->sig, disk_gpt_sig_magic, sizeof(disk_gpt_sig_magic))) {
/* LBA for partition table */
uint64_t lba_table;
@@ -922,7 +425,7 @@ static struct disk_part_iter *get_first_partition(struct disk_part_iter *part)
/* TODO: Check checksum. Possibly try alternative GPT */
#if DEBUG
puts("Looks like a GPT disk.");
- gpt_dump(gpt_candidate);
+ disk_gpt_header_dump(gpt_candidate);
#endif
/* TODO: Check table checksum (maybe) */
/* Note relevant GPT details */
@@ -935,9 +438,10 @@ static struct disk_part_iter *get_first_partition(struct disk_part_iter *part)
/* Load the partition table */
free(part->block);
part->block =
- read_sectors(lba_table,
- ((part->private.gpt.size * part->private.gpt.parts) +
- SECTOR - 1) / SECTOR);
+ disk_read_sectors(&diskinfo, lba_table,
+ ((part->private.gpt.size *
+ part->private.gpt.parts) + SECTOR -
+ 1) / SECTOR);
if (!part->block) {
error("Could not read GPT partition list!\n");
goto err_gpt_table;
@@ -973,20 +477,21 @@ static int find_by_guid(const struct guid *gpt_guid,
{
int drive;
bool is_me;
- struct gpt *header;
+ struct disk_gpt_header *header;
for (drive = 0x80; drive <= 0xff; drive++) {
- if (get_disk_params(drive))
+ if (disk_get_params(drive, &diskinfo))
continue; /* Drive doesn't exist */
- if (!(header = read_sectors(1, 1)))
+ if (!(header = disk_read_sectors(&diskinfo, 1, 1)))
continue; /* Cannot read sector */
- if (memcmp(&header->sig, gpt_sig_magic, sizeof(gpt_sig_magic))) {
+ if (memcmp
+ (&header->sig, disk_gpt_sig_magic, sizeof(disk_gpt_sig_magic))) {
/* Not a GPT disk */
free(header);
continue;
}
#if DEBUG
- gpt_dump(header);
+ disk_gpt_header_dump(header);
#endif
is_me = !memcmp(&header->disk_guid, &gpt_guid, sizeof(*gpt_guid));
free(header);
@@ -1022,7 +527,7 @@ static int find_by_label(const char *label, struct disk_part_iter **boot_part)
bool is_me;
for (drive = 0x80; drive <= 0xff; drive++) {
- if (get_disk_params(drive))
+ if (disk_get_params(drive, &diskinfo))
continue; /* Drive doesn't exist */
/* Check for a GPT disk */
boot_part[0] = get_first_partition(NULL);
@@ -1036,7 +541,7 @@ static int find_by_label(const char *label, struct disk_part_iter **boot_part)
}
/* Check for a matching partition */
while (boot_part[0]) {
- char gpt_label[sizeof(((struct gpt_part *) NULL)->name)];
+ char gpt_label[sizeof(((struct disk_gpt_part_entry *) NULL)->name)];
const char *gpt_label_scanner =
boot_part[0]->private.gpt.part_label;
int j = 0;
@@ -1189,10 +694,10 @@ enomem:
return;
}
-static int hide_unhide(struct mbr *mbr, int part)
+static int hide_unhide(struct disk_dos_mbr *mbr, int part)
{
int i;
- struct part_entry *pt;
+ struct disk_dos_part_entry *pt;
const uint16_t mask =
(1 << 0x01) | (1 << 0x04) | (1 << 0x06) | (1 << 0x07) | (1 << 0x0b) | (1
<<
@@ -1218,7 +723,7 @@ static int hide_unhide(struct mbr *mbr, int part)
}
if (write_back)
- return write_verify_sector(0, mbr);
+ return disk_write_verify_sector(&diskinfo, 0, mbr);
return 0; /* ok */
}
@@ -1297,7 +802,7 @@ See syslinux/com32/modules/chain.c for more information\n";
int main(int argc, char *argv[])
{
- struct mbr *mbr = NULL;
+ struct disk_dos_mbr *mbr = NULL;
char *p;
struct disk_part_iter *cur_part = NULL;
struct syslinux_rm_regs regs;
@@ -1471,13 +976,13 @@ int main(int argc, char *argv[])
regs.ebx.b[0] = regs.edx.b[0] = drive;
/* Get the disk geometry and disk access setup */
- if (get_disk_params(drive)) {
+ if (disk_get_params(drive, &diskinfo)) {
error("Cannot get disk parameters\n");
goto bail;
}
/* Get MBR */
- if (!(mbr = read_sectors(0, 1))) {
+ if (!(mbr = disk_read_sectors(&diskinfo, 0, 1))) {
error("Cannot read Master Boot Record or sector 0\n");
goto bail;
}
@@ -1730,7 +1235,10 @@ int main(int argc, char *argv[])
/* Actually read the boot sector */
if (!cur_part) {
data[ndata].data = mbr;
- } else if (!(data[ndata].data = read_sectors(cur_part->lba_data, 1))) {
+ } else
+ if (!
+ (data[ndata].data =
+ disk_read_sectors(&diskinfo, cur_part->lba_data, 1))) {
error("Cannot read boot sector\n");
goto bail;
}
@@ -1738,10 +1246,11 @@ int main(int argc, char *argv[])
data[ndata].base = load_base;
if (!opt.loadfile) {
- const struct mbr *br =
- (const struct mbr *)((char *)data[ndata].data +
- data[ndata].size - sizeof(struct mbr));
- if (br->sig != mbr_sig_magic) {
+ const struct disk_dos_mbr *br =
+ (const struct disk_dos_mbr *)((char *)data[ndata].data +
+ data[ndata].size -
+ sizeof(struct disk_dos_mbr));
+ if (br->sig != disk_mbr_sig_magic) {
error
("Boot sector signature not found (unbootable disk/partition?)\n");
goto bail;
@@ -1772,16 +1281,17 @@ int main(int argc, char *argv[])
if (cur_part) {
if (cur_part->next == next_gpt_part) {
/* Do GPT hand-over, if applicable (as per syslinux/doc/gpt.txt) */
- struct part_entry *record;
+ struct disk_dos_part_entry *record;
/* Look at the GPT partition */
- const struct gpt_part *gp = (const struct gpt_part *)
+ const struct disk_gpt_part_entry *gp =
+ (const struct disk_gpt_part_entry *)
(cur_part->block +
(cur_part->private.gpt.size * cur_part->private.gpt.index));
/* Note the partition length */
uint64_t lba_count = gp->lba_last - gp->lba_first + 1;
/* The length of the hand-over */
int synth_size =
- sizeof(struct part_entry) + sizeof(uint32_t) +
+ sizeof(struct disk_dos_part_entry) + sizeof(uint32_t) +
cur_part->private.gpt.size;
/* Will point to the partition record length in the hand-over */
uint32_t *plen;
@@ -1819,11 +1329,13 @@ int main(int argc, char *argv[])
regs.esi.w[0] = 0x7be;
dprintf("GPT handover:\n");
- mbr_part_dump(record);
- gpt_part_dump((struct gpt_part *)(plen + 1));
+ disk_dos_part_dump(record);
+#ifdef DEBUG
+ disk_gpt_part_dump((struct disk_gpt_part_entry *)(plen + 1));
+#endif
} else if (cur_part->record) {
/* MBR handover protocol */
- static struct part_entry handover_record;
+ static struct disk_dos_part_entry handover_record;
handover_record = *cur_part->record;
handover_record.start_lba = cur_part->lba_data;
@@ -1835,7 +1347,7 @@ int main(int argc, char *argv[])
regs.esi.w[0] = 0x7be;
dprintf("MBR handover:\n");
- mbr_part_dump(&handover_record);
+ disk_dos_part_dump(&handover_record);
}
}