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