2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
15 #warning "Only for little endian machines!!!"
16 # define AROS_BE2LONG(l) \
18 ((((unsigned long)(l)) >> 24) & 0x000000FFUL) | \
19 ((((unsigned long)(l)) >> 8) & 0x0000FF00UL) | \
20 ((((unsigned long)(l)) << 8) & 0x00FF0000UL) | \
21 ((((unsigned long)(l)) << 24) & 0xFF000000UL) \
27 #define ERR_BAD_FILETYPE 1
28 #define ERR_FILE_NOT_FOUND 2
29 #define ERR_FSYS_CORRUPT 3
38 unsigned short readcommand
;
39 unsigned short writecommand
;
40 unsigned int startblock
;
41 unsigned int countblock
;
42 unsigned short SizeBlock
;
44 unsigned int *blockbuffer
;
47 #define VF_IS_TRACKDISK (1<<0)
48 #define VF_MOVE_BB (1<<1)
53 unsigned short seg_adr
;
56 unsigned int stage2_firstblock
[128];
60 struct Volume
*volume
,
64 unsigned short command
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)
78 else if (command
== CMD_WRITE
)
80 if (write(volume
->fd
, buffer
, length
)!=-1)
89 unsigned int collectBlockList
91 struct Volume
*volume
,
93 struct BlockNode
*blocklist
97 unsigned int first_block
;
98 short blk_count
,count
;
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,
118 i
= volume
->SizeBlock
- 52;
119 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
122 retval
=readwriteBlock
124 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
129 printf("ReadError %d\n", retval
);
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
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;
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");
154 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
155 blocklist
[blk_count
].count
= 1;
159 i
= volume
->SizeBlock
- 51;
160 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
163 blocks in blocklist are relative to the first
164 sector of the HD (not partition)
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
;
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
]);
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
);
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
;
201 if ((*str1
==0) && (length
==0))
204 // if ((*str1==0) && (*str2==0)) return 1;
205 } while (capitalch(*str1
++,flags
)==capitalch(*str2
++,flags
));
207 return (*str1
) ? 1 : -1;
210 unsigned int getHashKey(char *name
,unsigned int tablesize
, unsigned char flags
) {
215 result
=(result
* 13 +capitalch(*name
++,flags
)) & 0x7FF;
216 return result
%tablesize
;
219 int getHeaderBlock(struct Volume
*volume
, char *name
, unsigned int *dirh
) {
222 key
= getHashKey(name
, (volume
->SizeBlock
-51)-6+1, 1);
224 return ERR_FILE_NOT_FOUND
;
228 AROS_BE2LONG(dirh
[6+key
]),
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)
241 if (!dirh
[volume
->SizeBlock
-4])
242 return ERR_FILE_NOT_FOUND
;
246 AROS_BE2LONG(dirh
[volume
->SizeBlock
-4]),
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
;
259 int findFile(struct Volume
*volume
, char *name
, unsigned int *buffer
) {
267 volume
->countblock
/2,
276 (AROS_BE2LONG(buffer
[volume
->SizeBlock
-1]) != ST_ROOT
) &&
277 (AROS_BE2LONG(buffer
[volume
->SizeBlock
-1]) != ST_USERDIR
)
279 return ERR_BAD_FILETYPE
;
281 while ((*name
!= '/') && (*name
))
286 errnum
= getHeaderBlock(volume
, dname
, buffer
);
294 void installStageFiles(struct Volume
*volume
) {
298 retval
=findFile(volume
, "/boot/pc/grub/stage2", stage2_firstblock
);
301 block
= AROS_BE2LONG(stage2_firstblock
[1]);
302 /* read first data block */
306 AROS_BE2LONG(stage2_firstblock
[volume
->SizeBlock
-51]),
307 (void *)stage2_firstblock
,
311 /* save first BB (with flags) */
312 if (volume
->flags
& VF_MOVE_BB
)
316 volume
, 1, volume
->blockbuffer
, 512,
322 block
=collectBlockList
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
336 AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]),
343 /* write stage1 as BB */
344 volume
->blockbuffer
[17]=block
;
345 retval
= readwriteBlock
348 volume
->blockbuffer
, 512, volume
->writecommand
351 printf("WriteError %d\n", retval
);
354 /* write first data block of stage2 */
366 printf("ReadError %d\n", retval
);
369 printf("stage1 file not found\n");
373 printf("stage2: %d\n",retval
);
376 struct Volume
*initVolume(char *filename
) {
377 struct Volume
*volume
=0;
382 if (lstat(filename
, &stat
)==0)
384 volume
= (struct Volume
*)calloc(1, sizeof(struct 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
);
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
402 volume
->blockbuffer
, 512, volume
->readcommand
406 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300)
408 retval
= readwriteBlock
411 volume
->blockbuffer
, 512, volume
->readcommand
415 volume
->flags
|= VF_MOVE_BB
;
417 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300) &&
418 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF)>0)
424 error
= "No Amiga FFS disk";
430 error
= "Couldn't open file";
431 free(volume
->blockbuffer
);
434 error
= "Not enough memory";
439 error
= "Not enough memory";
442 error
= "lstat() error";
443 printf("%s\n",error
);
447 void uninitVolume(struct Volume
*volume
) {
450 free(volume
->blockbuffer
);
454 void checkBootCode(struct Volume
*volume
) {
455 printf("CHECK not implemented yet\n");
458 void removeBootCode(struct Volume
*volume
) {
461 retval
= readwriteBlock
464 volume
->blockbuffer
, 512, volume
->readcommand
467 printf("ReadError %d\n", retval
);
470 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
472 retval
= readwriteBlock
475 volume
->blockbuffer
, 512, volume
->writecommand
478 printf("WriteError %d\n", retval
);
483 int main(int argc
, char **argv
) {
484 struct Volume
*volume
;
488 ((argc
== 2) && (strcmp(argv
[1],"--help")==0)) ||
491 printf("Usage: %s filename --noboot --check\n",argv
[0]);
494 volume
= initVolume(argv
[1]);
499 if (strcmp(argv
[2],"--noboot")==0)
500 removeBootCode(volume
);
501 else if (strcmp(argv
[2],"--check")==0)
502 checkBootCode(volume
);
505 installStageFiles(volume
);
506 uninitVolume(volume
);