source: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/read.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 3.5 KB
RevLine 
[e16e8f2]1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2009 Pierre-Alexandre Meyer
4 *
5 *   Some parts borrowed from chain.c32:
6 *
7 *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
8 *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
9 *
10 *   This file is part of Syslinux, and is made available under
11 *   the terms of the GNU General Public License version 2.
12 *
13 * ----------------------------------------------------------------------- */
14
15#include <com32.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include <disk/errno_disk.h>
20#include <disk/geom.h>
21#include <disk/read.h>
22#include <disk/util.h>
23#include <disk/common.h>
24
25/*
26 * TODO: implement file descriptors to cache metadata (geometry, ...)
27 */
28
29/**
30 * read_mbr - return a pointer to a malloced buffer containing the mbr
31 * @drive:      Drive number
32 * @buf:        Pre-allocated buffer for output
33 *
34 * Return the number of sectors read on success or -1 on failure.
35 * errno_disk contains the error number.
36 **/
37int read_mbr(int drive, void *buf)
38{
39    struct driveinfo drive_info;
40    drive_info.disk = drive;
41
42    /* MBR: lba = 0, 1 sector */
43    return read_sectors(&drive_info, buf, 0, 1);
44}
45
46/**
47 * dev_read - read from a drive
48 * @drive:      Drive number
49 * @buf:        Pre-allocated buffer for output
50 * @lba:        Position to start reading from
51 * @sectors:    Number of sectors to read
52 *
53 * High-level routine to read from a hard drive.
54 * Return the number of sectors read on success or -1 on failure.
55 * errno_disk contains the error number.
56 **/
57int dev_read(int drive, void *buf, unsigned int lba, int sectors)
58{
59    struct driveinfo drive_info;
60    drive_info.disk = drive;
61
62    return read_sectors(&drive_info, buf, lba, sectors);
63}
64
65/**
66 * read_sectors - read several sectors from disk
67 * @drive_info:         driveinfo struct describing the disk
68 * @data:               Pre-allocated buffer for output
69 * @lba:                Position to read
70 * @sectors:            Number of sectors to read
71 *
72 * Return the number of sectors read on success or -1 on failure.
73 * errno_disk contains the error number.
74 **/
75int read_sectors(struct driveinfo *drive_info, void *data,
76                 const unsigned int lba, const int sectors)
77{
78    com32sys_t inreg, outreg;
79    struct ebios_dapa *dapa;
80    void *buf;
81    char *bufp = data;
82    int rv = -1;
83
84    if (get_drive_parameters(drive_info) == -1)
85        return -1;
86
87    buf = lmalloc(sectors * SECTOR);
88    if (!buf)
89        return -1;
90
91    dapa = lmalloc(sizeof(*dapa));
92    if (!dapa)
93        goto fail;
94
95    memset(&inreg, 0, sizeof inreg);
96
97    if (drive_info->ebios) {
98        dapa->len = sizeof(*dapa);
99        dapa->count = sectors;
100        dapa->off = OFFS(buf);
101        dapa->seg = SEG(buf);
102        dapa->lba = lba;
103
104        inreg.esi.w[0] = OFFS(dapa);
105        inreg.ds = SEG(dapa);
106        inreg.edx.b[0] = drive_info->disk;
107        inreg.eax.b[1] = 0x42;  /* Extended read */
108    } else {
109        unsigned int c, h, s;
110
111        if (!drive_info->cbios) {       // XXX errno
112            /* We failed to get the geometry */
113            if (lba)
114                goto fail;      /* Can only read MBR */
115
116            s = 1;
117            h = 0;
118            c = 0;
119        } else
120            lba_to_chs(drive_info, lba, &s, &h, &c);
121
122        // XXX errno
123        if (s > 63 || h > 256 || c > 1023)
124            goto fail;
125
126        inreg.eax.w[0] = 0x0201;        /* Read one sector */
127        inreg.ecx.b[1] = c & 0xff;
128        inreg.ecx.b[0] = s + (c >> 6);
129        inreg.edx.b[1] = h;
130        inreg.edx.b[0] = drive_info->disk;
131        inreg.ebx.w[0] = OFFS(buf);
132        inreg.es = SEG(buf);
133    }
134
135    /* Perform the read */
136    if (int13_retry(&inreg, &outreg)) {
137        errno_disk = outreg.eax.b[1];
138        goto fail;              /* Give up */
139    }
140
141    memcpy(bufp, buf, sectors * SECTOR);
142    rv = sectors;
143
144fail:
145    lfree(dapa);
146    lfree(buf);
147    return rv;
148}
Note: See TracBrowser for help on using the repository browser.