1 /*
2 
3     File: next.c
4 
5     Copyright (C) 2007 Christophe GRENIER <grenier@cgsecurity.org>
6 
7     This software is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License along
18     with this program; if not, write the Free Software Foundation, Inc., 51
19     Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 
21  */
22 /*
23    Instead of incrementing the sector number by one and checking if its value
24    is aligned to a cylinder (PC) or similar boundary, return the next
25    sector number that will be aligned to such boundary.
26 */
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 #include "types.h"
32 #include "common.h"
33 #include "ext2.h"
34 #include "next.h"
35 extern const arch_fnct_t arch_i386;
36 extern const arch_fnct_t arch_mac;
37 extern const arch_fnct_t arch_none;
38 extern const arch_fnct_t arch_sun;
39 
40 struct search_location
41 {
42   uint64_t offset;
43   uint64_t inc;
44 };
45 typedef struct search_location search_location_t;
46 static inline uint64_t CHS_to_offset(const unsigned int C, const int H, const int S,const disk_t *disk_car);
47 
48 #define SEARCH_LOCATION_MAX 256
49 static unsigned int search_location_nbr=0;
50 static search_location_t search_location_info[SEARCH_LOCATION_MAX+1];
51 
CHS_to_offset(const unsigned int C,const int H,const int S,const disk_t * disk_car)52 static inline uint64_t CHS_to_offset(const unsigned int C, const int H, const int S,const disk_t *disk_car)
53 {
54   return (((uint64_t)C * disk_car->geom.heads_per_cylinder + H) * disk_car->geom.sectors_per_head +(S>0?S-1:S))*disk_car->sector_size;
55 }
56 
update_location(void)57 static void update_location(void)
58 {
59   unsigned int i;
60   const search_location_t *src=&search_location_info[search_location_nbr];
61   if(src->inc==0)
62   {
63     for(i=0; i<search_location_nbr; i++)
64     {
65       if(search_location_info[i].offset == src->offset)
66 	return ;
67     }
68     if(search_location_nbr < SEARCH_LOCATION_MAX)
69       search_location_nbr++;
70     return;
71   }
72   for(i=0; i<search_location_nbr; i++)
73   {
74     search_location_t *cur=&search_location_info[i];
75     if(cur->offset == src->offset &&
76 	cur->inc >= src->inc &&
77 	cur->inc % src->inc==0)
78     {
79       cur->inc=src->inc;
80       return ;
81     }
82     if(cur->inc == 0)
83     {
84       if(cur->offset == src->offset)
85       {
86 	cur->inc = src->inc;
87 	return ;
88       }
89     }
90     else
91     {
92       if(cur->offset == src->offset &&
93 	  src->inc >= cur->inc && src->inc % cur->inc==0)
94 	return ;
95       if(cur->inc==src->inc &&
96 	  cur->offset >= src->offset &&
97 	  (cur->offset - src->offset)%cur->inc==0)
98       {
99 	cur->offset=src->offset;
100 	return ;
101       }
102       if(cur->inc==src->inc &&
103 	  src->offset >= cur->offset &&
104 	  (src->offset - cur->offset)%cur->inc==0)
105 	return ;
106     }
107   }
108   if(search_location_nbr < SEARCH_LOCATION_MAX)
109     search_location_nbr++;
110 }
111 
search_location_init(const disk_t * disk_car,const unsigned int location_boundary,const int fast_mode)112 void search_location_init(const disk_t *disk_car, const unsigned int location_boundary, const int fast_mode)
113 {
114   /* test_nbr==1... */
115   if(disk_car->arch==&arch_i386)
116   {
117     if(fast_mode>1)
118     {
119       search_location_info[search_location_nbr].offset=CHS_to_offset(0,0,1,disk_car);
120       search_location_info[search_location_nbr].inc= CHS_to_offset(0,1,0,disk_car);
121       update_location();
122     }
123     else
124     {
125       //CHS H=0,1,2 S=1
126       search_location_info[search_location_nbr].offset=CHS_to_offset(0,0,1,disk_car);
127       search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
128       update_location();
129       search_location_info[search_location_nbr].offset=CHS_to_offset(0,1,1,disk_car);
130       search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
131       update_location();
132       search_location_info[search_location_nbr].offset=CHS_to_offset(0,2,1,disk_car);
133       search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
134     }
135     search_location_info[search_location_nbr].offset=0;
136     search_location_info[search_location_nbr].inc=2048*512;
137     update_location();
138   }
139   else
140   {
141     search_location_info[search_location_nbr].offset=0;
142     search_location_info[search_location_nbr].inc=location_boundary;
143     update_location();
144   }
145   if(fast_mode>0)
146   {
147     /* test_nbr==2 FAT32 backup boot sector */
148     if(disk_car->arch==&arch_i386)
149     {
150       //CHS H=0,1,2 S=7
151       search_location_info[search_location_nbr].offset=CHS_to_offset(0,0,7,disk_car);
152       search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
153       update_location();
154       search_location_info[search_location_nbr].offset=CHS_to_offset(0,1,7,disk_car);
155       search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
156       update_location();
157       search_location_info[search_location_nbr].offset=CHS_to_offset(0,2,7,disk_car);
158       search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
159       update_location();
160     }
161     else
162     {
163       search_location_info[search_location_nbr].offset=CHS_to_offset(0,0,7,disk_car);
164       search_location_info[search_location_nbr].inc=location_boundary;
165       update_location();
166     }
167     search_location_info[search_location_nbr].offset=CHS_to_offset(0,0,7,disk_car);
168     search_location_info[search_location_nbr].inc=2048*512;
169     update_location();
170     /* test_nbr==3 ou test_nbr==4, NTFS or HFS backup boot sector */
171     if(disk_car->arch==&arch_i386)
172     {
173       search_location_info[search_location_nbr].offset=CHS_to_offset(1,0,-1,disk_car);
174       search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
175       update_location();
176     }
177     else
178     {
179       search_location_info[search_location_nbr].offset=location_boundary-512;
180       search_location_info[search_location_nbr].inc=location_boundary;
181       update_location();
182     }
183     search_location_info[search_location_nbr].offset=(2048-1)*512;
184     search_location_info[search_location_nbr].inc=2048*512;
185     update_location();
186     /* test_nbr==5*/
187     {
188       int s_log_block_size;
189       for(s_log_block_size=0;s_log_block_size<=2;s_log_block_size++)
190       {
191 	const uint64_t hd_offset=3*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)*8*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)+(s_log_block_size==0?2*DEFAULT_SECTOR_SIZE:0);
192 	if(disk_car->arch==&arch_i386)
193 	{
194 	  search_location_info[search_location_nbr].offset=CHS_to_offset(0,0,1,disk_car)+hd_offset;
195 	  search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
196 	  update_location();
197 	  search_location_info[search_location_nbr].offset=CHS_to_offset(0,1,1,disk_car)+hd_offset;
198 	  search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
199 	  update_location();
200 	  search_location_info[search_location_nbr].offset=CHS_to_offset(0,2,1,disk_car)+hd_offset;
201 	  search_location_info[search_location_nbr].inc=CHS_to_offset(1,0,0,disk_car);
202 	  update_location();
203 	}
204 	else
205 	{
206 	  search_location_info[search_location_nbr].offset=CHS_to_offset(0,0,1,disk_car)+hd_offset;
207 	  search_location_info[search_location_nbr].inc=location_boundary;
208 	  update_location();
209 	}
210       }
211     }
212   }
213 }
214 
search_location_update(const uint64_t location)215 uint64_t search_location_update(const uint64_t location)
216 {
217   unsigned int i;
218   uint64_t min=(uint64_t)-1;
219   for(i=0;i<search_location_nbr;i++)
220   {
221     while(search_location_info[i].offset<=location)
222       search_location_info[i].offset+=search_location_info[i].inc;
223     if(min>search_location_info[i].offset)
224       min=search_location_info[i].offset;
225   }
226   return min;
227 }
228 
229