Subversion Repositories shark

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
 
22
/***************************************
23
 
24
  CVS :        $Id: lodsk.c,v 1.1.1.1 2002-03-29 14:12:49 pj Exp $
25
 
26
  Revision:    $Revision: 1.1.1.1 $
27
 
28
  Last update: $Date: 2002-03-29 14:12:49 $
29
 
30
  This module is used by block device sub-system to scan a physical
31
  hard disk to find logical layout (partition scheme).
32
 
33
***************************************/
34
 
35
/*
36
 * Copyright (C) 1999 Massimiliano Giorgi
37
 *
38
 * This program is free software; you can redistribute it and/or modify
39
 * it under the terms of the GNU General Public License as published by
40
 * the Free Software Foundation; either version 2 of the License, or
41
 * (at your option) any later version.
42
 *
43
 * This program is distributed in the hope that it will be useful,
44
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
46
 * GNU General Public License for more details.
47
 *
48
 * You should have received a copy of the GNU General Public License
49
 * along with this program; if not, write to the Free Software
50
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
51
 *
52
 */
53
 
54
#include "glue.h"
55
 
56
#include "bdev.h"
57
#include "sysind.h"
58
#include "lodsk.h"
59
 
60
/*+ Log Level used to report an error +*/
61
#define LODSKERRLOG KERN_ERR
62
 
63
/*+ Log level used to inform +*/
64
#define LODSKLOG    KERN_NOTICE
65
 
66
/*+ An aligned buffer for data I/O +*/
67
static __uint8_t  buffer[512] __attribute__ ((aligned(4)));
68
 
69
/*++++++++++++++++++++++++++++++++++++++
70
 
71
  This function convert a physical partion structure to a partition
72
  structure (the difference is that the physical partition structure
73
  has a "strange" layout and must be parsed to find actually values that
74
  are saved into a partition structure).
75
 
76
  struct phpartition *ph
77
    physical partition to parse
78
 
79
  struct partition *lo
80
    values are stored into this structure
81
  ++++++++++++++++++++++++++++++++++++++*/
82
 
83
static void partph2lo(struct phpartition *ph,struct partition *lo)
84
{
85
  lo->boot_ind=((ph->boot_ind&0x80)?1:0);
86
  lo->sys_ind=ph->sys_ind;
87
  lo->rel_sect=ph->rel_sect;
88
  lo->nr_sects=ph->nr_sects;
89
  /**/
90
  lo->st_head=ph->st_h;
91
  lo->st_sect=ph->st_s&0x3f;
92
  lo->st_cyl=(__uint16_t)ph->st_c|(((__uint16_t)ph->st_s&0xc0)<<2);
93
  lo->en_head=ph->st_h;
94
  lo->en_sect=ph->en_s&0x3f;
95
  lo->en_cyl=(__uint16_t)ph->en_c|(((__uint16_t)ph->en_s&0xc0)<<2);
96
}
97
 
98
/*++++++++++++++++++++++++++++++++++++++
99
 
100
  Find if a partition is an extended partition.
101
 
102
  #define is_extended_partition
103
    return 0 if no, other value if yes
104
 
105
  sys_ind
106
    "system indicator" for that partition
107
  ++++++++++++++++++++++++++++++++++++++*/
108
 
109
#define is_extended_partition(sys_ind) (   \
110
  (sys_ind) == DOS_EXTENDED_PARTITION ||   \
111
  (sys_ind) == WIN98_EXTENDED_PARTITION || \
112
  (sys_ind) == LINUX_EXTENDED_PARTITION    \
113
)
114
 
115
/*++++++++++++++++++++++++++++++++++++++
116
 
117
  Scan recursiverly an extended partition to find other partition (this
118
  function suppose an IBM PC hard disk architecture).
119
  When a new partition is found the callback function is called.
120
 
121
  int extended_partition
122
    return 0 on success, other value on error
123
 
124
  char *lname
125
    it is the name of the physical disk; for informational purpose only
126
    (for example "hda").
127
 
128
  __dev_t device
129
    it's the device to scan
130
 
131
  lodsk_callback_func func
132
    it's the callback function to call when a new partition is found
133
 
134
  void *data
135
    this is opaque data passed to the callback function
136
 
137
  __blkcnt_t psect
138
    is the starting block (sector) number for this extended partition
139
 
140
  __blkcnt_t psize
141
    is the size in blocks of this extended partition
142
 
143
  int showinfo
144
    show information with printk()
145
  ++++++++++++++++++++++++++++++++++++++*/
