Added a test for MUIA_Listview_SelectChange.
[AROS.git] / arch / i386-pc / boot / floppy / install.c
blob234cb0e055db95047e5e2db1d0f181c8a9fc4a48
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <errno.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <fcntl.h>
13 #include <sys/stat.h>
15 #warning "Only for little endian machines!!!"
16 # define AROS_BE2LONG(l) \
17 ( \
18 ((((unsigned long)(l)) >> 24) & 0x000000FFUL) | \
19 ((((unsigned long)(l)) >> 8) & 0x0000FF00UL) | \
20 ((((unsigned long)(l)) << 8) & 0x00FF0000UL) | \
21 ((((unsigned long)(l)) << 24) & 0xFF000000UL) \
24 #define CMD_READ 1
25 #define CMD_WRITE 2
27 #define ERR_BAD_FILETYPE 1
28 #define ERR_FILE_NOT_FOUND 2
29 #define ERR_FSYS_CORRUPT 3
31 #define T_SHORT 2
33 #define ST_ROOT 1
34 #define ST_USERDIR 2
36 struct Volume {
37 int fd;
38 unsigned short readcommand;
39 unsigned short writecommand;
40 unsigned int startblock;
41 unsigned int countblock;
42 unsigned short SizeBlock;
43 unsigned char flags;
44 unsigned int *blockbuffer;
47 #define VF_IS_TRACKDISK (1<<0)
48 #define VF_MOVE_BB (1<<1)
50 struct BlockNode {
51 unsigned int sector;
52 unsigned short count;
53 unsigned short seg_adr;
56 unsigned int stage2_firstblock[128];
58 int readwriteBlock
60 struct Volume *volume,
61 unsigned int block,
62 void *buffer,
63 size_t length,
64 unsigned short command
67 off_t offset;
68 int retval;
70 offset = (volume->startblock+block)*(volume->SizeBlock*4);
71 if (lseek(volume->fd, offset,SEEK_SET)!=-1)
73 if (command == CMD_READ)
75 if (read(volume->fd, buffer, length)!=-1)
76 return 0;
78 else if (command == CMD_WRITE)
80 if (write(volume->fd, buffer, length)!=-1)
81 return 0;
83 else
84 errno = 0;
86 return errno;
89 unsigned int collectBlockList
91 struct Volume *volume,
92 unsigned int block,
93 struct BlockNode *blocklist
96 int retval;
97 unsigned int first_block;
98 short blk_count,count;
99 unsigned short i;
101 #warning "TODO: logical/physical blocks"
103 initialze stage2-blocklist
104 (it is NULL-terminated)
106 for (blk_count=-1;blocklist[blk_count].sector!=0;blk_count--)
107 blocklist[blk_count].sector = 0;
109 the first block of stage2 will be stored in stage1
110 so skip the first filekey in the first loop
112 #warning "Block read twice"
113 retval=readwriteBlock
115 volume, block, volume->blockbuffer, volume->SizeBlock*4,
116 volume->readcommand
118 i = volume->SizeBlock - 52;
119 first_block = AROS_BE2LONG(volume->blockbuffer[volume->SizeBlock-51]);
120 blk_count=0;
121 do {
122 retval=readwriteBlock
124 volume, block, volume->blockbuffer, volume->SizeBlock*4,
125 volume->readcommand
127 if (retval)
129 printf("ReadError %d\n", retval);
130 return 0;
132 while ((i>=6) && (volume->blockbuffer[i]))
135 if current sector follows right after last sector
136 then we don't need a new element
138 if (
139 (blocklist[blk_count].sector) &&
140 ((blocklist[blk_count].sector+blocklist[blk_count].count)==
141 AROS_BE2LONG(volume->blockbuffer[i]))
144 blocklist[blk_count].count += 1;
146 else
148 blk_count--; /* decrement first */
149 if (blocklist[blk_count-1].sector != 0)
151 printf("There is no more space to save blocklist in stage2\n");
152 return 0;
154 blocklist[blk_count].sector = AROS_BE2LONG(volume->blockbuffer[i]);
155 blocklist[blk_count].count = 1;
157 i--;
159 i = volume->SizeBlock - 51;
160 block = AROS_BE2LONG(volume->blockbuffer[volume->SizeBlock - 2]);
161 } while (block);
163 blocks in blocklist are relative to the first
164 sector of the HD (not partition)
166 i = 0;
167 for (count=-1;count>=blk_count;count--)
169 blocklist[count].sector += volume->startblock;
170 blocklist[count].seg_adr = 0x820 + (i*32);
171 i += blocklist[count].count;
173 return first_block;
176 /**************************************************************************/
178 unsigned int calcChkSum(unsigned short SizeBlock, unsigned int *buffer) {
179 unsigned int sum=0,count=0;
181 for (count=0;count<SizeBlock;count++)
182 sum += AROS_BE2LONG(buffer[count]);
183 return sum;
186 unsigned char capitalch(unsigned char ch, unsigned char flags) {
188 if ((flags==0) || (flags==1))
189 return (unsigned char)((ch>='a') && (ch<='z') ? ch-('a'-'A') : ch);
190 else // DOS\(>=2)
191 return (unsigned char)(((ch>=224) && (ch<=254) && (ch!=247)) ||
192 ((ch>='a') && (ch<='z')) ? ch-('a'-'A') : ch);
195 // str2 is a BCPL string
196 int noCaseStrCmp(char *str1, char *str2, unsigned char flags) {
197 unsigned char length;
199 length=str2++[0];
200 do {
201 if ((*str1==0) && (length==0))
202 return 0;
203 length--;
204 // if ((*str1==0) && (*str2==0)) return 1;
205 } while (capitalch(*str1++,flags)==capitalch(*str2++,flags));
206 str1--;
207 return (*str1) ? 1 : -1;
210 unsigned int getHashKey(char *name,unsigned int tablesize, unsigned char flags) {
211 unsigned int result;
213 result=strlen(name);
214 while (*name!=0)
215 result=(result * 13 +capitalch(*name++,flags)) & 0x7FF;
216 return result%tablesize;
219 int getHeaderBlock(struct Volume *volume, char *name, unsigned int *dirh) {
220 int key;
222 key = getHashKey(name, (volume->SizeBlock-51)-6+1, 1);
223 if (!dirh[6+key])
224 return ERR_FILE_NOT_FOUND;
225 readwriteBlock
227 volume,
228 AROS_BE2LONG(dirh[6+key]),
229 dirh,
230 volume->SizeBlock*4,
231 volume->readcommand
233 if (calcChkSum(volume->SizeBlock, dirh))
234 return ERR_FSYS_CORRUPT;
235 if (AROS_BE2LONG(dirh[0]) != T_SHORT)
236 return ERR_BAD_FILETYPE;
237 while (noCaseStrCmp(name,
238 (char *)((unsigned long)dirh+((volume->SizeBlock-20)*4)),1)
239 != 0)
241 if (!dirh[volume->SizeBlock-4])
242 return ERR_FILE_NOT_FOUND;
243 readwriteBlock
245 volume,
246 AROS_BE2LONG(dirh[volume->SizeBlock-4]),
247 dirh,
248 volume->SizeBlock*4,
249 volume->readcommand
251 if (calcChkSum(volume->SizeBlock, (unsigned int *)dirh))
252 return ERR_FSYS_CORRUPT;
253 if (AROS_BE2LONG(dirh[0]) != T_SHORT)
254 return ERR_BAD_FILETYPE;
256 return 0;
259 int findFile(struct Volume *volume, char *name, unsigned int *buffer) {
260 char dname[32];
261 char *nbuf;
262 int errnum;
264 readwriteBlock
266 volume,
267 volume->countblock/2,
268 buffer,
269 volume->SizeBlock*4,
270 volume->readcommand
272 name++;
273 while (*name)
275 if (
276 (AROS_BE2LONG(buffer[volume->SizeBlock-1]) != ST_ROOT) &&
277 (AROS_BE2LONG(buffer[volume->SizeBlock-1]) != ST_USERDIR)
279 return ERR_BAD_FILETYPE;
280 nbuf = dname;
281 while ((*name != '/') && (*name))
282 *nbuf++ = *name++;
283 if (*name == '/')
284 name++;
285 *nbuf = 0;
286 errnum = getHeaderBlock(volume, dname, buffer);
287 if (errnum)
288 return errnum;
290 return 0;
294 void installStageFiles(struct Volume *volume) {
295 int retval;
296 unsigned int block;
298 retval=findFile(volume, "/boot/pc/grub/stage2", stage2_firstblock);
299 if ( retval == 0 )
301 block = AROS_BE2LONG(stage2_firstblock[1]);
302 /* read first data block */
303 readwriteBlock
305 volume,
306 AROS_BE2LONG(stage2_firstblock[volume->SizeBlock-51]),
307 (void *)stage2_firstblock,
308 volume->SizeBlock*4,
309 volume->readcommand
311 /* save first BB (with flags) */
312 if (volume->flags & VF_MOVE_BB)
314 readwriteBlock
316 volume, 1, volume->blockbuffer, 512,
317 volume->writecommand
320 if (
322 block=collectBlockList
324 volume, block,
325 (struct BlockNode *)&stage2_firstblock[128]
330 if (findFile(volume, "/boot/pc/grub/stage1", volume->blockbuffer) == 0)
332 /* read first data block of stage1 */
333 retval = readwriteBlock
335 volume,
336 AROS_BE2LONG(volume->blockbuffer[volume->SizeBlock-51]),
337 volume->blockbuffer,
338 512,
339 volume->readcommand
341 if (retval == 0)
343 /* write stage1 as BB */
344 volume->blockbuffer[17]=block;
345 retval = readwriteBlock
347 volume, 0,
348 volume->blockbuffer, 512, volume->writecommand
350 if (retval)
351 printf("WriteError %d\n", retval);
352 else
354 /* write first data block of stage2 */
355 readwriteBlock
357 volume,
358 block,
359 stage2_firstblock,
360 512,
361 volume->writecommand
365 else
366 printf("ReadError %d\n", retval);
368 else
369 printf("stage1 file not found\n");
372 else
373 printf("stage2: %d\n",retval);
376 struct Volume *initVolume(char *filename) {
377 struct Volume *volume=0;
378 struct stat stat;
379 char *error;
380 unsigned int retval;
382 if (lstat(filename, &stat)==0)
384 volume = (struct Volume *)calloc(1, sizeof(struct Volume));
385 if (volume)
387 volume->SizeBlock = 128;
388 volume->blockbuffer = (unsigned int *)calloc(1, volume->SizeBlock*4);
389 if (volume->blockbuffer)
391 volume->fd = open(filename, O_RDWR);
392 if (volume->fd)
394 #warning "No support for partitions"
395 volume->startblock = 0;
396 volume->countblock = stat.st_size/(volume->SizeBlock*4);
397 volume->readcommand = CMD_READ;
398 volume->writecommand = CMD_WRITE;
399 retval = readwriteBlock
401 volume, 0,
402 volume->blockbuffer, 512, volume->readcommand
404 if (retval == 0)
406 if ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)!=0x444F5300)
408 retval = readwriteBlock
410 volume, 1,
411 volume->blockbuffer, 512, volume->readcommand
414 else
415 volume->flags |= VF_MOVE_BB;
416 if (
417 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)==0x444F5300) &&
418 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFF)>0)
421 return volume;
423 else
424 error = "No Amiga FFS disk";
426 else
427 error = "ReadError";
429 else
430 error = "Couldn't open file";
431 free(volume->blockbuffer);
433 else
434 error = "Not enough memory";
435 free(volume);
436 volume = 0;
438 else
439 error = "Not enough memory";
441 else
442 error = "lstat() error";
443 printf("%s\n",error);
444 return 0;
447 void uninitVolume(struct Volume *volume) {
449 close(volume->fd);
450 free(volume->blockbuffer);
451 free(volume);
454 void checkBootCode(struct Volume *volume) {
455 printf("CHECK not implemented yet\n");
458 void removeBootCode(struct Volume *volume) {
459 int retval;
461 retval = readwriteBlock
463 volume, 1,
464 volume->blockbuffer, 512, volume->readcommand
466 if (retval)
467 printf("ReadError %d\n", retval);
468 else
470 if ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)==0x444F5300)
472 retval = readwriteBlock
474 volume, 0,
475 volume->blockbuffer, 512, volume->writecommand
477 if (retval)
478 printf("WriteError %d\n", retval);
483 int main(int argc, char **argv) {
484 struct Volume *volume;
486 if (
487 (argc == 1) ||
488 ((argc == 2) && (strcmp(argv[1],"--help")==0)) ||
489 (argc > 3)
491 printf("Usage: %s filename --noboot --check\n",argv[0]);
492 else
494 volume = initVolume(argv[1]);
495 if (volume)
497 if (argc == 3)
499 if (strcmp(argv[2],"--noboot")==0)
500 removeBootCode(volume);
501 else if (strcmp(argv[2],"--check")==0)
502 checkBootCode(volume);
504 else
505 installStageFiles(volume);
506 uninitVolume(volume);
509 return 0;