Revert, thx Thomas, wasnt sure.
[reactos.git] / reactos / tools / mkflpimg.c
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <time.h>
6
7 #define N_CYLINDERS 80
8 #define ROOT_ENTRY_SIZE 32
9
10 #define SECTOR_SIZE 512
11 #define SECTORS_PER_CLUSTER 1
12 #define N_RESERVED 1
13 #define N_FATS 2
14 #define N_ROOT_ENTRIES 224
15 #define SECTORS_PER_DISK (N_HEADS * N_CYLINDERS * SECTORS_PER_TRACK)
16 #define MEDIA_TYPE 0xf0
17 #define SECTORS_PER_FAT 9
18 #define SECTORS_PER_TRACK 18
19 #define N_HEADS 2
20 #define SIGNATURE 0x29 /* only MS? */
21 #define END_SIGNATURE 0xaa55
22
23
24 #define ATTR_READONLY 0x01
25 #define ATTR_HIDDEN 0x02
26 #define ATTR_SYSTEM 0x04
27 #define ATTR_VOLUME 0x08
28 #define ATTR_SUBDIR 0x10
29 #define ATTR_ARCHIVE 0x20
30 #define ATTR_RES1 0x40
31 #define ATTR_RES2 0x80
32
33
34 typedef unsigned char disk_sector_t[SECTOR_SIZE];
35
36 typedef struct boot_sector
37 {
38 unsigned short jmp;
39 unsigned char nop;
40 char oem[8];
41 unsigned short bytes_per_sector;
42 unsigned char sectors_per_cluster;
43 unsigned short reserved_sectors;
44 unsigned char n_fats;
45 unsigned short n_root_entries;
46 unsigned short n_sectors;
47 unsigned char media_type;
48 unsigned short sectors_per_fat;
49 unsigned short sectors_per_track;
50 unsigned short n_heads;
51 unsigned long hidden_sectors;
52 unsigned long huge_sectors;
53 unsigned char drive;
54 unsigned char reserved;
55 unsigned char signature;
56 unsigned long volume_id;
57 char volume_label[11];
58 char file_system[8];
59 unsigned char boot_code[SECTOR_SIZE - 62 - 2];
60 unsigned short end_signature;
61 } __attribute__ ((packed)) boot_sector_t;
62
63
64 typedef struct root_entry
65 {
66 char name[8];
67 char extension[3];
68 unsigned char attribute;
69 unsigned char reserved[10];
70 unsigned short time;
71 unsigned short date;
72 unsigned short cluster;
73 unsigned long size;
74 } __attribute ((packed)) root_entry_t;
75
76
77 disk_sector_t *new_image(char *bsfname)
78 {
79 FILE *bsf;
80 disk_sector_t *img;
81 boot_sector_t boot_sec;
82 root_entry_t *root;
83
84 if ((bsf = fopen(bsfname, "rb")) == NULL)
85 {
86 printf("Boot sector image file %s not found!\n", bsfname);
87 return NULL;
88 }
89 if (fread(&boot_sec, 1, SECTOR_SIZE, bsf) != SECTOR_SIZE)
90 {
91 printf("Unable to read boot sector image file %s!\n", bsfname);
92 fclose(bsf);
93 return NULL;
94 }
95 fclose(bsf);
96
97 if ( (boot_sec.bytes_per_sector != SECTOR_SIZE) ||
98 (boot_sec.sectors_per_cluster != SECTORS_PER_CLUSTER) ||
99 (boot_sec.reserved_sectors != N_RESERVED) ||
100 (boot_sec.n_fats != N_FATS) ||
101 (boot_sec.n_root_entries != N_ROOT_ENTRIES) ||
102 (boot_sec.n_sectors != SECTORS_PER_DISK) ||
103 (boot_sec.media_type != MEDIA_TYPE) ||
104 (boot_sec.sectors_per_fat != SECTORS_PER_FAT) ||
105 (boot_sec.sectors_per_track != SECTORS_PER_TRACK) ||
106 (boot_sec.n_heads != N_HEADS) ||
107 // (boot_sec.signature != SIGNATURE) ||
108 (boot_sec.end_signature != END_SIGNATURE) )
109 {
110 printf("Invalid boot sector in file %s\n", bsfname);
111 return NULL;
112 }
113
114 if ((img = (disk_sector_t *)malloc(SECTOR_SIZE * SECTORS_PER_DISK)) == NULL)
115 {
116 printf("Not enough memory!\n");
117 return NULL;
118 }
119
120 memset(img, 0, SECTOR_SIZE * SECTORS_PER_TRACK);
121 memcpy(img, &boot_sec, SECTOR_SIZE);
122
123 root = (root_entry_t *)img[N_RESERVED + N_FATS * SECTORS_PER_FAT];
124 strncpy(root->name, "REACTOS ", 11);
125 root->attribute = ATTR_VOLUME;
126
127 return img;
128 }
129
130
131 void create_root_entry(root_entry_t *root, char *fname,
132 unsigned short cluster, unsigned long size)
133 {
134 int i, j;
135 time_t t;
136 struct tm *localt;
137
138 i = 0;
139 j = 0;
140 while ((fname[j] != '\0') && (fname[j] != '.') && (i < 8))
141 {
142 root->name[i] = toupper(fname[j]);
143 i++;
144 j++;
145 }
146 while (i < 8)
147 {
148 root->name[i] = ' ';
149 i++;
150 }
151 if (fname[j] == '.')
152 {
153 i = 0;
154 j++;
155 while ((fname[j] != '\0') && (i < 3))
156 {
157 root->extension[i] = toupper(fname[j]);
158 i++;
159 j++;
160 }
161 while (i < 3)
162 {
163 root->extension[i] = ' ';
164 i++;
165 }
166 }
167 else
168 {
169 i = 0;
170 while (i < 3)
171 {
172 root->extension[i] = ' ';
173 i++;
174 }
175 }
176
177 root->attribute = ATTR_ARCHIVE;
178 t = time(0);
179 localt = localtime(&t);
180 root->time = (((localt->tm_hour & 0x001f) << 11) |
181 ((localt->tm_min & 0x003f) << 5) |
182 ((localt->tm_sec / 2) & 0x001f));
183 root->date = ((((localt->tm_year - 80) & 0x007f) << 9) |
184 (((localt->tm_mon + 1) & 0x000f) << 5) |
185 (localt->tm_mday & 0x001f));
186 root->cluster = cluster;
187 root->size = size;
188 }
189
190
191 void update_fat(unsigned char *fat, int cl_start, int cl_end)
192 {
193 int i, k;
194 unsigned short *cl;
195
196 for (i = cl_start; i < cl_end - 1; i++)
197 {
198 k = (i - 2) * 3 / 2;
199 cl = ((unsigned short *)&fat[k]);
200 if (i & 1)
201 {
202 *cl = (*cl & 0x000f) | (((i + 1) & 0x0fff) << 4);
203 }
204 else
205 {
206 *cl = (*cl & 0xf000) | ((i + 1) & 0x0fff);
207 }
208 }
209 k = (i - 2) * 3 / 2;
210 cl = ((unsigned short *)&fat[k]);
211 if (i & 1)
212 {
213 *cl = (*cl & 0x000f) | 0xfff0;
214 }
215 else
216 {
217 *cl = (*cl & 0xf000) | 0x0fff;
218 }
219 }
220
221
222 int copy_files(disk_sector_t *img, char *filenames[], int n_files)
223 {
224 int i, k;
225 FILE *f;
226 int cl_start, cl_end;
227 unsigned char *fat1, *fat2;
228 root_entry_t *root;
229 unsigned long n, size;
230
231 fat1 = (unsigned char *)img[N_RESERVED];
232 fat2 = (unsigned char *)img[N_RESERVED + SECTORS_PER_FAT];
233 root = (root_entry_t *)img[N_RESERVED + N_FATS * SECTORS_PER_FAT];
234
235 k = N_RESERVED +
236 N_FATS * SECTORS_PER_FAT +
237 N_ROOT_ENTRIES * ROOT_ENTRY_SIZE / SECTOR_SIZE;
238
239 cl_end = 1;
240
241 if (n_files > N_ROOT_ENTRIES)
242 {
243 n_files = N_ROOT_ENTRIES;
244 }
245
246 for (i = 0; i < n_files; i++)
247 {
248 cl_start = cl_end + 1;
249 if ((f = fopen(filenames[i], "rb")) == NULL)
250 {
251 printf("Error opening file %s!", filenames[i]);
252 return 1;
253 }
254
255 printf(" %s\n", filenames[i]);
256
257 size = 0;
258 while ((n = fread(img[k], 1, SECTOR_SIZE, f)) > 0)
259 {
260 size += n;
261 cl_end++;
262 k++;
263 }
264 fclose(f);
265
266 root++;
267 create_root_entry(root, filenames[i], cl_start, size);
268
269 update_fat(fat1, cl_start, cl_end);
270 }
271 memcpy(fat2, fat1, SECTORS_PER_FAT * SECTOR_SIZE);
272
273 return 0;
274 }
275
276
277 int write_image(disk_sector_t *img, char *imgname)
278 {
279 FILE *f;
280
281 if ((f = fopen(imgname, "rb")) != NULL)
282 {
283 printf("Image file %s already exists!\n", imgname);
284 fclose(f);
285 free(img);
286 return 1;
287 }
288
289 f = fopen(imgname, "wb");
290 if (fwrite(img, SECTOR_SIZE, SECTORS_PER_DISK, f) != SECTORS_PER_DISK)
291 {
292 printf("Unable to write image file %s\n!", imgname);
293 fclose(f);
294 free(img);
295 return 1;
296 }
297 fclose(f);
298
299 free(img);
300 return 0;
301 }
302
303
304 int main(int argc, char *argv[])
305 {
306 disk_sector_t *img;
307 char *imgname;
308 char *bsfname;
309 char **filenames;
310 int n_files;
311
312 if (argc < 4)
313 {
314 printf("Usage: mkflpimg <image> <boot sector> <source files>\n");
315 return 1;
316 }
317
318 imgname = argv[1];
319 bsfname = argv[2];
320 filenames = &argv[3];
321 n_files = argc - 3;
322
323 printf("Creating image ...\n");
324 if ((img = new_image(bsfname)) == NULL)
325 {
326 return 1;
327 }
328
329 printf("Copying files ...\n");
330
331 if (copy_files(img, filenames, n_files))
332 {
333 return 1;
334 }
335
336 printf("Writing image file ...\n");
337
338 if (write_image(img, imgname))
339 {
340 return 1;
341 }
342
343 printf("Finished.\n");
344
345 return 0;
346 }
347