~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to debian/grub-extras/ntldr-img/utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2010-01-11 11:12:55 UTC
  • mfrom: (17.3.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100111111255-lr8ebkqw5x41gq6j
Tags: 1.98~20100101-1ubuntu1
* Resynchronise with Debian. Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Conflict with grub (<< 0.97-54) as well as grub-legacy.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu. Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed. If it is, show the
    menu, otherwise boot immediately. If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt. Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - If the environment variable "quiet" is set to something other than 0,
    suppress progress messages as the kernel and initrd load. Set this for
    non-recovery kernel menu entries.
  - Add GRUB_DEFAULT=saved, as well as grub-set-default and grub-reboot
    utilities. Provides functionality essentially equivalent to GRUB
    Legacy's savedefault.
  - Keep the loopback file open so that subsequent changes to the "root"
    environment variable don't affect it.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Handle RAID devices containing virtio components.
* Update savedefault patch from current Bazaar branch, fixing grub-reboot
  to have distinct behaviour from grub-set-default (LP: #497326).
* Fix grub-mkisofs compilation error with FORTIFY_SOURCE.
* Convert recordfail boilerplate in each menu entry to use a function.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  GRUB Utilities --  Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
3
 
 *  Copyright (C) 2007 Bean (bean123@126.com)
4
 
 *
5
 
 *  This program is free software; you can redistribute it and/or modify
6
 
 *  it under the terms of the GNU General Public License as published by
7
 
 *  the Free Software Foundation; either version 2 of the License, or
8
 
 *  (at your option) any later version.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 
 */
19
 
 
20
 
#ifdef LINUX
21
 
 
22
 
#define _FILE_OFFSET_BITS 64    // This is required to enable 64-bit off_t
23
 
#include <unistd.h>
24
 
 
25
 
#endif
26
 
 
27
 
#include <stdio.h>
28
 
#include <fcntl.h>
29
 
 
30
 
#include "utils.h"
31
 
 
32
 
static unsigned char ebuf[512];
33
 
 
34
 
#if defined(WIN32)
35
 
 
36
 
#ifdef __GNUC__                         // Mingw or Cygwin
37
 
 
38
 
#define u_off_t         off64_t
39
 
#define u_lseek         lseek64
40
 
 
41
 
#else
42
 
 
43
 
#define u_off_t         __int64
44
 
#define u_lseek         _lseeki64
45
 
 
46
 
#endif
47
 
 
48
 
#else
49
 
 
50
 
#define u_off_t         off_t           // In FreeBSD, off_t is 64-bit !
51
 
#define u_lseek         lseek
52
 
 
53
 
#endif
54
 
 
55
 
int go_sect(int hd,unsigned long sec)
56
 
{
57
 
  // Test if 64-bit seek is supported
58
 
  if (sizeof(u_off_t)>=8)
59
 
    {
60
 
      u_off_t bs,rs;
61
 
 
62
 
      bs=sec;
63
 
      bs<<=9;
64
 
      rs=u_lseek(hd,bs,SEEK_SET);
65
 
      return (bs!=rs);
66
 
    }
67
 
  else
68
 
    {
69
 
      unsigned long bs[2];
70
 
 
71
 
      bs[0]=sec<<9;
72
 
      bs[1]=sec>>23;
73
 
      if (bs[1])
74
 
        return 1;
75
 
      return (lseek(hd,bs[0],SEEK_SET)!=bs[0]);
76
 
    }
77
 
}
78
 
 
79
 
// Partition enumerator
80
 
// xe->cur is the current partition number, before the first call to xd_enum,
81
 
// it should be set to 0xFF
82
 
// xe->nxt is the target partition number, if it equals 0xFF, it means enumerate
83
 
// all partitions, otherwise, it means jump to the specific partition.
84
 
int xd_enum(int hd,xde_t* xe)
85
 
{
86
 
  int nn=512,kk=1,cc;
87
 
 
88
 
  for (cc=xe->cur;;)
89
 
    {
90
 
      if (cc==0xFF)
91
 
        {
92
 
          unsigned long pt[4][2];
93
 
          int i,j,np;
94
 
 
95
 
          if (go_sect(hd,0))
96
 
            return 1;
97
 
          if (read(hd,ebuf,nn)!=nn)
98
 
            return 1;
99
 
          if (valueat(ebuf,0x1FE,unsigned short)!=0xAA55)
100
 
            return 1;
101
 
          np=0;
102
 
          for (i=0x1BE;i<0x1FE;i+=16)
103
 
            if (ebuf[i+4])
104
 
              {
105
 
                if ((pt[np][1]=valueat(ebuf,i+12,unsigned long))==0)
106
 
                  return 1;
107
 
                pt[np++][0]=valueat(ebuf,i+8,unsigned long);
108
 
              }
109
 
          if (np==0)
110
 
            return 1;
111
 
          // Sort partition table base on start address
112
 
          for (i=0;i<np-1;i++)
113
 
            {
114
 
              int k=i;
115
 
              for (j=i+1;j<np;j++)
116
 
                if (pt[k][0]>pt[j][0]) k=j;
117
 
              if (k!=i)
118
 
                {
119
 
                  unsigned long tt;
120
 
 
121
 
                  tt=pt[i][0];
122
 
                  pt[i][0]=pt[k][0];
123
 
                  pt[k][0]=tt;
124
 
                  tt=pt[i][1];
125
 
                  pt[i][1]=pt[k][1];
126
 
                  pt[k][1]=tt;
127
 
                }
128
 
            }
129
 
          // Should have space for MBR
130
 
          if (pt[0][0]==0)
131
 
            return 1;
132
 
          // Check for partition overlap
133
 
          for (i=0;i<np-1;i++)
134
 
            if (pt[i][0]+pt[i][1]>pt[i+1][0])
135
 
              return 1;
136
 
          cc=0;
137
 
        }
138
 
      else if (kk)
139
 
        cc++;
140
 
      if ((unsigned char)cc>xe->nxt)
141
 
        return 1;
142
 
      if (cc<4)
143
 
        {
144
 
          if (xe->nxt<4)
145
 
            {
146
 
              // Empty partition
147
 
              if (! ebuf[xe->nxt*16+4+0x1BE])
148
 
                return 1;
149
 
              xe->cur=xe->nxt;
150
 
              xe->dfs=ebuf[xe->nxt*16+4+0x1BE];
151
 
              xe->bse=valueat(ebuf,xe->nxt*16+8+0x1BE,unsigned long);
152
 
              xe->len=valueat(ebuf,xe->nxt*16+12+0x1BE,unsigned long);
153
 
              return 0;
154
 
            }
155
 
          else if (xe->nxt!=0xFF)
156
 
            cc=4;
157
 
          else while (cc<4)
158
 
            {
159
 
              if (ebuf[cc*16+4+0x1BE])
160
 
                {
161
 
                  xe->cur=cc;
162
 
                  xe->dfs=ebuf[cc*16+4+0x1BE];
163
 
                  xe->bse=valueat(ebuf,cc*16+8+0x1BE,unsigned long);
164
 
                  xe->len=valueat(ebuf,cc*16+12+0x1BE,unsigned long);
165
 
                  return 0;
166
 
                }
167
 
              cc++;
168
 
            }
169
 
        }
170
 
      if ((cc==4) && (kk))
171
 
        {
172
 
          int i;
173
 
 
174
 
          // Scan for extended partition
175
 
          for (i=0;i<4;i++)
176
 
            if ((ebuf[i*16+4+0x1BE]==5) || (ebuf[i*16+4+0x1BE]==0xF)) break;
177
 
          if (i==4)
178
 
            return 1;
179
 
          xe->ebs=xe->bse=valueat(ebuf,i*16+8+0x1BE,unsigned long);
180
 
        }
181
 
      else
182
 
        {
183
 
          // Is end of extended partition chain ?
184
 
          if ((ebuf[4+0x1CE]!=0x5) && (ebuf[4+0x1CE]!=0xF) ||
185
 
              (valueat(ebuf,8+0x1CE,unsigned long)==0))
186
 
            return 1;
187
 
          xe->bse=xe->ebs+valueat(ebuf,8+0x1CE,unsigned long);
188
 
        }
189
 
      {
190
 
        int r;
191
 
 
192
 
        while (1)
193
 
          {
194
 
            if (go_sect(hd,xe->bse))
195
 
              return 1;
196
 
 
197
 
            if (read(hd,ebuf,nn)!=nn)
198
 
              return 1;
199
 
 
200
 
            if (valueat(ebuf,0x1FE,unsigned short)!=0xAA55)
201
 
              return 1;
202
 
 
203
 
            if ((ebuf[4+0x1BE]==5) || (ebuf[4+0x1BE]==0xF))
204
 
              if (valueat(ebuf,8+0x1BE,unsigned long)==0)
205
 
                return 1;
206
 
              else
207
 
                {
208
 
                  xe->bse=xe->ebs+valueat(ebuf,8+0x1BE,unsigned long);
209
 
                  continue;
210
 
                }
211
 
            break;
212
 
          }
213
 
        kk=(ebuf[4+0x1BE]!=0);
214
 
        if ((kk) && ((xe->nxt==0xFF) || (cc==xe->nxt)))
215
 
          {
216
 
            xe->cur=cc;
217
 
            xe->dfs=ebuf[4+0x1BE];
218
 
            xe->bse+=valueat(ebuf,8+0x1BE,unsigned long);
219
 
            xe->len=valueat(ebuf,12+0x1BE,unsigned long);
220
 
            return 0;
221
 
          }
222
 
      }
223
 
    }
224
 
}
225
 
 
226
 
#define EXT2_SUPER_MAGIC      0xEF53
227
 
 
228
 
int mbr_nhd, mbr_spt;
229
 
 
230
 
void split_chs(unsigned char* chs,unsigned long* c,unsigned long* h,unsigned long* s)
231
 
{
232
 
  *h=chs[0];
233
 
  *s=(chs[1] & 0x3F)-1;
234
 
  *c=((unsigned long)(chs[1]>>6))*256+chs[2];
235
 
}
236
 
 
237
 
int chk_chs(unsigned long nhd,unsigned long spt,unsigned long lba,unsigned char* chs)
238
 
{
239
 
  unsigned long c,h,s;
240
 
 
241
 
  split_chs(chs,&c,&h,&s);
242
 
  if (c==0x3FF)
243
 
    return ((nhd==h+1) && (spt==s+1));
244
 
  else
245
 
    return (c*nhd*spt+h*spt+s==lba);
246
 
}
247
 
 
248
 
int chk_mbr(unsigned char* buf)
249
 
{
250
 
  unsigned long nhd,spt,a1,a2,c2,h2,s2;
251
 
  int i;
252
 
 
253
 
  i=0x1BE;
254
 
  while ((i<0x1FE) && (buf[i+4]==0))
255
 
    i+=16;
256
 
  if (i>=0x1FE)
257
 
    return 0;
258
 
  a1=valueat(buf[i],8,unsigned long);
259
 
  a2=a1+valueat(buf[i],12,unsigned long)-1;
260
 
  if (a1>=a2)
261
 
    return 0;
262
 
  split_chs(buf+i+5,&c2,&h2,&s2);
263
 
  if (c2==0x3FF)
264
 
    {
265
 
      nhd=h2+1;
266
 
      spt=s2+1;
267
 
      if (! chk_chs(nhd,spt,a1,buf+i+1))
268
 
        return 0;
269
 
    }
270
 
  else
271
 
    {
272
 
      unsigned long c1,h1,s1;
273
 
      long n1,n2;
274
 
 
275
 
      split_chs(buf+i+1,&c1,&h1,&s1);
276
 
      if ((c1==0x3FF) || (c1>c2))
277
 
        return 0;
278
 
      n1=(long)(c1*a2)-(long)(c2*a1)-(long)(c1*s2)+(long)(c2*s1);
279
 
      n2=(long)(c1*h2)-(long)(c2*h1);
280
 
      if (n2<0)
281
 
        {
282
 
          n2=-n2;
283
 
          n1=-n1;
284
 
        }
285
 
      if ((n2==0) || (n1<=0) || (n1 % n2))
286
 
        return 0;
287
 
      spt=(unsigned long)(n1/n2);
288
 
      if (c2)
289
 
        {
290
 
          n1=(long)a2-(long)s2-(long)(h2*spt);
291
 
          n2=(long)(c2*spt);
292
 
          if ((n2==0) || (n1<=0) || (n1 % n2))
293
 
            return 0;
294
 
          nhd=(unsigned long)(n1/n2);
295
 
        }
296
 
      else
297
 
        nhd=h2+1;
298
 
    }
299
 
  if ((nhd==0) || (nhd>255) || (spt==0) || (spt>63))
300
 
    return 0;
301
 
  i+=16;
302
 
  while (i<0x1FE)
303
 
    {
304
 
      if (buf[i+4])
305
 
        {
306
 
          if ((! chk_chs(nhd,spt,valueat(buf[i],8,unsigned long),buf+i+1)) ||
307
 
              (! chk_chs(nhd,spt,valueat(buf[i],8,unsigned long)+valueat(buf[i],12,unsigned long)-1,buf+i+5)))
308
 
            return 0;
309
 
        }
310
 
      i+=16;
311
 
    }
312
 
  mbr_nhd=(int)nhd;
313
 
  mbr_spt=(int)spt;
314
 
  return 1;
315
 
}
316
 
 
317
 
int get_fstype(unsigned char* buf)
318
 
{
319
 
  if (chk_mbr(buf))
320
 
    return FST_MBR;
321
 
 
322
 
  // The first sector of EXT2 might not contain the 0xAA55 signature
323
 
  if (valueat(buf[1024],56,unsigned short)==EXT2_SUPER_MAGIC)
324
 
    return FST_EXT2;
325
 
  if (valueat(buf[0],0x1FE,unsigned short)!=0xAA55)
326
 
    return FST_OTHER;
327
 
  if (! strncmp(&buf[0x36],"FAT",3))
328
 
    return ((buf[0x26]==0x28) || (buf[0x26]==0x29))?FST_FAT16:FST_OTHER;
329
 
  if (! strncmp(&buf[0x52],"FAT32",5))
330
 
    return ((buf[0x42]==0x28) || (buf[0x42]==0x29))?FST_FAT32:FST_OTHER;
331
 
  if (! strncmp(&buf[0x3],"NTFS",4))
332
 
    return ((buf[0]==0xEB) && (buf[1]==0x52))?FST_NTFS:FST_OTHER;
333
 
  return FST_OTHER;
334
 
}
335
 
 
336
 
char* fst2str(int fs)
337
 
{
338
 
  switch (fs) {
339
 
  case FST_OTHER:
340
 
    return "Other";
341
 
  case FST_MBR:
342
 
    return "MBR";
343
 
  case FST_FAT16:
344
 
    return "FAT12/FAT16";
345
 
  case FST_FAT32:
346
 
    return "FAT32";
347
 
  case FST_NTFS:
348
 
    return "NTFS";
349
 
  case FST_EXT2:
350
 
    return "EXT2/EXT3";
351
 
  default:
352
 
    return "Unknown";
353
 
  }
354
 
}
355
 
 
356
 
typedef struct {
357
 
  int id;
358
 
  char* str;
359
 
} fstab_t;
360
 
 
361
 
static fstab_t fstab[]= {
362
 
  {0x1,"FAT12"},
363
 
  {0x4,"FAT16"},
364
 
  {0x5,"Extended"},
365
 
  {0x6,"FAT16B"},
366
 
  {0x7,"NTFS"},
367
 
  {0xB,"FAT32"},
368
 
  {0xC,"FAT32X"},
369
 
  {0xE,"FAT16X"},
370
 
  {0xF,"ExtendedX"},
371
 
  {0x11,"(H)FAT12"},
372
 
  {0x14,"(H)FAT16"},
373
 
  {0x16,"(H)FAT16B"},
374
 
  {0x17,"(H)NTFS"},
375
 
  {0x1B,"(H)FAT32"},
376
 
  {0x1C,"(H)FAT32X"},
377
 
  {0x1E,"(H)FAT16X"},
378
 
  {0x82,"Swap"},
379
 
  {0x83,"Ext2"},
380
 
  {0xA5,"FBSD"},
381
 
  {0,"Other"}};
382
 
 
383
 
char* dfs2str(int fs)
384
 
{
385
 
  int i;
386
 
 
387
 
  for (i=0;fstab[i].id;i++)
388
 
    if (fs==fstab[i].id)
389
 
      return fstab[i].str;
390
 
  return fstab[i].str;
391
 
}
 
1
/*
 
2
 *  GRUB Utilities --  Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
 
3
 *  Copyright (C) 2007 Bean (bean123@126.com)
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 2 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
18
 */
 
19
 
 
20
#ifdef LINUX
 
21
 
 
22
#define _FILE_OFFSET_BITS 64    // This is required to enable 64-bit off_t
 
23
#include <unistd.h>
 
24
 
 
25
#endif
 
26
 
 
27
#include <stdio.h>
 
28
#include <fcntl.h>
 
29
 
 
30
#include "utils.h"
 
31
 
 
32
static unsigned char ebuf[512];
 
33
 
 
34
#if defined(WIN32)
 
35
 
 
36
#ifdef __GNUC__                         // Mingw or Cygwin
 
37
 
 
38
#define u_off_t         off64_t
 
39
#define u_lseek         lseek64
 
40
 
 
41
#else
 
42
 
 
43
#define u_off_t         __int64
 
44
#define u_lseek         _lseeki64
 
45
 
 
46
#endif
 
47
 
 
48
#else
 
49
 
 
50
#define u_off_t         off_t           // In FreeBSD, off_t is 64-bit !
 
51
#define u_lseek         lseek
 
52
 
 
53
#endif
 
54
 
 
55
int go_sect(int hd,unsigned long sec)
 
56
{
 
57
  // Test if 64-bit seek is supported
 
58
  if (sizeof(u_off_t)>=8)
 
59
    {
 
60
      u_off_t bs,rs;
 
61
 
 
62
      bs=sec;
 
63
      bs<<=9;
 
64
      rs=u_lseek(hd,bs,SEEK_SET);
 
65
      return (bs!=rs);
 
66
    }
 
67
  else
 
68
    {
 
69
      unsigned long bs[2];
 
70
 
 
71
      bs[0]=sec<<9;
 
72
      bs[1]=sec>>23;
 
73
      if (bs[1])
 
74
        return 1;
 
75
      return (lseek(hd,bs[0],SEEK_SET)!=bs[0]);
 
76
    }
 
77
}
 
78
 
 
79
// Partition enumerator
 
80
// xe->cur is the current partition number, before the first call to xd_enum,
 
81
// it should be set to 0xFF
 
82
// xe->nxt is the target partition number, if it equals 0xFF, it means enumerate
 
83
// all partitions, otherwise, it means jump to the specific partition.
 
84
int xd_enum(int hd,xde_t* xe)
 
85
{
 
86
  int nn=512,kk=1,cc;
 
87
 
 
88
  for (cc=xe->cur;;)
 
89
    {
 
90
      if (cc==0xFF)
 
91
        {
 
92
          unsigned long pt[4][2];
 
93
          int i,j,np;
 
94
 
 
95
          if (go_sect(hd,0))
 
96
            return 1;
 
97
          if (read(hd,ebuf,nn)!=nn)
 
98
            return 1;
 
99
          if (valueat(ebuf,0x1FE,unsigned short)!=0xAA55)
 
100
            return 1;
 
101
          np=0;
 
102
          for (i=0x1BE;i<0x1FE;i+=16)
 
103
            if (ebuf[i+4])
 
104
              {
 
105
                if ((pt[np][1]=valueat(ebuf,i+12,unsigned long))==0)
 
106
                  return 1;
 
107
                pt[np++][0]=valueat(ebuf,i+8,unsigned long);
 
108
              }
 
109
          if (np==0)
 
110
            return 1;
 
111
          // Sort partition table base on start address
 
112
          for (i=0;i<np-1;i++)
 
113
            {
 
114
              int k=i;
 
115
              for (j=i+1;j<np;j++)
 
116
                if (pt[k][0]>pt[j][0]) k=j;
 
117
              if (k!=i)
 
118
                {
 
119
                  unsigned long tt;
 
120
 
 
121
                  tt=pt[i][0];
 
122
                  pt[i][0]=pt[k][0];
 
123
                  pt[k][0]=tt;
 
124
                  tt=pt[i][1];
 
125
                  pt[i][1]=pt[k][1];
 
126
                  pt[k][1]=tt;
 
127
                }
 
128
            }
 
129
          // Should have space for MBR
 
130
          if (pt[0][0]==0)
 
131
            return 1;
 
132
          // Check for partition overlap
 
133
          for (i=0;i<np-1;i++)
 
134
            if (pt[i][0]+pt[i][1]>pt[i+1][0])
 
135
              return 1;
 
136
          cc=0;
 
137
        }
 
138
      else if (kk)
 
139
        cc++;
 
140
      if ((unsigned char)cc>xe->nxt)
 
141
        return 1;
 
142
      if (cc<4)
 
143
        {
 
144
          if (xe->nxt<4)
 
145
            {
 
146
              // Empty partition
 
147
              if (! ebuf[xe->nxt*16+4+0x1BE])
 
148
                return 1;
 
149
              xe->cur=xe->nxt;
 
150
              xe->dfs=ebuf[xe->nxt*16+4+0x1BE];
 
151
              xe->bse=valueat(ebuf,xe->nxt*16+8+0x1BE,unsigned long);
 
152
              xe->len=valueat(ebuf,xe->nxt*16+12+0x1BE,unsigned long);
 
153
              return 0;
 
154
            }
 
155
          else if (xe->nxt!=0xFF)
 
156
            cc=4;
 
157
          else while (cc<4)
 
158
            {
 
159
              if (ebuf[cc*16+4+0x1BE])
 
160
                {
 
161
                  xe->cur=cc;
 
162
                  xe->dfs=ebuf[cc*16+4+0x1BE];
 
163
                  xe->bse=valueat(ebuf,cc*16+8+0x1BE,unsigned long);
 
164
                  xe->len=valueat(ebuf,cc*16+12+0x1BE,unsigned long);
 
165
                  return 0;
 
166
                }
 
167
              cc++;
 
168
            }
 
169
        }
 
170
      if ((cc==4) && (kk))
 
171
        {
 
172
          int i;
 
173
 
 
174
          // Scan for extended partition
 
175
          for (i=0;i<4;i++)
 
176
            if ((ebuf[i*16+4+0x1BE]==5) || (ebuf[i*16+4+0x1BE]==0xF)) break;
 
177
          if (i==4)
 
178
            return 1;
 
179
          xe->ebs=xe->bse=valueat(ebuf,i*16+8+0x1BE,unsigned long);
 
180
        }
 
181
      else
 
182
        {
 
183
          // Is end of extended partition chain ?
 
184
          if ((ebuf[4+0x1CE]!=0x5) && (ebuf[4+0x1CE]!=0xF) ||
 
185
              (valueat(ebuf,8+0x1CE,unsigned long)==0))
 
186
            return 1;
 
187
          xe->bse=xe->ebs+valueat(ebuf,8+0x1CE,unsigned long);
 
188
        }
 
189
      {
 
190
        int r;
 
191
 
 
192
        while (1)
 
193
          {
 
194
            if (go_sect(hd,xe->bse))
 
195
              return 1;
 
196
 
 
197
            if (read(hd,ebuf,nn)!=nn)
 
198
              return 1;
 
199
 
 
200
            if (valueat(ebuf,0x1FE,unsigned short)!=0xAA55)
 
201
              return 1;
 
202
 
 
203
            if ((ebuf[4+0x1BE]==5) || (ebuf[4+0x1BE]==0xF))
 
204
              if (valueat(ebuf,8+0x1BE,unsigned long)==0)
 
205
                return 1;
 
206
              else
 
207
                {
 
208
                  xe->bse=xe->ebs+valueat(ebuf,8+0x1BE,unsigned long);
 
209
                  continue;
 
210
                }
 
211
            break;
 
212
          }
 
213
        kk=(ebuf[4+0x1BE]!=0);
 
214
        if ((kk) && ((xe->nxt==0xFF) || (cc==xe->nxt)))
 
215
          {
 
216
            xe->cur=cc;
 
217
            xe->dfs=ebuf[4+0x1BE];
 
218
            xe->bse+=valueat(ebuf,8+0x1BE,unsigned long);
 
219
            xe->len=valueat(ebuf,12+0x1BE,unsigned long);
 
220
            return 0;
 
221
          }
 
222
      }
 
223
    }
 
224
}
 
225
 
 
226
#define EXT2_SUPER_MAGIC      0xEF53
 
227
 
 
228
int mbr_nhd, mbr_spt;
 
229
 
 
230
void split_chs(unsigned char* chs,unsigned long* c,unsigned long* h,unsigned long* s)
 
231
{
 
232
  *h=chs[0];
 
233
  *s=(chs[1] & 0x3F)-1;
 
234
  *c=((unsigned long)(chs[1]>>6))*256+chs[2];
 
235
}
 
236
 
 
237
int chk_chs(unsigned long nhd,unsigned long spt,unsigned long lba,unsigned char* chs)
 
238
{
 
239
  unsigned long c,h,s;
 
240
 
 
241
  split_chs(chs,&c,&h,&s);
 
242
  if (c==0x3FF)
 
243
    return ((nhd==h+1) && (spt==s+1));
 
244
  else
 
245
    return (c*nhd*spt+h*spt+s==lba);
 
246
}
 
247
 
 
248
int chk_mbr(unsigned char* buf)
 
249
{
 
250
  unsigned long nhd,spt,a1,a2,c2,h2,s2;
 
251
  int i;
 
252
 
 
253
  i=0x1BE;
 
254
  while ((i<0x1FE) && (buf[i+4]==0))
 
255
    i+=16;
 
256
  if (i>=0x1FE)
 
257
    return 0;
 
258
  a1=valueat(buf[i],8,unsigned long);
 
259
  a2=a1+valueat(buf[i],12,unsigned long)-1;
 
260
  if (a1>=a2)
 
261
    return 0;
 
262
  split_chs(buf+i+5,&c2,&h2,&s2);
 
263
  if (c2==0x3FF)
 
264
    {
 
265
      nhd=h2+1;
 
266
      spt=s2+1;
 
267
      if (! chk_chs(nhd,spt,a1,buf+i+1))
 
268
        return 0;
 
269
    }
 
270
  else
 
271
    {
 
272
      unsigned long c1,h1,s1;
 
273
      long n1,n2;
 
274
 
 
275
      split_chs(buf+i+1,&c1,&h1,&s1);
 
276
      if ((c1==0x3FF) || (c1>c2))
 
277
        return 0;
 
278
      n1=(long)(c1*a2)-(long)(c2*a1)-(long)(c1*s2)+(long)(c2*s1);
 
279
      n2=(long)(c1*h2)-(long)(c2*h1);
 
280
      if (n2<0)
 
281
        {
 
282
          n2=-n2;
 
283
          n1=-n1;
 
284
        }
 
285
      if ((n2==0) || (n1<=0) || (n1 % n2))
 
286
        return 0;
 
287
      spt=(unsigned long)(n1/n2);
 
288
      if (c2)
 
289
        {
 
290
          n1=(long)a2-(long)s2-(long)(h2*spt);
 
291
          n2=(long)(c2*spt);
 
292
          if ((n2==0) || (n1<=0) || (n1 % n2))
 
293
            return 0;
 
294
          nhd=(unsigned long)(n1/n2);
 
295
        }
 
296
      else
 
297
        nhd=h2+1;
 
298
    }
 
299
  if ((nhd==0) || (nhd>255) || (spt==0) || (spt>63))
 
300
    return 0;
 
301
  i+=16;
 
302
  while (i<0x1FE)
 
303
    {
 
304
      if (buf[i+4])
 
305
        {
 
306
          if ((! chk_chs(nhd,spt,valueat(buf[i],8,unsigned long),buf+i+1)) ||
 
307
              (! chk_chs(nhd,spt,valueat(buf[i],8,unsigned long)+valueat(buf[i],12,unsigned long)-1,buf+i+5)))
 
308
            return 0;
 
309
        }
 
310
      i+=16;
 
311
    }
 
312
  mbr_nhd=(int)nhd;
 
313
  mbr_spt=(int)spt;
 
314
  return 1;
 
315
}
 
316
 
 
317
int get_fstype(unsigned char* buf)
 
318
{
 
319
  if (chk_mbr(buf))
 
320
    return FST_MBR;
 
321
 
 
322
  // The first sector of EXT2 might not contain the 0xAA55 signature
 
323
  if (valueat(buf[1024],56,unsigned short)==EXT2_SUPER_MAGIC)
 
324
    return FST_EXT2;
 
325
  if (valueat(buf[0],0x1FE,unsigned short)!=0xAA55)
 
326
    return FST_OTHER;
 
327
  if (! strncmp(&buf[0x36],"FAT",3))
 
328
    return ((buf[0x26]==0x28) || (buf[0x26]==0x29))?FST_FAT16:FST_OTHER;
 
329
  if (! strncmp(&buf[0x52],"FAT32",5))
 
330
    return ((buf[0x42]==0x28) || (buf[0x42]==0x29))?FST_FAT32:FST_OTHER;
 
331
  if (! strncmp(&buf[0x3],"NTFS",4))
 
332
    return ((buf[0]==0xEB) && (buf[1]==0x52))?FST_NTFS:FST_OTHER;
 
333
  return FST_OTHER;
 
334
}
 
335
 
 
336
char* fst2str(int fs)
 
337
{
 
338
  switch (fs) {
 
339
  case FST_OTHER:
 
340
    return "Other";
 
341
  case FST_MBR:
 
342
    return "MBR";
 
343
  case FST_FAT16:
 
344
    return "FAT12/FAT16";
 
345
  case FST_FAT32:
 
346
    return "FAT32";
 
347
  case FST_NTFS:
 
348
    return "NTFS";
 
349
  case FST_EXT2:
 
350
    return "EXT2/EXT3";
 
351
  default:
 
352
    return "Unknown";
 
353
  }
 
354
}
 
355
 
 
356
typedef struct {
 
357
  int id;
 
358
  char* str;
 
359
} fstab_t;
 
360
 
 
361
static fstab_t fstab[]= {
 
362
  {0x1,"FAT12"},
 
363
  {0x4,"FAT16"},
 
364
  {0x5,"Extended"},
 
365
  {0x6,"FAT16B"},
 
366
  {0x7,"NTFS"},
 
367
  {0xB,"FAT32"},
 
368
  {0xC,"FAT32X"},
 
369
  {0xE,"FAT16X"},
 
370
  {0xF,"ExtendedX"},
 
371
  {0x11,"(H)FAT12"},
 
372
  {0x14,"(H)FAT16"},
 
373
  {0x16,"(H)FAT16B"},
 
374
  {0x17,"(H)NTFS"},
 
375
  {0x1B,"(H)FAT32"},
 
376
  {0x1C,"(H)FAT32X"},
 
377
  {0x1E,"(H)FAT16X"},
 
378
  {0x82,"Swap"},
 
379
  {0x83,"Ext2"},
 
380
  {0xA5,"FBSD"},
 
381
  {0,"Other"}};
 
382
 
 
383
char* dfs2str(int fs)
 
384
{
 
385
  int i;
 
386
 
 
387
  for (i=0;fstab[i].id;i++)
 
388
    if (fs==fstab[i].id)
 
389
      return fstab[i].str;
 
390
  return fstab[i].str;
 
391
}