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

« back to all changes in this revision

Viewing changes to roms/u-boot/disk/part_amiga.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
 * (C) Copyright 2001
 
3
 * Hans-Joerg Frieden, Hyperion Entertainment
 
4
 * Hans-JoergF@hyperion-entertainment.com
 
5
 *
 
6
 * SPDX-License-Identifier:     GPL-2.0+
 
7
 */
 
8
#include <common.h>
 
9
#include <command.h>
 
10
#include <ide.h>
 
11
#include "part_amiga.h"
 
12
 
 
13
#ifdef HAVE_BLOCK_DEVICE
 
14
 
 
15
#undef AMIGA_DEBUG
 
16
 
 
17
#ifdef AMIGA_DEBUG
 
18
#define PRINTF(fmt, args...) printf(fmt ,##args)
 
19
#else
 
20
#define PRINTF(fmt, args...)
 
21
#endif
 
22
 
 
23
struct block_header
 
24
{
 
25
    u32 id;
 
26
    u32 summed_longs;
 
27
    s32 chk_sum;
 
28
};
 
29
 
 
30
static unsigned char block_buffer[DEFAULT_SECTOR_SIZE];
 
31
static struct rigid_disk_block rdb = {0};
 
32
static struct bootcode_block bootcode = {0};
 
33
 
 
34
/*
 
35
 * Copy a bcpl to a c string
 
36
 */
 
37
static void bcpl_strcpy(char *to, char *from)
 
38
{
 
39
    int len = *from++;
 
40
 
 
41
    while (len)
 
42
    {
 
43
        *to++ = *from++;
 
44
        len--;
 
45
    }
 
46
    *to = 0;
 
47
}
 
48
 
 
49
/*
 
50
 * Print a BCPL String. BCPL strings start with a byte with the length
 
51
 * of the string, and don't contain a terminating nul character
 
52
 */
 
53
static void bstr_print(char *string)
 
54
{
 
55
    int len = *string++;
 
56
    char buffer[256];
 
57
    int i;
 
58
 
 
59
    i = 0;
 
60
    while (len)
 
61
    {
 
62
        buffer[i++] = *string++;
 
63
        len--;
 
64
    }
 
65
 
 
66
    buffer[i] = 0;
 
67
    printf("%-10s", buffer);
 
68
}
 
69
 
 
70
/*
 
71
 * Sum a block. The checksum of a block must end up at zero
 
72
 * to be valid. The chk_sum field is selected so that adding
 
73
 * it yields zero.
 
74
 */
 
75
int sum_block(struct block_header *header)
 
76
{
 
77
    s32 *block = (s32 *)header;
 
78
    u32 i;
 
79
    s32 sum = 0;
 
80
 
 
81
    for (i = 0; i < header->summed_longs; i++)
 
82
        sum += *block++;
 
83
 
 
84
    return (sum != 0);
 
85
}
 
86
 
 
87
/*
 
88
 * Print an AmigaOS disk type. Disk types are a four-byte identifier
 
89
 * describing the file system. They are usually written as a three-letter
 
90
 * word followed by a backslash and a version number. For example,
 
91
 * DOS\0 would be the original file system. SFS\0 would be SmartFileSystem.
 
92
 * DOS\1 is FFS.
 
93
 */
 
94
static void print_disk_type(u32 disk_type)
 
95
{
 
96
    char buffer[6];
 
97
    buffer[0] = (disk_type & 0xFF000000)>>24;
 
98
    buffer[1] = (disk_type & 0x00FF0000)>>16;
 
99
    buffer[2] = (disk_type & 0x0000FF00)>>8;
 
100
    buffer[3] = '\\';
 
101
    buffer[4] = (disk_type & 0x000000FF) + '0';
 
102
    buffer[5] = 0;
 
103
    printf("%s", buffer);
 
104
}
 
105
 
 
106
/*
 
107
 * Print the info contained within the given partition block
 
108
 */
 
109
static void print_part_info(struct partition_block *p)
 
110
{
 
111
    struct amiga_part_geometry *g;
 
112
 
 
113
    g = (struct amiga_part_geometry *)&(p->environment);
 
114
 
 
115
    bstr_print(p->drive_name);
 
116
    printf("%6d\t%6d\t",
 
117
           g->low_cyl * g->block_per_track * g->surfaces ,
 
118
           (g->high_cyl - g->low_cyl + 1) * g->block_per_track * g->surfaces - 1);
 
119
    print_disk_type(g->dos_type);
 
120
    printf("\t%5d\n", g->boot_priority);
 
121
}
 
122
 
 
123
/*
 
124
 * Search for the Rigid Disk Block. The rigid disk block is required
 
125
 * to be within the first 16 blocks of a drive, needs to have
 
126
 * the ID AMIGA_ID_RDISK ('RDSK') and needs to have a valid
 
127
 * sum-to-zero checksum
 
128
 */
 
129
struct rigid_disk_block *get_rdisk(block_dev_desc_t *dev_desc)
 
