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
32 static unsigned char ebuf
[512];
36 #ifdef __GNUC__ // Mingw or Cygwin
38 #define u_off_t off64_t
39 #define u_lseek lseek64
43 #define u_off_t __int64
44 #define u_lseek _lseeki64
50 #define u_off_t off_t // In FreeBSD, off_t is 64-bit !
55 int go_sect(int hd
,unsigned long sec
)
57 // Test if 64-bit seek is supported
58 if (sizeof(u_off_t
)>=8)
64 rs
=u_lseek(hd
,bs
,SEEK_SET
);
75 return (lseek(hd
,bs
[0],SEEK_SET
)!=bs
[0]);
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
)
92 unsigned long pt
[4][2];
97 if (read(hd
,ebuf
,nn
)!=nn
)
99 if (valueat(ebuf
,0x1FE,unsigned short)!=0xAA55)
102 for (i
=0x1BE;i
<0x1FE;i
+=16)
105 if ((pt
[np
][1]=valueat(ebuf
,i
+12,unsigned long))==0)
107 pt
[np
++][0]=valueat(ebuf
,i
+8,unsigned long);
111 // Sort partition table base on start address
116 if (pt
[k
][0]>pt
[j
][0]) k
=j
;
129 // Should have space for MBR
132 // Check for partition overlap
134 if (pt
[i
][0]+pt
[i
][1]>pt
[i
+1][0])
140 if ((unsigned char)cc
>xe
->nxt
)
147 if (! ebuf
[xe
->nxt
*16+4+0x1BE])
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);
155 else if (xe
->nxt
!=0xFF)
159 if (ebuf
[cc
*16+4+0x1BE])
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);
174 // Scan for extended partition
176 if ((ebuf
[i
*16+4+0x1BE]==5) || (ebuf
[i
*16+4+0x1BE]==0xF)) break;
179 xe
->ebs
=xe
->bse
=valueat(ebuf
,i
*16+8+0x1BE,unsigned long);
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))
187 xe
->bse
=xe
->ebs
+valueat(ebuf
,8+0x1CE,unsigned long);
194 if (go_sect(hd
,xe
->bse
))
197 if (read(hd
,ebuf
,nn
)!=nn
)
200 if (valueat(ebuf
,0x1FE,unsigned short)!=0xAA55)
203 if ((ebuf
[4+0x1BE]==5) || (ebuf
[4+0x1BE]==0xF))
204 if (valueat(ebuf
,8+0x1BE,unsigned long)==0)
208 xe
->bse
=xe
->ebs
+valueat(ebuf
,8+0x1BE,unsigned long);
213 kk
=(ebuf
[4+0x1BE]!=0);
214 if ((kk
) && ((xe
->nxt
==0xFF) || (cc
==xe
->nxt
)))
217 xe
->dfs
=ebuf
[4+0x1BE];
218 xe
->bse
+=valueat(ebuf
,8+0x1BE,unsigned long);
219 xe
->len
=valueat(ebuf
,12+0x1BE,unsigned long);
226 #define EXT2_SUPER_MAGIC 0xEF53
228 int mbr_nhd
, mbr_spt
;
230 void split_chs(unsigned char* chs
,unsigned long* c
,unsigned long* h
,unsigned long* s
)
233 *s
=(chs
[1] & 0x3F)-1;
234 *c
=((unsigned long)(chs
[1]>>6))*256+chs
[2];
237 int chk_chs(unsigned long nhd
,unsigned long spt
,unsigned long lba
,unsigned char* chs
)
241 split_chs(chs
,&c
,&h
,&s
);
243 return ((nhd
==h
+1) && (spt
==s
+1));
245 return (c
*nhd
*spt
+h
*spt
+s
==lba
);
248 int chk_mbr(unsigned char* buf
)
250 unsigned long nhd
,spt
,a1
,a2
,c2
,h2
,s2
;
254 while ((i
<0x1FE) && (buf
[i
+4]==0))
258 a1
=valueat(buf
[i
],8,unsigned long);
259 a2
=a1
+valueat(buf
[i
],12,unsigned long)-1;
262 split_chs(buf
+i
+5,&c2
,&h2
,&s2
);
267 if (! chk_chs(nhd
,spt
,a1
,buf
+i
+1))
272 unsigned long c1
,h1
,s1
;
275 split_chs(buf
+i
+1,&c1
,&h1
,&s1
);
276 if ((c1
==0x3FF) || (c1
>c2
))
278 n1
=(long)(c1
*a2
)-(long)(c2
*a1
)-(long)(c1
*s2
)+(long)(c2
*s1
);
279 n2
=(long)(c1
*h2
)-(long)(c2
*h1
);
285 if ((n2
==0) || (n1
<=0) || (n1
% n2
))
287 spt
=(unsigned long)(n1
/n2
);
290 n1
=(long)a2
-(long)s2
-(long)(h2
*spt
);
292 if ((n2
==0) || (n1
<=0) || (n1
% n2
))
294 nhd
=(unsigned long)(n1
/n2
);
299 if ((nhd
==0) || (nhd
>255) || (spt
==0) || (spt
>63))
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)))
317 int get_fstype(unsigned char* buf
)
322 // The first sector of EXT2 might not contain the 0xAA55 signature
323 if (valueat(buf
[1024],56,unsigned short)==EXT2_SUPER_MAGIC
)
325 if (valueat(buf
[0],0x1FE,unsigned short)!=0xAA55)
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
;
336 char* fst2str(int fs
)
344 return "FAT12/FAT16";
361 static fstab_t fstab
[]= {
383 char* dfs2str(int fs
)
387 for (i
=0;fstab
[i
].id
;i
++)