146
 
147
/* this routine is from Linux 2.2.9 (modificated to run into S.Ha.R.K.) */
148
 
149
static int extended_partition(char *lname, __dev_t device,
150
                              lodsk_callback_func func, void *data,
151
                              __blkcnt_t psect, __blkcnt_t psize,
152
                              char *infobuffer, int nextid)
153
{
154
  char name[MAXLODSKNAME];
155
  struct phpartition *ppar;
156
  struct partition lpar;
157
  struct lodskinfo info;
158
  __blkcnt_t stpsect=psect;
159
  int ret;
160
  int i;
161
  int counter=5;
162
  int first=1;
163
 
164
  //if (phdsk_sectorsize(pdisk)!=512) return -1;
165
 
166
  for (;;) {
167
 
168
    //cprintf("reading block %li\n",(long)psect);
169
 
170
    ret=bdev_read(device,psect,buffer);
171
    if (ret) return -1;
172
    //cprintf("read block %li\n",(long)psect);
173
    if (*(__uint16_t*)(buffer+0x1fe)!=MSDOS_LABEL_MAGIC) return -1;
174
    //cprintf("ok sector\n");
175
 
176
    ppar=(struct phpartition*)(buffer+0x1be);
177
 
178
    /*
179
     * Usually, the first entry is the real data partition,
180
     * the 2nd entry is the next extended partition, or empty,
181
     * and the 3rd and 4th entries are unused.
182
     * However, DRDOS sometimes has the extended partition as
183
     * the first entry (when the data partition is empty),
184
     * and OS/2 seems to use all four entries.
185
     */
186
 
187
    /*
188
     * First process the data partition(s)
189
     */
190
 
191
    for (i=0; i<4; i++, ppar++) {
192
      partph2lo(ppar,&lpar);
193
 
194
      /*
195
        cprintf("-- %i --\n",i+x);
196
        cprintf("c: %4i h: %4i s: %4i\n",lpar.st_cyl,lpar.st_head,lpar.st_sect);
197
        cprintf("c: %4i h: %4i s: %4i\n",lpar.en_cyl,lpar.en_head,lpar.en_sect);
198
        cprintf("sys: %02x relsec: %li  num sect: %li\n",
199
        lpar.sys_ind,lpar.rel_sect,lpar.nr_sects);
200
        */
201
 
202
      if (!lpar.nr_sects || is_extended_partition(lpar.sys_ind))
203
        continue;
204
 
205
      /* Check the 3rd and 4th entries -
206
         these sometimes contain random garbage */
207
      if (i >= 2
208
          && lpar.rel_sect + lpar.nr_sects > psize
209
          && (psect + lpar.rel_sect < psect ||
210
              psect + lpar.rel_sect + lpar.nr_sects >
211
              psect + psize))
212
        continue;
213
 
214
      sprintf(name,"%s%i ",lname,counter++);
215
 
216
      info.fs_ind=lpar.sys_ind;
217
      info.start=psect+lpar.rel_sect;
218
      info.size=lpar.nr_sects;
219
      ret=func(nextid++,&info,data);
220
 
221
      if (infobuffer!=NULL&&first) strcat(infobuffer,"< ");
222
      first=0;
223
      if (infobuffer) strcat(infobuffer,name);
224
    }
225
 
226
    ppar=(struct phpartition*)(buffer+0x1be);
227
 
228
    /*
229
     * Next, process the (first) extended partition, if present.
230
     * (So far, there seems to be no reason to make
231
     *  extended_partition()  recursive and allow a tree
232
     *  of extended partitions.)
233
     * It should be a link to the next logical partition.
234
     * Create a minor for this just long enough to get the next
235
     * partition table.  The minor will be reused for the next
236
     * data partition.
237
     */
238
    for (i=0; i<4; i++, ppar++)
239
      if(ppar->nr_sects && is_extended_partition(ppar->sys_ind))
240
        break;
241
    if (i == 4)
242
      break;     /* nothing left to do, go to the end*/
243
 
244
    psect=stpsect+ppar->rel_sect;
245
    psize=ppar->nr_sects;
246
  }
247
 
248
  if (infobuffer!=NULL&&!first) strcat(infobuffer,"> ");
249
  return nextid;
250
}
251
 
252
//extern int ide_check_geometry(int pdisk, __uint8_t *buffer);
253
 