130
{
 
131
    int i;
 
132
    int limit;
 
133
    char *s;
 
134
 
 
135
    s = getenv("amiga_scanlimit");
 
136
    if (s)
 
137
        limit = simple_strtoul(s, NULL, 10);
 
138
    else
 
139
        limit = AMIGA_BLOCK_LIMIT;
 
140
 
 
141
    for (i=0; i<limit; i++)
 
142
    {
 
143
        ulong res = dev_desc->block_read(dev_desc->dev, i, 1,
 
144
                                         (ulong *)block_buffer);
 
145
        if (res == 1)
 
146
        {
 
147
            struct rigid_disk_block *trdb = (struct rigid_disk_block *)block_buffer;
 
148
            if (trdb->id == AMIGA_ID_RDISK)
 
149
            {
 
150
                PRINTF("Rigid disk block suspect at %d, checking checksum\n",i);
 
151
                if (sum_block((struct block_header *)block_buffer) == 0)
 
152
                {
 
153
                    PRINTF("FOUND\n");
 
154
                    memcpy(&rdb, trdb, sizeof(struct rigid_disk_block));
 
155
                    return (struct rigid_disk_block *)&rdb;
 
156
                }
 
157
            }
 
158
        }
 
159
    }
 
160
    PRINTF("Done scanning, no RDB found\n");
 
161
    return NULL;
 
162
}
 
163
 
 
164
/*
 
165
 * Search for boot code
 
166
 * Again, the first boot block must be located somewhere in the first 16 blocks, or rooted in the
 
167
 * Ridgid disk block
 
168
 */
 
169
 
 
170
struct bootcode_block *get_bootcode(block_dev_desc_t *dev_desc)
 
171
{
 
172
    int i;
 
173
    int limit;
 
174
    char *s;
 
175
 
 
176
    s = getenv("amiga_scanlimit");
 
177
    if (s)
 
178
        limit = simple_strtoul(s, NULL, 10);
 
179
    else
 
180
        limit = AMIGA_BLOCK_LIMIT;
 
181
 
 
182
    PRINTF("Scanning for BOOT from 0 to %d\n", limit);
 
183
 
 
184
    for (i = 0; i < limit; i++)
 
185
    {
 
186
        ulong res = dev_desc->block_read(dev_desc->dev, i, 1, (ulong *)block_buffer);
 
187
        if (res == 1)
 
188
        {
 
189
            struct bootcode_block *boot = (struct bootcode_block *)block_buffer;
 
190
            if (boot->id == AMIGA_ID_BOOT)
 
191
            {
 
192
                PRINTF("BOOT block at %d, checking checksum\n", i);
 
193
                if (sum_block((struct block_header *)block_buffer) == 0)
 
194
                {
 
195
                    PRINTF("Found valid bootcode block\n");
 
196
                    memcpy(&bootcode, boot, sizeof(struct bootcode_block));
 
197
                    return &bootcode;
 
198
                }
 
199
            }
 
200
        }
 
201
    }
 
202
 
 
203
    PRINTF("No boot code found on disk\n");
 
204
    return 0;
 
205
}
 
206
 
 
207
/*
 
208
 * Test if the given partition has an Amiga partition table/Rigid
 
209
 * Disk block
 
210
 */
 
211
int test_part_amiga(block_dev_desc_t *dev_desc)
 
212
{
 
213
    struct rigid_disk_block *rdb;
 
214
    struct bootcode_block *bootcode;
 
215
 
 
216
    PRINTF("test_part_amiga: Testing for an Amiga RDB partition\n");
 
217
 
 
218
    rdb = get_rdisk(dev_desc);
 
219
    if (rdb)
 
220
    {
 
221
        bootcode = get_bootcode(dev_desc);
 
222
        if (bootcode)
 
223
            PRINTF("test_part_amiga: bootable Amiga disk\n");
 
224
        else
 
225
            PRINTF("test_part_amiga: non-bootable Amiga disk\n");
 
226
 
 
227
        return 0;
 
228
    }
 
229
    else
 
230
    {
 
231
        PRINTF("test_part_amiga: no RDB found\n");
 
232
        return -1;
 
233
    }
 
234
 
 
235
}
 
236
 
 
237
/*
 
238
 * Find partition number partnum on the given drive.
 
239
 */
 
240
static struct partition_block *find_partition(block_dev_desc_t *dev_desc, int partnum)
 
