[syslinux] [PATCH 02/12] core: move disklib into core

Andre Ericson de.ericson at gmail.com
Mon Aug 20 01:16:44 PDT 2012


Move disklib into core so that it can be used by multidisk support.

Signed-off-by: Andre Ericson <de.ericson at gmail.com>
Signed-off-by: Paulo Alcantara <pcacjr at zytor.com>
---
 core/disk.c         | 567 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 core/include/disk.h | 143 +++++++++++++
 2 files changed, 710 insertions(+)
 create mode 100644 core/disk.c

diff --git a/core/disk.c b/core/disk.c
new file mode 100644
index 0000000..5e3ce61
--- /dev/null
+++ b/core/disk.c
@@ -0,0 +1,567 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ *   Copyright (C) 2010 Shao Miller
+ *   Copyright 2012 Andre Ericson
+ *
+ *   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 <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 inreg, outreg;
+    struct disk_ebios_eparam *eparam = NULL;
+
+    memset(diskinfo, 0, sizeof *diskinfo);
+    diskinfo->disk = disk;
+    diskinfo->bps = SECTOR;
+
+    /* Get EBIOS support */
+    memset(&inreg, 0, sizeof inreg);
+    inreg.eax.b[1] = 0x41;
+    inreg.ebx.w[0] = 0x55aa;
+    inreg.edx.b[0] = disk;
+    inreg.eflags.b[0] = 0x3;	/* CF set */
+
+    __intcall(0x13, &inreg, &outreg);
+
+    if (!(outreg.eflags.l & EFLAGS_CF) &&
+            outreg.ebx.w[0] == 0xaa55 && (outreg.ecx.b[0] & 1)) {
+        diskinfo->ebios = 1;
+    }
+
+    /* Get extended disk parameters if ebios == 1 */
+    if (diskinfo->ebios) {
+        eparam = lmalloc(sizeof *eparam);
+        if (!eparam)
+            return -1;
+        memset(&inreg, 0, sizeof inreg);
+        inreg.eax.b[1] = 0x48;
+        inreg.edx.b[0] = disk;
+        inreg.esi.w[0] = OFFS(eparam);
+        inreg.ds = SEG(eparam);
+
+        memset(eparam, 0, sizeof *eparam);
+        eparam->len = sizeof *eparam;
+
+        __intcall(0x13, &inreg, &outreg);
+
+        if (!(outreg.eflags.l & EFLAGS_CF)) {
+            diskinfo->lbacnt = eparam->lbacnt;
+            if (eparam->bps)
+                diskinfo->bps = eparam->bps;
+            /*
+             * don't think about using geometry data returned by
+             * 48h, as it can differ from 08h a lot ...
+             */
+        }
+    }
+    /*
+     * Get disk parameters the old way - really only useful for hard
+     * disks, but if we have a partitioned floppy it's actually our best
+     * chance...
+     */
+    memset(&inreg, 0, sizeof inreg);
+    inreg.eax.b[1] = 0x08;
+    inreg.edx.b[0] = disk;
+
+    __intcall(0x13, &inreg, &outreg);
+
+    if (outreg.eflags.l & EFLAGS_CF) {
+        lfree(eparam);
+        return diskinfo->ebios ? 0 : -1;
+    }
+
+    diskinfo->spt = 0x3f & outreg.ecx.b[0];
+    diskinfo->head = 1 + outreg.edx.b[1];
+    diskinfo->cyl = 1 + (outreg.ecx.b[1] | ((outreg.ecx.b[0] & 0xc0u) << 2));
+
+    if (diskinfo->spt)
+        diskinfo->cbios = 1;	/* Valid geometry */
+    else {
+        diskinfo->head = 1;
+        diskinfo->spt = 1;
+        diskinfo->cyl = 1;
+    }
+
+    if (!diskinfo->lbacnt)
+        diskinfo->lbacnt = diskinfo->cyl * diskinfo->head * diskinfo->spt;
+
+    lfree(eparam);
+    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 = NULL;
+    uint8_t *buf = NULL;
+    void *data;
+
+    if (!count || lba + count > diskinfo->lbacnt)
+        return NULL;
+
+    memset(&inreg, 0, sizeof inreg);
+
+    buf = (uint8_t *)lmalloc(diskinfo->bps * count);
+    if (!buf)
+        return NULL;
+
+    if (diskinfo->ebios) {
+        dapa = lmalloc(sizeof *dapa);
+        if (!dapa)
+            goto fail;
+        dapa->len = sizeof(struct disk_ebios_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 fail;
+
+    data = malloc(count * diskinfo->bps);
+    if (data)
+        memcpy(data, buf, count * diskinfo->bps);
+    lfree(dapa);
+    lfree(buf);
+    return data;
+
+fail:
+    lfree(buf);
+    lfree(dapa);
+    return NULL;
+}
+
+/**
+ * Write disk block(s).
+ *
+ * @v diskinfo			The disk drive to write to
+ * @v lba			The logical block address to begin writing at
+ * @v data			The data to write
+ * @v count			The number of sectors to write
+ * @ret (int)			0 upon success, -1 upon failure
+ *
+ * Uses the disk number and information from diskinfo.
+ * Write sector(s) to a disk drive, starting at lba.
+ */
+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 = NULL;
+    uint8_t *buf = NULL;
+
+    if (!count || lba + count > diskinfo->lbacnt)
+        return -1;
+
+    buf = (uint8_t *)lmalloc(diskinfo->bps * count);
+    if (!buf)
+        return -1;
+
+    memcpy(buf, data, count * diskinfo->bps);
+    memset(&inreg, 0, sizeof inreg);
+
+    if (diskinfo->ebios) {
+        dapa = lmalloc(sizeof *dapa);
+        if (!dapa)
+            goto fail;
+        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 fail;
+
+    lfree(dapa);
+    lfree(buf);
+
+    return 0;			/* ok */
+
+fail:
+    lfree(buf);
+    lfree(dapa);
+    return -1;
+}
+
+/**
+ * Write disk blocks and verify they were 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
+ * @v count			The number of sectors to write
+ * @ret rv			0 upon success, -1 upon failure
+ *
+ * Uses the disk number and information from diskinfo.
+ * Writes sectors to a disk drive starting at lba, then reads them back
+ * to verify they were written correctly.
+ */
+int disk_write_verify_sectors(const struct disk_info *const diskinfo,
+        uint64_t lba, const void *buf, uint8_t count)
+{
+    char *rb;
+    int rv;
+
+    rv = disk_write_sectors(diskinfo, lba, buf, count);
+    if (rv)
+        return rv;		/* Write failure */
+    rb = disk_read_sectors(diskinfo, lba, count);
+    if (!rb)
+        return -1;		/* Readback failure */
+    rv = memcmp(buf, rb, count * diskinfo->bps);
+    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;
+    printf("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/core/include/disk.h b/core/include/disk.h
index ac23e92..51358ea 100644
--- a/core/include/disk.h
+++ b/core/include/disk.h
@@ -4,6 +4,51 @@
 #include <stddef.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <stdint.h>
+#include <com32.h>
+#include "core.h"
+
+#define SECTOR 512u     /* bytes/sector */
+
+struct disk_info {
+    int disk;
+    int ebios;          /* EBIOS supported on this disk */
+    int cbios;          /* CHS geometry is valid */
+    uint32_t bps;       /* bytes per sector */
+    uint64_t lbacnt;        /* total amount of sectors */
+    uint32_t cyl;
+    uint32_t head;
+    uint32_t spt;
+};
+
+struct disk_ebios_dapa {
+    uint16_t len;
+    uint16_t count;
+    uint16_t off;
+    uint16_t seg;
+    uint64_t lba;
+} __attribute__ ((packed));
+
+struct disk_ebios_eparam {
+    uint16_t len;
+    uint16_t info;
+    uint32_t cyl;
+    uint32_t head;
+    uint32_t spt;
+    uint64_t lbacnt;
+    uint16_t bps;   /* bytes per sector */
+    uint32_t edd;
+    uint16_t dpi_sig;
+    uint8_t  dpi_len;
+    char     reserved1[3];
+    char     hostbus[4];
+    char     if_type[8];
+    char     if_path[8];
+    char     dev_path[8];
+    char     reserved2;
+    uint8_t  checksum;
+} __attribute__ ((packed));
+
 
 typedef uint64_t sector_t;
 typedef uint64_t block_t;
@@ -27,6 +72,104 @@ struct disk {
     int (*rdwr_sectors)(struct disk *, void *, sector_t, size_t, bool);
 };
 
+/**
+ * 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_sectors(const struct disk_info *const diskinfo,
+                  uint64_t lba, const void *data, uint8_t count);
+extern int disk_write_verify_sectors(const struct disk_info *const diskinfo,
+                     uint64_t lba, const void *buf, uint8_t count);
+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);
+
+
 extern void read_sectors(char *, sector_t, int);
 extern void getoneblk(struct disk *, char *, block_t, int);
 
-- 
1.7.11.3




More information about the Syslinux mailing list