~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/openhackware/src/libpart/isofs.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * <isofs.c>
 
3
 *
 
4
 * Open Hack'Ware BIOS ISOFS partition type management
 
5
 * 
 
6
 * Copyright (c) 2004-2005 Jocelyn Mayer
 
7
 * 
 
8
 *   This program is free software; you can redistribute it and/or
 
9
 *   modify it under the terms of the GNU General Public License V2
 
10
 *   as published by the Free Software Foundation
 
11
 *
 
12
 *   This program is distributed in the hope that it will be useful,
 
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *   GNU General Public License for more details.
 
16
 *
 
17
 *   You should have received a copy of the GNU General Public License
 
18
 *   along with this program; if not, write to the Free Software
 
19
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
20
 */
 
21
 
 
22
#include <stdlib.h>
 
23
#include <stdio.h>
 
24
#include "bios.h"
 
25
#include "libpart.h"
 
26
 
 
27
/* ISO FS partitions handlers */
 
28
#define ISOFS_BLOCSIZE (2048)
 
29
 
 
30
/* Generic ISO fs descriptor */
 
31
typedef struct isofs_desc_t isofs_desc_t;
 
32
struct isofs_desc_t {
 
33
    uint8_t type;
 
34
    uint8_t ID[5];
 
35
    uint8_t version;
 
36
    uint8_t data[2041];
 
37
} __attribute__ ((packed));
 
38
 
 
39
typedef struct iso_primary_desc_t iso_primary_desc_t;
 
40
struct iso_primary_desc_t {
 
41
    uint8_t type;
 
42
    uint8_t ID[5];
 
43
    uint8_t version;
 
44
    uint8_t pad0;
 
45
    uint8_t system_id[32];
 
46
    uint8_t volume_id[32];
 
47
    uint8_t pad1[8];
 
48
    uint32_t volume_size;
 
49
} __attribute__ ((packed));
 
50
 
 
51
/* The only descriptor we're interrested in here
 
52
 * is El-torito boot descriptor
 
53
 */
 
54
typedef struct isofs_bootdesc_t isofs_bootdesc_t;
 
55
struct isofs_bootdesc_t {
 
56
    uint8_t type;
 
57
    uint8_t ID[5];
 
58
    uint8_t version;
 
59
    uint8_t sys_ID[32];
 
60
    uint8_t pad[32];
 
61
    uint32_t catalog;
 
62
    uint8_t data[1973];
 
63
} __attribute__ ((packed));
 
64
 
 
65
#define ISO_BOOTABLE 0x88
 
66
enum {
 
67
    ISOBOOT_IX86 = 0,
 
68
    ISOBOOT_PPC  = 1,
 
69
    ISOBOOT_MAC  = 2,
 
70
};
 
71
 
 
72
enum {
 
73
    ISOMEDIA_NOEMUL = 0,
 
74
    ISOMEDIA_FL12   = 1,
 
75
    ISOMEDIA_FL144  = 2,
 
76
    ISOMEDIA_FL288  = 3,
 
77
    ISOMEDIA_HD     = 4,
 
78
};
 
79
 
 
80
typedef struct isofs_validdesc_t isofs_validdesc_t;
 
81
struct isofs_validdesc_t {
 
82
    uint8_t ID;
 
83
    uint8_t arch;
 
84
    uint8_t pad[2];
 
85
    uint8_t name[24];
 
86
    uint8_t csum[2];
 
87
    uint16_t key;
 
88
} __attribute__ ((packed));
 
89
 
 
90
typedef struct isofs_bootcat_t isofs_bootcat_t;
 
91
struct isofs_bootcat_t {
 
92
    uint8_t bootable;
 
93
    uint8_t media;
 
94
    uint8_t segment[2];
 
95
    uint8_t sys_type;
 
96
    uint8_t pad;
 
97
    uint16_t nsect;
 
98
    uint32_t offset;
 
99
    uint8_t data[20];
 
100
} __attribute__ ((packed));
 
101
 
 
102
part_t *isofs_probe_partitions (bloc_device_t *bd)
 