241
{
 
242
    struct rigid_disk_block *rdb;
 
243
    struct partition_block *p;
 
244
    u32 block;
 
245
 
 
246
    PRINTF("Trying to find partition block %d\n", partnum);
 
247
    rdb = get_rdisk(dev_desc);
 
248
    if (!rdb)
 
249
    {
 
250
        PRINTF("find_partition: no rdb found\n");
 
251
        return NULL;
 
252
    }
 
253
 
 
254
    PRINTF("find_partition: Scanning partition list\n");
 
255
 
 
256
    block = rdb->partition_list;
 
257
    PRINTF("find_partition: partition list at 0x%x\n", block);
 
258
 
 
259
    while (block != 0xFFFFFFFF)
 
260
    {
 
261
        ulong res = dev_desc->block_read(dev_desc->dev, block, 1,
 
262
                                         (ulong *)block_buffer);
 
263
        if (res == 1)
 
264
        {
 
265
            p = (struct partition_block *)block_buffer;
 
266
            if (p->id == AMIGA_ID_PART)
 
267
            {
 
268
                PRINTF("PART block suspect at 0x%x, checking checksum\n",block);
 
269
                if (sum_block((struct block_header *)p) == 0)
 
270
                {
 
271
                    if (partnum == 0) break;
 
272
                    else
 
273
                    {
 
274
                        partnum--;
 
275
                        block = p->next;
 
276
                    }
 
277
                }
 
278
            } else block = 0xFFFFFFFF;
 
279
        } else block = 0xFFFFFFFF;
 
280
    }
 
281
 
 
282
    if (block == 0xFFFFFFFF)
 
283
    {
 
284
        PRINTF("PART block not found\n");
 
285
        return NULL;
 
286
    }
 
287
 
 
288
    return (struct partition_block *)block_buffer;
 
289
}
 
290
 
 
291
/*
 
292
 * Get info about a partition
 
293
 */
 
294
int get_partition_info_amiga (block_dev_desc_t *dev_desc, int part, disk_partition_t *info)
 
295
{
 
296
    struct partition_block *p = find_partition(dev_desc, part-1);
 
297
    struct amiga_part_geometry *g;
 
298
    u32 disk_type;
 
299
 
 
300
    if (!p) return -1;
 
301
 
 
302
    g = (struct amiga_part_geometry *)&(p->environment);
 
303
    info->start = g->low_cyl  * g->block_per_track * g->surfaces;
 
304
    info->size  = (g->high_cyl - g->low_cyl + 1) * g->block_per_track * g->surfaces - 1;
 
305
    info->blksz = rdb.block_bytes;
 
306
    bcpl_strcpy(info->name, p->drive_name);
 
307
 
 
308
 
 
309
    disk_type = g->dos_type;
 
310
 
 
311
    info->type[0] = (disk_type & 0xFF000000)>>24;
 
312
    info->type[1] = (disk_type & 0x00FF0000)>>16;
 
313
    info->type[2] = (disk_type & 0x0000FF00)>>8;
 
314
    info->type[3] = '\\';
 
315
    info->type[4] = (disk_type & 0x000000FF) + '0';
 
316
    info->type[5] = 0;
 
317
 
 
318
    return 0;
 
319
}
 
320
 
 
321
void print_part_amiga (block_dev_desc_t *dev_desc)
 
322
{
 
323
    struct rigid_disk_block *rdb;
 
324
    struct bootcode_block *boot;
 
325
    struct partition_block *p;
 
326
    u32 block;
 
327
    int i = 1;
 
328
 
 
329
    rdb = get_rdisk(dev_desc);
 
330
    if (!rdb)
 
331
    {
 
332
        PRINTF("print_part_amiga: no rdb found\n");
 
333
        return;
 
334
    }
 
335
 
 
336
    PRINTF("print_part_amiga: Scanning partition list\n");
 
337
 
 
338
    block = rdb->partition_list;
 
339
    PRINTF("print_part_amiga: partition list at 0x%x\n", block);
 
340
 
 
341
    printf("Summary:  DiskBlockSize: %d\n"
 
342
           "          Cylinders    : %d\n"
 
343
           "          Sectors/Track: %d\n"
 
344
           "          Heads        : %d\n\n",
 
345
           rdb->block_bytes, rdb->cylinders, rdb->sectors,
 
346
           rdb->heads);
 
347
 
 
348
    printf("                 First   Num. \n"
 
349
           "Nr.  Part. Name  Block   Block  Type        Boot Priority\n");
 
350
 
 
351
    while (block != 0xFFFFFFFF)
 
352
    {
 
353
        ulong res;
 
354
 
 
355
        PRINTF("Trying to load block #0x%X\n", block);
 
356
 
 
357
        res = dev_desc->block_read(dev_desc->dev, block, 1,
 
358
                                   (ulong *)block_buffer);
 
359
        if (res == 1)
 
360
        {
 
361
            p = (struct partition_block *)block_buffer;
 
362
            if (p->id == AMIGA_ID_PART)
 
363
            {
 
364
                PRINTF("PART block suspect at 0x%x, checking checksum\n",block);
 
365
                if (sum_block((struct block_header *)p) == 0)
 
366
                {
 
367
                    printf("%-4d ", i); i++;
 
368
                    print_part_info(p);
 
369
                    block = p->next;
 
370
                }
 
371
            } else block = 0xFFFFFFFF;
 
372
        } else block = 0xFFFFFFFF;
 
373
    }
 
374
 
 
375
    boot = get_bootcode(dev_desc);
 
376
    if (boot)
 
377
    {
 
378
        printf("Disk is bootable\n");
 
379
    }
 
380
}
 
381
 
 
382
#endif