2 * GRUB Utilities -- Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
3 * Copyright (C) 2007 Bean (bean123@126.com)
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.
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.
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.
22 #define _FILE_OFFSET_BITS 64 // This is required to enable 64-bit off_t
33 static unsigned char ebuf
[512];
37 #ifdef __GNUC__ // Mingw or Cygwin
39 #define u_off_t off64_t
40 #define u_lseek lseek64
44 #define u_off_t __int64
45 #define u_lseek _lseeki64
51 #define u_off_t off_t // In FreeBSD, off_t is 64-bit !
56 int go_sect(int hd
,unsigned long sec
)
58 // Test if 64-bit seek is supported
59 if (sizeof(u_off_t
)>=8)
65 rs
=u_lseek(hd
,bs
,SEEK_SET
);
76 return (lseek(hd
,bs
[0],SEEK_SET
)!=(off_t
)bs
[0]);
80 // Partition enumerator
81 // xe->cur is the current partition number, before the first call to xd_enum,
82 // it should be set to 0xFF
83 // xe->nxt is the target partition number, if it equals 0xFF, it means enumerate
84 // all partitions, otherwise, it means jump to the specific partition.
85 int xd_enum(int hd
,xde_t
* xe
)
93 unsigned long pt
[4][2];
98 if (read(hd
,ebuf
,nn
)!=nn
)
100 if (get16(ebuf
,0x1FE)!=0xAA55)
103 for (i
=0x1BE;i
<0x1FE;i
+=16)
106 if ((pt
[np
][1]=get32(ebuf
,i
+12))==0)
108 pt
[np
++][0]=get32(ebuf
,i
+8);
112 // Sort partition table base on start address
117 if (pt
[k
][0]>pt
[j
][0]) k
=j
;
130 // Should have space for MBR
133 // Check for partition overlap
135 if (pt
[i
][0]+pt
[i
][1]>pt
[i
+1][0])
141 if ((unsigned char)cc
>xe
->nxt
)
148 if (! ebuf
[xe
->nxt
*16+4+0x1BE])
151 xe
->dfs
=ebuf
[xe
->nxt
*16+4+0x1BE];
152 xe
->bse
=get32(ebuf
,xe
->nxt
*16+8+0x1BE);
153 xe
->len
=get32(ebuf
,xe
->nxt
*16+12+0x1BE);
156 else if (xe
->nxt
!=0xFF)
160 if (ebuf
[cc
*16+4+0x1BE])
163 xe
->dfs
=ebuf
[cc
*16+4+0x1BE];
164 xe
->bse
=get32(ebuf
,cc
*16+8+0x1BE);
165 xe
->len
=get32(ebuf
,cc
*16+12+0x1BE);
175 // Scan for extended partition
177 if ((ebuf
[i
*16+4+0x1BE]==5) || (ebuf
[i
*16+4+0x1BE]==0xF)) break;
180 xe
->ebs
=xe
->bse
=get32(ebuf
,i
*16+8+0x1BE);
184 // Is end of extended partition chain ?
185 if (((ebuf
[4+0x1CE]!=0x5) && (ebuf
[4+0x1CE]!=0xF)) ||
186 (get32(ebuf
,8+0x1CE)==0))
188 xe
->bse
=xe
->ebs
+get32(ebuf
,8+0x1CE);
193 if (go_sect(hd
,xe
->bse
))
196 if (read(hd
,ebuf
,nn
)!=nn
)
199 if (get16(ebuf
,0x1FE)!=0xAA55)
202 if ((ebuf
[4+0x1BE]==5) || (ebuf
[4+0x1BE]==0xF))
204 if (get32(ebuf
,8+0x1BE)==0)
208 xe
->bse
=xe
->ebs
+get32(ebuf
,8+0x1BE);
214 kk
=(ebuf
[4+0x1BE]!=0);
215 if ((kk
) && ((xe
->nxt
==0xFF) || (cc
==xe
->nxt
)))
218 xe
->dfs
=ebuf
[4+0x1BE];
219 xe
->bse
+=get32(ebuf
,8+0x1BE);
220 xe
->len
=get32(ebuf
,12+0x1BE);
227 #define EXT2_SUPER_MAGIC 0xEF53
229 int mbr_nhd
, mbr_spt
;
231 static void split_chs(unsigned char* chs
,unsigned long* c
,unsigned long* h
,unsigned long* s
)
234 *s
=(chs
[1] & 0x3F)-1;
235 *c
=((unsigned long)(chs
[1]>>6))*256+chs
[2];
238 static int chk_chs(unsigned long nhd
,unsigned long spt
,unsigned long lba
,unsigned char* chs
)
242 split_chs(chs
,&c
,&h
,&s
);
244 return ((nhd
==h
+1) && (spt
==s
+1));
246 return (c
*nhd
*spt
+h
*spt
+s
==lba
);
249 static int chk_mbr(unsigned char* buf
)
251 unsigned long nhd
,spt
,a1
,a2
,c2
,h2
,s2
;
255 while ((i
<0x1FE) && (buf
[i
+4]==0))
260 a2
=a1
+get32(&buf
[i
],12)-1;
263 split_chs(buf
+i
+5,&c2
,&h2
,&s2
);
268 if (! chk_chs(nhd
,spt
,a1
,buf
+i
+1))
273 unsigned long c1
,h1
,s1
;
276 split_chs(buf
+i
+1,&c1
,&h1
,&s1
);
277 if ((c1
==0x3FF) || (c1
>c2
))
279 n1
=(long)(c1
*a2
)-(long)(c2
*a1
)-(long)(c1
*s2
)+(long)(c2
*s1
);
280 n2
=(long)(c1
*h2
)-(long)(c2
*h1
);
286 if ((n2
==0) || (n1
<=0) || (n1
% n2
))
288 spt
=(unsigned long)(n1
/n2
);
291 n1
=(long)a2
-(long)s2
-(long)(h2
*spt
);
293 if ((n2
==0) || (n1
<=0) || (n1
% n2
))
295 nhd
=(unsigned long)(n1
/n2
);
300 if ((nhd
==0) || (nhd
>255) || (spt
==0) || (spt
>63))
307 if ((! chk_chs(nhd
,spt
,get32(&buf
[i
],8),buf
+i
+1)) ||
308 (! chk_chs(nhd
,spt
,get32(&buf
[i
],8)+get32(&buf
[i
],12)-1,buf
+i
+5)))
318 int get_fstype(unsigned char* buf
)
323 // The first sector of EXT2 might not contain the 0xAA55 signature
324 if (get16(&buf
[1024],56)==EXT2_SUPER_MAGIC
)
326 if (get16(&buf
[0],0x1FE)!=0xAA55)
328 if (! memcmp(&buf
[0x36],"FAT",3))
329 return ((buf
[0x26]==0x28) || (buf
[0x26]==0x29))?FST_FAT16
:FST_OTHER
;
330 if (! memcmp(&buf
[0x52],"FAT32",5))
331 return ((buf
[0x42]==0x28) || (buf
[0x42]==0x29))?FST_FAT32
:FST_OTHER
;
332 if (! memcmp(&buf
[0x3],"NTFS",4))
333 return ((buf
[0]==0xEB) && (buf
[1]==0x52))?FST_NTFS
:FST_OTHER
;
337 const char* fst2str(int fs
)
345 return "FAT12/FAT16";
362 static fstab_t fstab
[]= {
384 const char* dfs2str(int fs
)
388 for (i
=0;fstab
[i
].id
;i
++)