254
/*++++++++++++++++++++++++++++++++++++++
255
 
256
  This function is called to scan a physical hard disk to find its logical
257
  structure (IBM PC hard disk harchitecture is supposed).
258
 
259
  int msdos_partition
260
    return 0 on success, other value on error
261
 
262
  char *lname
263
    name to use if information is shown (for example "hdc")
264
 
265
  __dev_t device
266
    device to scan
267
 
268
  lodsk_callback_func func
269
    callback function to call when a partition is found
270
 
271
  void *data
272
    opaque data passed to the callback function
273
 
274
  int showinfo
275
    is true if informations will be displayed
276
  ++++++++++++++++++++++++++++++++++++++*/
277
 
278
/* this routine is from Linux 2.2.9 (modificated to run into S.Ha.R.K.) */
279
 
280
static int ibmpc_arch_scan(char *lname, __dev_t device,
281
                           lodsk_callback_func func,
282
                           void *data, char *infobuffer)
283
{
284
  struct lodskinfo info;
285
  char name[MAXLODSKNAME];
286
  struct phpartition *ppar;
287
  struct partition lpar;
288
  int i;
289
  int ret;
290
  int nextid;
291
 
292
  ret=bdev_read(device,0,buffer);
293
  if (ret) {
294
    cprintf("XXXXXXXXXXXXXXXX");
295
    return -1;
296
  }
297
 
298
  //if (phdsk_sectorsize(pdisk)!=512) return -1;
299
 
300
  if (*(__uint16_t*)(buffer+0x1fe)!=MSDOS_LABEL_MAGIC) return -1;
301
 
302
  ppar=(struct phpartition*)(buffer+0x1be);
303
 
304
  nextid=5;
305
  for (i=0;i<4;i++,ppar+=1) {
306
    partph2lo(ppar,&lpar);
307
 
308
    /*
309
    cprintf("-- %i --\n",i);
310
    cprintf("c: %4i h: %4i s: %4i\n",lpar.st_cyl,lpar.st_head,lpar.st_sect);
311
    cprintf("c: %4i h: %4i s: %4i\n",lpar.en_cyl,lpar.en_head,lpar.en_sect);
312
    cprintf("sys: %02x relsec: %li  num sect: %li\n",
313
              lpar.sys_ind,lpar.rel_sect,lpar.nr_sects);
314
    */
315
 
316
    /*
317
    if (phdsk[pdisk].ide_check_geom&&i==0) {
318
      ide_check_geometry(pdisk,buffer);
319
    }
320
    */
321
 
322
    if (!lpar.nr_sects) continue;
323
    if (is_extended_partition(lpar.sys_ind)) {
324
      nextid=extended_partition(lname,device,func,data,
325
                         lpar.rel_sect,lpar.nr_sects,infobuffer,nextid);
326
      if (nextid<0) return -1;
327
    } else {
328
      sprintf(name,"%s%i ",lname,i+1);
329
 
330
      info.fs_ind=lpar.sys_ind;
331
      info.start=lpar.rel_sect;
332
      info.size=lpar.nr_sects;
333
      ret=func(i+1,&info,data);      
334
 
335
      if (infobuffer) strcat(infobuffer,name);
336
 
337
      if (ret) return 0;
338
    }    
339
  }
340
 
341
  return 0;
342
}
343
 
344
/*++++++++++++++++++++++++++++++++++++++
345
 
346
  This function scan a physical hard disk for logical structure; actually
347
  only IBM PC hard disk architecture is recognized.
348
 
349
  int lodsk_scan
350
    return 0 on success, other value on error
351
 
352
  __dev_t device
353
    device to scan
354
 
355
  lodsk_callback_func func
356
    callback function to call when a new partition is found
357
 
358
  void *data
359
    opaque data passed to the callback function
360
 
361
  int showinfo
362
    if information must be displayed
363
 
364
  char *lname
365
    logical name, for information only (example "hda")
366
  ++++++++++++++++++++++++++++++++++++++*/
367
 
368
int lodsk_scan(__dev_t device, lodsk_callback_func func,
369
               void *data, int showinfo, char *lname)
370
{
371
  char buffer[1024]; /* DANGER!!! */
372
  int ret;
373
 
374
  if (showinfo) sprintf(buffer,"%s: ",lname);
375
  ret=ibmpc_arch_scan(lname,device,func,data,showinfo?buffer:NULL);
376
  if (showinfo) printk(KERN_INFO "%s",buffer);
377
  return ret;
378
}
379
 
380
 
381