103
{
 
104
    unsigned char name[32];
 
105
    void *buffer;
 
106
    union {
 
107
        isofs_desc_t desc;
 
108
        isofs_bootdesc_t bootdesc;
 
109
        iso_primary_desc_t primdesc;
 
110
    } *desc;
 
111
    isofs_validdesc_t *valid;
 
112
    isofs_bootcat_t *bootcat;
 
113
    part_t *part;
 
114
    uint32_t boot_desc;
 
115
    uint32_t nsect, bloc, offset, length;
 
116
    int i, end_reached;
 
117
 
 
118
    part = NULL;
 
119
    buffer = malloc(ISOFS_BLOCSIZE);
 
120
    end_reached = 0;
 
121
    desc = buffer;
 
122
    boot_desc = -1;
 
123
    /* The descriptors start at offset 0x8000 */
 
124
    for (bloc = 0x8000 / ISOFS_BLOCSIZE; end_reached == 0; bloc++) {
 
125
        bd_seek(bd, bloc, 0);
 
126
        if (bd_read(bd, buffer, ISOFS_BLOCSIZE) < 0) {
 
127
            ERROR("%s bloc_read %d failed\n", __func__, bloc);
 
128
            goto error;
 
129
        }
 
130
        if (strncmp("CD001", desc->desc.ID, 5) != 0) {
 
131
            //            MSG("\rNo ISO9660 signature\n");
 
132
            goto error;
 
133
        }
 
134
        /* We found at least one valid descriptor */
 
135
        switch (desc->desc.type) {
 
136
        case 0x00:
 
137
            /* El-torito descriptor, great ! */
 
138
            DPRINTF("El-torito descriptor: %08x %d\n", desc->bootdesc.catalog,
 
139
                    (char *)&desc->bootdesc.catalog - (char *)desc);
 
140
            boot_desc = get_le32(&desc->bootdesc.catalog);
 
141
            break;
 
142
        case 0x01:
 
143
            /* ISOFS primary descriptor */
 
144
            DPRINTF("ISOFS primary descriptor (%d %d)\n",
 
145
                    get_le32(&desc->primdesc.volume_size) * 2048,
 
146
                    get_le32(&desc->primdesc.volume_size));
 
147
            break;
 
148
        case 0x02:
 
149
            /* ISOFS suplementary descriptor */
 
150
            DPRINTF("ISOFS suplementary descriptor\n");
 
151
            break;
 
152
        case 0xFF:
 
153
            /* End of descriptor list */
 
154
            DPRINTF("End of descriptor list\n");
 
155
            end_reached = 1;
 
156
            break;
 
157
        }
 
158
    }
 
159
    if (boot_desc != (uint32_t)(-1)) {
 
160
        /* Find the validation descriptor */
 
161
        bd_seek(bd, boot_desc, 0);
 
162
        for (i = 0; i < (ISOFS_BLOCSIZE / 64); i++) {
 
163
            DPRINTF("ISO catalog...\n");
 
164
            bd_read(bd, buffer, 64);
 
165
            valid = buffer;
 
166
#if 1
 
167
            if (valid->ID != 0x01 || get_le16(&valid->key) != 0xAA55) {
 
168
                ERROR("ISO catalog with invalid ID/key: %x %x\n",
 
169
                      valid->ID, valid->key);
 
170
                continue;
 
171
            }
 
172
#endif
 
173
#if 0
 
174
#if defined (__i386__)
 
175
            if (valid->arch != ISOBOOT_IX86) {
 
176
                ERROR("ISO catalog not for x86: %d\n", valid->arch);
 
177
                continue;
 
178
            }
 
179
#elif defined (__powerpc__) || defined (_ARCH_PPC)
 
180
            if (valid->arch != ISOBOOT_PPC && valid->arch != ISOBOOT_MAC) {
 
181
                ERROR("ISO catalog not for PPC: %d\n", valid->arch);
 
182
                continue;
 
183
            }
 
184
#else
 
185
            ERROR("Unknown host architecture !\n");
 
186
            continue;
 
187
#endif
 
188
#endif
 
189
            bootcat = (void *)(valid + 1);
 
190
            if (bootcat->bootable != ISO_BOOTABLE) {
 
191
                ERROR("Non bootable ISO catalog\n");
 
192
                continue;
 
193
            }
 
194
            nsect = get_le16(&bootcat->nsect);
 
195
            switch (bootcat->media) {
 
196
            case ISOMEDIA_NOEMUL:
 
197
                length = nsect * ISOFS_BLOCSIZE;
 
198
                dprintf("No emulation\n");
 
199
                break;
 
200
            case ISOMEDIA_FL12:
 
201
                length = 1200 * 1024;
 
202
                dprintf("1.2 MB floppy\n");
 
203
                break;
 
204
            case ISOMEDIA_FL144:
 
205
                length = 1440 * 1024;
 
206
                dprintf("1.44 MB floppy\n");
 
207
                break;
 
208
            case ISOMEDIA_FL288:
 
209
                length = 2880 * 1024;
 
210
                dprintf("2.88 MB floppy\n");
 
211
                break;
 
212
            case ISOMEDIA_HD:
 
213
                length = nsect * ISOFS_BLOCSIZE;
 
214
                dprintf("HD image\n");
 
215
                break;
 
216
            default:
 
217
                ERROR("Unknown media type: %d\n", bootcat->media);
 
218
                continue;
 
219
            }
 
220
            offset = get_le32(&bootcat->offset);
 
221
            /* Register boot disc */
 
222
            part = malloc(sizeof(part_t));
 
223
            part->bd = bd;
 
224
            part_set_blocsize(bd, part, ISOFS_BLOCSIZE);
 
225
            part->start = offset;
 
226
            part->size = (length + ISOFS_BLOCSIZE - 1) / ISOFS_BLOCSIZE;
 
227
            part->boot_start.bloc = 0;
 
228
            part->boot_start.offset = 0;
 
229
            part->boot_size.bloc = length / ISOFS_BLOCSIZE;
 
230
            part->boot_size.offset = length % ISOFS_BLOCSIZE;
 
231
            part->boot_load = 0;
 
232
            part->boot_entry = 0;
 
233
            if (valid->name[0] == '\0') {
 
234
                strcpy(name, "ISOFS");
 
235
            } else {
 
236
                memcpy(name, valid->name, sizeof(valid->name));
 
237
                name[sizeof(valid->name)] = '\0';
 
238
            }
 
239
            printf("Partition '%s': %p st %0x size %0x %d\n",
 
240
                   name, part, offset, length, bootcat->media);
 
241
            printf("    boot %0x %0x load %0x entry %0x\n",
 
242
                   part->boot_start.bloc, part->boot_size.bloc,
 
243
                   part->boot_load, part->boot_entry);
 
244
            part->flags = PART_TYPE_ISO9660 | PART_FLAG_BOOT;
 
245
            part_register(bd, part, name, i + 1);
 
246
            fs_raw_set_bootfile(part, part->boot_start.bloc,
 
247
                                part->boot_start.offset,
 
248
                                part->boot_size.bloc,
 
249
                                part->boot_size.offset);
 
250
            break;
 
251
        }
 
252
    }
 
253
error:
 
254
    free(buffer);
 
255
 
 
256
    return part;
 
257
}