Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
46 theseven 1
/***************************************************************************
2
 *             __________               __   ___.
3
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7
 *                     \/            \/     \/    \/            \/
8
 * $Id: disk.c 26629 2010-06-06 13:28:13Z gevaerts $
9
 *
10
 * Copyright (C) 2002 by Björn Stenberg
11
 *
12
 * This program is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU General Public License
14
 * as published by the Free Software Foundation; either version 2
15
 * of the License, or (at your option) any later version.
16
 *
17
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18
 * KIND, either express or implied.
19
 *
20
 ****************************************************************************/
49 theseven 21
#include "global.h"
22
#include "thread.h"
46 theseven 23
#include <stdio.h>
24
#include "storage.h"
25
#include "debug.h"
26
#include "fat.h"
27
#ifdef HAVE_HOTSWAP
28
#include "dir.h" /* for release_dirs() */
29
#include "file.h" /* for release_files() */
30
#endif
31
#include "disk.h"
58 theseven 32
#include "util.h"
46 theseven 33
#include <string.h>
34
 
35
/* Partition table entry layout:
36
   -----------------------
37
   0: 0x80 - active
38
   1: starting head
39
   2: starting sector
40
   3: starting cylinder
41
   4: partition type
42
   5: end head
43
   6: end sector
44
   7: end cylinder
45
   8-11: starting sector (LBA)
46
   12-15: nr of sectors in partition
47
*/
48
 
