2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
14 #warning "Only for little endian machines!!!"
15 # define AROS_BE2LONG(l) \
17 ((((unsigned long)(l)) >> 24) & 0x000000FFUL) | \
18 ((((unsigned long)(l)) >> 8) & 0x0000FF00UL) | \
19 ((((unsigned long)(l)) << 8) & 0x00FF0000UL) | \
20 ((((unsigned long)(l)) << 24) & 0xFF000000UL) \
26 #define ERR_BAD_FILETYPE 1
27 #define ERR_FILE_NOT_FOUND 2
28 #define ERR_FSYS_CORRUPT 3
37 unsigned short readcommand
;
38 unsigned short writecommand
;
39 unsigned int startblock
;
40 unsigned int countblock
;
41 unsigned short SizeBlock
;
43 unsigned int *blockbuffer
;
46 #define VF_IS_TRACKDISK (1<<0)
47 #define VF_MOVE_BB (1<<1)
52 unsigned short seg_adr
;
55 unsigned int stage2_firstblock
[128];
59 struct Volume
*volume
,
63 unsigned short command
69 offset
= (volume
->startblock
+block
)*(volume
->SizeBlock
*4);
70 if (lseek(volume
->fd
, offset
,SEEK_SET
)!=-1)
72 if (command
== CMD_READ
)
74 if (read(volume
->fd
, buffer
, length
)!=-1)
77 else if (command
== CMD_WRITE
)
79 if (write(volume
->fd
, buffer
, length
)!=-1)
88 unsigned int collectBlockList
90 struct Volume
*volume
,
92 struct BlockNode
*blocklist
95 unsigned int retval
, first_block
;
96 short blk_count
,count
;
99 #warning "TODO: logical/physical blocks"
101 initialze stage2-blocklist
102 (it is NULL-terminated)
104 for (blk_count
=-1;blocklist
[blk_count
].sector
!=0;blk_count
--)
105 blocklist
[blk_count
].sector
= 0;
107 the first block of stage2 will be stored in stage1
108 so skip the first filekey in the first loop
110 #warning "Block read twice"
111 retval
=readwriteBlock
113 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
116 i
= volume
->SizeBlock
- 52;
117 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
120 retval
=readwriteBlock
122 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
127 printf("ReadError %ld\n", retval
);
130 while ((i
>=6) && (volume
->blockbuffer
[i
]))
133 if current sector follows right after last sector
134 then we don't need a new element
137 (blocklist
[blk_count
].sector
) &&
138 ((blocklist
[blk_count
].sector
+blocklist
[blk_count
].count
)==
139 AROS_BE2LONG(volume
->blockbuffer
[i
]))
142 blocklist
[blk_count
].count
+= 1;
146 blk_count
--; /* decrement first */
147 if (blocklist
[blk_count
-1].sector
!= 0)
149 printf("There is no more space to save blocklist in stage2\n");
152 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
153 blocklist
[blk_count
].count
= 1;
157 i
= volume
->SizeBlock
- 51;
158 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
161 blocks in blocklist are relative to the first
162 sector of the HD (not partition)
165 for (count
=-1;count
>=blk_count
;count
--)
167 blocklist
[count
].sector
+= volume
->startblock
;
168 blocklist
[count
].seg_adr
= 0x820 + (i
*32);
169 i
+= blocklist
[count
].count
;
174 /**************************************************************************/
176 unsigned int calcChkSum(unsigned short SizeBlock
, unsigned int *buffer
) {
177 unsigned int sum
=0,count
=0;
179 for (count
=0;count
<SizeBlock
;count
++)
180 sum
+= AROS_BE2LONG(buffer
[count
]);
184 unsigned char capitalch(unsigned char ch
, unsigned char flags
) {
186 if ((flags
==0) || (flags
==1))
187 return (unsigned char)((ch
>='a') && (ch
<='z') ? ch
-('a'-'A') : ch
);
189 return (unsigned char)(((ch
>=224) && (ch
<=254) && (ch
!=247)) ||
190 ((ch
>='a') && (ch
<='z')) ? ch
-('a'-'A') : ch
);
193 // str2 is a BCPL string
194 int noCaseStrCmp(char *str1
, char *str2
, unsigned char flags
) {
195 unsigned char length
;
199 if ((*str1
==0) && (length
==0))
202 // if ((*str1==0) && (*str2==0)) return 1;
203 } while (capitalch(*str1
++,flags
)==capitalch(*str2
++,flags
));
205 return (*str1
) ? 1 : -1;
208 unsigned int getHashKey(char *name
,unsigned int tablesize
, unsigned char flags
) {
213 result
=(result
* 13 +capitalch(*name
++,flags
)) & 0x7FF;
214 return result
%tablesize
;
217 int getHeaderBlock(struct Volume
*volume
, char *name
, unsigned int *dirh
) {
220 key
= getHashKey(name
, (volume
->SizeBlock
-51)-6+1, 1);
222 return ERR_FILE_NOT_FOUND
;
226 AROS_BE2LONG(dirh
[6+key
]),
231 if (calcChkSum(volume
->SizeBlock
, dirh
))
232 return ERR_FSYS_CORRUPT
;
233 if (AROS_BE2LONG(dirh
[0]) != T_SHORT
)
234 return ERR_BAD_FILETYPE
;
235 while (noCaseStrCmp(name
,(char *)((unsigned int)dirh
+((volume
->SizeBlock
-20)*4)),1) != 0)
237 if (!dirh
[volume
->SizeBlock
-4])
238 return ERR_FILE_NOT_FOUND
;
242 AROS_BE2LONG(dirh
[volume
->SizeBlock
-4]),
247 if (calcChkSum(volume
->SizeBlock
, (unsigned int *)dirh
))
248 return ERR_FSYS_CORRUPT
;
249 if (AROS_BE2LONG(dirh
[0]) != T_SHORT
)
250 return ERR_BAD_FILETYPE
;
255 int findFile(struct Volume
*volume
, char *name
, unsigned int *buffer
) {
263 volume
->countblock
/2,
272 (AROS_BE2LONG(buffer
[volume
->SizeBlock
-1]) != ST_ROOT
) &&
273 (AROS_BE2LONG(buffer
[volume
->SizeBlock
-1]) != ST_USERDIR
)
275 return ERR_BAD_FILETYPE
;
277 while ((*name
!= '/') && (*name
))
282 errnum
= getHeaderBlock(volume
, dname
, buffer
);
290 void installStageFiles(struct Volume
*volume
) {
291 unsigned int block
,retval
;
293 retval
=findFile(volume
, "/boot/grub/stage2", stage2_firstblock
);
296 block
= AROS_BE2LONG(stage2_firstblock
[1]);
297 /* read first data block */
301 AROS_BE2LONG(stage2_firstblock
[volume
->SizeBlock
-51]),
302 (void *)stage2_firstblock
,
306 /* save first BB (with flags) */
307 if (volume
->flags
& VF_MOVE_BB
)
311 volume
, 1, volume
->blockbuffer
, 512,
317 block
=collectBlockList
320 (struct BlockNode
*)&stage2_firstblock
[128]
325 if (findFile(volume
, "/boot/grub/stage1", volume
->blockbuffer
) == 0)
327 /* read first data block of stage1 */
328 retval
= readwriteBlock
331 AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]),
338 /* write stage1 as BB */
339 volume
->blockbuffer
[17]=block
;
340 retval
= readwriteBlock
343 volume
->blockbuffer
, 512, volume
->writecommand
346 printf("WriteError %ld\n", retval
);
349 /* write first data block of stage2 */
361 printf("ReadError %d\n", retval
);
364 printf("stage1 file not found\n");
368 printf("stage2: %d\n",retval
);
371 struct Volume
*initVolume(char *filename
) {
372 struct Volume
*volume
=0;
377 if (lstat(filename
, &stat
)==0)
379 volume
= (struct Volume
*)calloc(1, sizeof(struct Volume
));
382 volume
->SizeBlock
= 128;
383 volume
->blockbuffer
= (unsigned int *)calloc(1, volume
->SizeBlock
*4);
384 if (volume
->blockbuffer
)
386 volume
->fd
= open(filename
, O_RDWR
);
389 #warning "No support for partitions"
390 volume
->startblock
= 0;
391 volume
->countblock
= stat
.st_size
/(volume
->SizeBlock
*4);
392 volume
->readcommand
= CMD_READ
;
393 volume
->writecommand
= CMD_WRITE
;
394 retval
= readwriteBlock
397 volume
->blockbuffer
, 512, volume
->readcommand
401 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300)
403 retval
= readwriteBlock
406 volume
->blockbuffer
, 512, volume
->readcommand
410 volume
->flags
|= VF_MOVE_BB
;
412 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300) &&
413 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF)>0)
419 error
= "No Amiga FFS disk";
425 error
= "Couldn't open file";
426 free(volume
->blockbuffer
);
429 error
= "Not enough memory";
434 error
= "Not enough memory";
437 error
= "lstat() error";
438 printf("%s\n",error
);
442 void uninitVolume(struct Volume
*volume
) {
445 free(volume
->blockbuffer
);
449 void checkBootCode(struct Volume
*volume
) {
450 printf("CHECK not implemented yet\n");
453 void removeBootCode(struct Volume
*volume
) {
456 retval
= readwriteBlock
459 volume
->blockbuffer
, 512, volume
->readcommand
462 printf("ReadError %ld\n", retval
);
465 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
467 retval
= readwriteBlock
470 volume
->blockbuffer
, 512, volume
->writecommand
473 printf("WriteError %ld\n", retval
);
478 int main(int argc
, char **argv
) {
479 struct Volume
*volume
;
483 ((argc
== 2) && (strcmp(argv
[1],"--help")==0)) ||
486 printf("Usage: %s filename --noboot --check\n",argv
[0]);
489 volume
= initVolume(argv
[1]);
494 if (strcmp(argv
[2],"--noboot")==0)
495 removeBootCode(volume
);
496 else if (strcmp(argv
[2],"--check")==0)
497 checkBootCode(volume
);
500 installStageFiles(volume
);
501 uninitVolume(volume
);