source: grub-pc/trunk/fuentes/debian/grub-extras/ntldr-img/utils.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 8.9 KB
Line 
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 <string.h>
29#include <fcntl.h>
30
31#include "utils.h"
32
33static unsigned char ebuf[512];
34
35#if defined(WIN32)
36
37#ifdef __GNUC__                         // Mingw or Cygwin
38
39#define u_off_t         off64_t
40#define u_lseek         lseek64
41
42#else
43
44#define u_off_t         __int64
45#define u_lseek         _lseeki64
46
47#endif
48
49#else
50
51#define u_off_t         off_t           // In FreeBSD, off_t is 64-bit !
52#define u_lseek         lseek
53
54#endif
55
56int go_sect(int hd,unsigned long sec)
57{
58  // Test if 64-bit seek is supported
59  if (sizeof(u_off_t)>=8)
60    {
61      u_off_t bs,rs;
62
63      bs=sec;
64      bs<<=9;
65      rs=u_lseek(hd,bs,SEEK_SET);
66      return (bs!=rs);
67    }
68  else
69    {
70      unsigned long bs[2];
71
72      bs[0]=sec<<9;
73      bs[1]=sec>>23;
74      if (bs[1])
75        return 1;
76      return (lseek(hd,bs[0],SEEK_SET)!=(off_t)bs[0]);
77    }
78}
79
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.
85int xd_enum(int hd,xde_t* xe)
86{
87  int nn=512,kk=1,cc;
88
89  for (cc=xe->cur;;)
90    {
91      if (cc==0xFF)
92        {
93          unsigned long pt[4][2];
94          int i,j,np;
95
96          if (go_sect(hd,0))
97            return 1;
98          if (read(hd,ebuf,nn)!=nn)
99            return 1;
100          if (get16(ebuf,0x1FE)!=0xAA55)
101            return 1;
102          np=0;
103          for (i=0x1BE;i<0x1FE;i+=16)
104            if (ebuf[i+4])
105              {
106                if ((pt[np][1]=get32(ebuf,i+12))==0)
107                  return 1;
108                pt[np++][0]=get32(ebuf,i+8);
109              }
110          if (np==0)
111            return 1;
112          // Sort partition table base on start address
113          for (i=0;i<np-1;i++)
114            {
115              int k=i;
116              for (j=i+1;j<np;j++)
117                if (pt[k][0]>pt[j][0]) k=j;
118              if (k!=i)
119                {
120                  unsigned long tt;
121
122                  tt=pt[i][0];
123                  pt[i][0]=pt[k][0];
124                  pt[k][0]=tt;
125                  tt=pt[i][1];
126                  pt[i][1]=pt[k][1];
127                  pt[k][1]=tt;
128                }
129            }
130          // Should have space for MBR
131          if (pt[0][0]==0)
132            return 1;
133          // Check for partition overlap
134          for (i=0;i<np-1;i++)
135            if (pt[i][0]+pt[i][1]>pt[i+1][0])
136              return 1;
137          cc=0;
138        }
139      else if (kk)
140        cc++;
141      if ((unsigned char)cc>xe->nxt)
142        return 1;
143      if (cc<4)
144        {
145          if (xe->nxt<4)
146            {
147              // Empty partition
148              if (! ebuf[xe->nxt*16+4+0x1BE])
149                return 1;
150              xe->cur=xe->nxt;
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);
154              return 0;
155            }
156          else if (xe->nxt!=0xFF)
157            cc=4;
158          else while (cc<4)
159            {
160              if (ebuf[cc*16+4+0x1BE])
161                {
162                  xe->cur=cc;
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);
166                  return 0;
167                }
168              cc++;
169            }
170        }
171      if ((cc==4) && (kk))
172        {
173          int i;
174
175          // Scan for extended partition
176          for (i=0;i<4;i++)
177            if ((ebuf[i*16+4+0x1BE]==5) || (ebuf[i*16+4+0x1BE]==0xF)) break;
178          if (i==4)
179            return 1;
180          xe->ebs=xe->bse=get32(ebuf,i*16+8+0x1BE);
181        }
182      else
183        {
184          // Is end of extended partition chain ?
185          if (((ebuf[4+0x1CE]!=0x5) && (ebuf[4+0x1CE]!=0xF)) ||
186              (get32(ebuf,8+0x1CE)==0))
187            return 1;
188          xe->bse=xe->ebs+get32(ebuf,8+0x1CE);
189        }
190      {
191        while (1)
192          {
193            if (go_sect(hd,xe->bse))
194              return 1;
195
196            if (read(hd,ebuf,nn)!=nn)
197              return 1;
198
199            if (get16(ebuf,0x1FE)!=0xAA55)
200              return 1;
201
202            if ((ebuf[4+0x1BE]==5) || (ebuf[4+0x1BE]==0xF))
203              {
204                if (get32(ebuf,8+0x1BE)==0)
205                  return 1;
206                else
207                  {
208                    xe->bse=xe->ebs+get32(ebuf,8+0x1BE);
209                    continue;
210                  }
211              }
212            break;
213          }
214        kk=(ebuf[4+0x1BE]!=0);
215        if ((kk) && ((xe->nxt==0xFF) || (cc==xe->nxt)))
216          {
217            xe->cur=cc;
218            xe->dfs=ebuf[4+0x1BE];
219            xe->bse+=get32(ebuf,8+0x1BE);
220            xe->len=get32(ebuf,12+0x1BE);
221            return 0;
222          }
223      }
224    }
225}
226
227#define EXT2_SUPER_MAGIC      0xEF53
228
229int mbr_nhd, mbr_spt;
230
231static void split_chs(unsigned char* chs,unsigned long* c,unsigned long* h,unsigned long* s)
232{
233  *h=chs[0];
234  *s=(chs[1] & 0x3F)-1;
235  *c=((unsigned long)(chs[1]>>6))*256+chs[2];
236}
237
238static int chk_chs(unsigned long nhd,unsigned long spt,unsigned long lba,unsigned char* chs)
239{
240  unsigned long c,h,s;
241
242  split_chs(chs,&c,&h,&s);
243  if (c==0x3FF)
244    return ((nhd==h+1) && (spt==s+1));
245  else
246    return (c*nhd*spt+h*spt+s==lba);
247}
248
249static int chk_mbr(unsigned char* buf)
250{
251  unsigned long nhd,spt,a1,a2,c2,h2,s2;
252  int i;
253
254  i=0x1BE;
255  while ((i<0x1FE) && (buf[i+4]==0))
256    i+=16;
257  if (i>=0x1FE)
258    return 0;
259  a1=get32(&buf[i],8);
260  a2=a1+get32(&buf[i],12)-1;
261  if (a1>=a2)
262    return 0;
263  split_chs(buf+i+5,&c2,&h2,&s2);
264  if (c2==0x3FF)
265    {
266      nhd=h2+1;
267      spt=s2+1;
268      if (! chk_chs(nhd,spt,a1,buf+i+1))
269        return 0;
270    }
271  else
272    {
273      unsigned long c1,h1,s1;
274      long n1,n2;
275
276      split_chs(buf+i+1,&c1,&h1,&s1);
277      if ((c1==0x3FF) || (c1>c2))
278        return 0;
279      n1=(long)(c1*a2)-(long)(c2*a1)-(long)(c1*s2)+(long)(c2*s1);
280      n2=(long)(c1*h2)-(long)(c2*h1);
281      if (n2<0)
282        {
283          n2=-n2;
284          n1=-n1;
285        }
286      if ((n2==0) || (n1<=0) || (n1 % n2))
287        return 0;
288      spt=(unsigned long)(n1/n2);
289      if (c2)
290        {
291          n1=(long)a2-(long)s2-(long)(h2*spt);
292          n2=(long)(c2*spt);
293          if ((n2==0) || (n1<=0) || (n1 % n2))
294            return 0;
295          nhd=(unsigned long)(n1/n2);
296        }
297      else
298        nhd=h2+1;
299    }
300  if ((nhd==0) || (nhd>255) || (spt==0) || (spt>63))
301    return 0;
302  i+=16;
303  while (i<0x1FE)
304    {
305      if (buf[i+4])
306        {
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)))
309            return 0;
310        }
311      i+=16;
312    }
313  mbr_nhd=(int)nhd;
314  mbr_spt=(int)spt;
315  return 1;
316}
317
318int get_fstype(unsigned char* buf)
319{
320  if (chk_mbr(buf))
321    return FST_MBR;
322
323  // The first sector of EXT2 might not contain the 0xAA55 signature
324  if (get16(&buf[1024],56)==EXT2_SUPER_MAGIC)
325    return FST_EXT2;
326  if (get16(&buf[0],0x1FE)!=0xAA55)
327    return FST_OTHER;
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;
334  return FST_OTHER;
335}
336
337const char* fst2str(int fs)
338{
339  switch (fs) {
340  case FST_OTHER:
341    return "Other";
342  case FST_MBR:
343    return "MBR";
344  case FST_FAT16:
345    return "FAT12/FAT16";
346  case FST_FAT32:
347    return "FAT32";
348  case FST_NTFS:
349    return "NTFS";
350  case FST_EXT2:
351    return "EXT2/EXT3";
352  default:
353    return "Unknown";
354  }
355}
356
357typedef struct {
358  int id;
359  const char* str;
360} fstab_t;
361
362static fstab_t fstab[]= {
363  {0x1,"FAT12"},
364  {0x4,"FAT16"},
365  {0x5,"Extended"},
366  {0x6,"FAT16B"},
367  {0x7,"NTFS"},
368  {0xB,"FAT32"},
369  {0xC,"FAT32X"},
370  {0xE,"FAT16X"},
371  {0xF,"ExtendedX"},
372  {0x11,"(H)FAT12"},
373  {0x14,"(H)FAT16"},
374  {0x16,"(H)FAT16B"},
375  {0x17,"(H)NTFS"},
376  {0x1B,"(H)FAT32"},
377  {0x1C,"(H)FAT32X"},
378  {0x1E,"(H)FAT16X"},
379  {0x82,"Swap"},
380  {0x83,"Ext2"},
381  {0xA5,"FBSD"},
382  {0,"Other"}};
383
384const char* dfs2str(int fs)
385{
386  int i;
387
388  for (i=0;fstab[i].id;i++)
389    if (fs==fstab[i].id)
390      return fstab[i].str;
391  return fstab[i].str;
392}
Note: See TracBrowser for help on using the repository browser.