49
#define BYTES2INT32(array,pos)                  \
50
    ((long)array[pos] | ((long)array[pos+1] << 8 ) |        \
51
     ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
52
 
53
static const unsigned char fat_partition_types[] = {
54
    0x0b, 0x1b, /* FAT32 + hidden variant */
55
    0x0c, 0x1c, /* FAT32 (LBA) + hidden variant */
56
#ifdef HAVE_FAT16SUPPORT
57
    0x04, 0x14, /* FAT16 <= 32MB + hidden variant */
58
    0x06, 0x16, /* FAT16  > 32MB + hidden variant */
59
    0x0e, 0x1e, /* FAT16 (LBA) + hidden variant */
60
#endif
61
};
62
 
63
static struct partinfo part[NUM_DRIVES*4]; /* space for 4 partitions on 2 drives */
64
static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */
65
static struct mutex disk_mutex;
66
 
67
struct partinfo* disk_init(IF_MD_NONVOID(int drive))
68
{
69
    int i;
70
#ifdef HAVE_MULTIDRIVE
47 farthen 71
    /* For each drive, start at a different position, in order not to destroy
72
       the first entry of drive 0.
46 theseven 73
       That one is needed to calculate config sector position. */
74
    struct partinfo* pinfo = &part[drive*4];
75
    if ((size_t)drive >= sizeof(part)/sizeof(*part)/4)
76
        return NULL; /* out of space in table */
77
#else
78
    struct partinfo* pinfo = part;
79
    const int drive = 0;
80
    (void)drive;
81
#endif
82
 
58 theseven 83
    unsigned char* sector = fat_get_sector_buffer();
46 theseven 84
    storage_read_sectors(IF_MD2(drive,) 0,1, sector);
85
    /* check that the boot sector is initialized */
86
    if ( (sector[510] != 0x55) ||
87
         (sector[511] != 0xaa)) {
58 theseven 88
        fat_release_sector_buffer();
50 theseven 89
        DEBUGF("Bad boot sector signature");
46 theseven 90
        return NULL;
91
    }
92
 
93
    /* parse partitions */
94
    for ( i=0; i<4; i++ ) {
95
        unsigned char* ptr = sector + 0x1be + 16*i;
96
        pinfo[i].type  = ptr[4];
97
        pinfo[i].start = BYTES2INT32(ptr, 8);
98
        pinfo[i].size  = BYTES2INT32(ptr, 12);
99
 
50 theseven 100
        DEBUGF("Part%d: Type %02x, start: %08lx size: %08lx",
46 theseven 101
               i,pinfo[i].type,pinfo[i].start,pinfo[i].size);
102
 
103
        /* extended? */
104
        if ( pinfo[i].type == 5 ) {
105
            /* not handled yet */
106
        }
107
    }
58 theseven 108
    fat_release_sector_buffer();
46 theseven 109
    return pinfo;
110
}
111
 
112
struct partinfo* disk_partinfo(int partition)
113
{
114
    return &part[partition];
115
}
116
 
117
void disk_init_subsystem(void)
118
{
119
   mutex_init(&disk_mutex);
120
}
121
 
122
int disk_mount_all(void)
123
{
124
    int mounted=0;
125
    int i;
126
 
127
#ifdef HAVE_HOTSWAP
128
    mutex_lock(&disk_mutex);
129
#endif
130
 
131
    fat_init(); /* reset all mounted partitions */
132
    for (i=0; i<NUM_VOLUMES; i++)
133
        vol_drive[i] = -1; /* mark all as unassigned */
134
 
135
#ifndef HAVE_MULTIDRIVE
136
    mounted = disk_mount(0);
137
#else
138
    for(i=0;i<NUM_DRIVES;i++)
139
    {
140
#ifdef HAVE_HOTSWAP
141
        if (storage_present(i))
142
#endif
143
            mounted += disk_mount(i); 
144
    }
145
#endif
146
 
147
#ifdef HAVE_HOTSWAP
148
    mutex_unlock(&disk_mutex);
149
#endif
150
    return mounted;
151
}
152
 
153
static int get_free_volume(void)
154
{
155
    int i;
156
    for (i=0; i<NUM_VOLUMES; i++)
157
    {
158
        if (vol_drive[i] == -1) /* unassigned? */
159
            return i;
160
    }
161
 
162
    return -1; /* none found */
163
}
164
 
165
int disk_mount(int drive)
166
{
167
    int i;
168
    int mounted = 0; /* reset partition-on-drive flag */
169
    int volume;
170
    struct partinfo* pinfo;
171
 
172
#ifdef HAVE_HOTSWAP
173
    mutex_lock(&disk_mutex);
174
#endif
175
 
176
    volume = get_free_volume();
177
    pinfo = disk_init(IF_MD(drive));
178
 
179
    if (pinfo == NULL)
180
    {
181
#ifdef HAVE_HOTSWAP
182
        mutex_unlock(&disk_mutex);
183
#endif
184
        return 0;
185
    }
186
    for (i = 0; volume != -1 && i<4 && mounted<NUM_VOLUMES_PER_DRIVE; i++)
187
    {
188
        if (memchr(fat_partition_types, pinfo[i].type,
189
                   sizeof(fat_partition_types)) == NULL)
190
            continue;  /* not an accepted partition type */
191
 
192
        if (!fat_mount(IF_MV2(volume,) IF_MD2(drive,) pinfo[i].start))
193
        {
194
            mounted++;
195
            vol_drive[volume] = drive; /* remember the drive for this volume */
196
            volume = get_free_volume(); /* prepare next entry */
197
        }
198
    }
199
 
200
    if (mounted == 0 && volume != -1) /* none of the 4 entries worked? */
201
    {   /* try "superfloppy" mode */
50 theseven 202
        DEBUGF("No partition found, trying to mount sector 0.");
46 theseven 203
        if (!fat_mount(IF_MV2(volume,) IF_MD2(drive,) 0))
204
        {
205
            mounted = 1;
206
            vol_drive[volume] = drive; /* remember the drive for this volume */
207
        }
208
    }
209
#ifdef HAVE_HOTSWAP
210
    mutex_unlock(&disk_mutex);
211
#endif
212
    return mounted;
213
}
214
 
215
#ifdef HAVE_HOTSWAP
216
int disk_unmount(int drive)
217
{
218
    int unmounted = 0;
219
    int i;
220
    mutex_lock(&disk_mutex);
221
    for (i=0; i<NUM_VOLUMES; i++)
222
    {
223
        if (vol_drive[i] == drive)
224
        {   /* force releasing resources */
225
            vol_drive[i] = -1; /* mark unused */
226
            unmounted++;
227
            release_files(i);
228
            release_dirs(i);
229
            fat_unmount(i, false);
230
        }
231
    }
232
    mutex_unlock(&disk_mutex);
233
 
234
    return unmounted;
235
}
236
#endif /* #ifdef HAVE_HOTSWAP */