aboutsummaryrefslogtreecommitdiffstats
path: root/com32/lib/syslinux/multifs_utils.c
blob: f06ad0061a4fa3835a9d68b879b07f5d89e93498 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * Copyright (C) 2012 Andre Ericson <de.ericson@gmail.com>
 * Copyright (C) 2012-2015 Paulo Alcantara <pcacjr@zytor.com>
 * Copyright (C) 2013 Raphael S. Carvalho <raphael.scarv@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "core.h"
#include "fs.h"
#include "disk.h"
#include "cache.h"

#include <syslinux/multifs_utils.h>

/* 0x80 - 0xFF
 * BIOS limitation */
#define DISK_ID_OFFSET 0x80

/* MaxTransfer for multifs access */
#define MAX_TRANSFER 127

static void *get_private(uint8_t devno, uint64_t part_start,
                         uint16_t bsHeads, uint16_t bsSecPerTrack)
{
    com32sys_t *regs;
    struct bios_disk_private *priv;

    regs = malloc(sizeof(*regs));
    if (!regs)
        return NULL;
    memset(regs, 0, sizeof(*regs));

    regs->edx.b[0] = devno;
    regs->edx.b[1] = 0; /* XXX: cdrom ->->-> always 0? */
    regs->ecx.l = part_start & 0xFFFFFFFF;
    regs->ebx.l = part_start >> 32;
    regs->esi.w[0] = bsHeads;
    regs->edi.w[0] = bsSecPerTrack;
    regs->ebp.l = MAX_TRANSFER; /* XXX: should it be pre-defined? */

    priv = malloc(sizeof(*priv));
    if (!priv) {
        free(regs);
        priv = NULL;
    } else {
        priv->regs = regs;
    }
    return priv;
}

void *bios_find_partition(uint8_t diskno, uint8_t partno)
{
    uint8_t disk_devno;
    struct part_iter *iter = NULL;
    struct disk_info diskinfo;

    dprintf("%s: diskno %d partition %d\n", __func__, diskno, partno);

    disk_devno = DISK_ID_OFFSET + diskno;
    if (disk_get_params(disk_devno, &diskinfo))
        return NULL;
    if (!(iter = pi_begin(&diskinfo, 0)))
        return NULL;

    do {
        if (iter->index == partno)
            break;
    } while (!pi_next(iter));

    if (iter->status) {
        dprintf("multifs: Request disk/partition combination not found.\n");
        pi_del(&iter);
        return NULL;
    }
    dprintf("multifs: found 0x%llx at index: %i and partition %i\n",
            iter->abs_lba, iter->index, partno);
    return get_private(disk_devno, iter->abs_lba, diskinfo.head, diskinfo.spt);
}