2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
12 #include <proto/dos.h>
13 #include <proto/exec.h>
15 #include <devices/newstyle.h>
16 #include <devices/trackdisk.h>
18 #include <dos/dosextens.h>
19 #include <dos/filehandler.h>
20 #include <exec/errors.h>
22 #include <exec/memory.h>
23 #include <exec/types.h>
24 #include <exec/ports.h>
25 #include <aros/macros.h>
31 struct FileSysStartupMsg
*fssm
;
41 #define VF_IS_TRACKDISK (1<<0)
42 #define VF_MOVE_BB (1<<1)
50 ULONG stage2_firstblock
[128];
54 struct Volume
*volume
,
55 ULONG block
, APTR buffer
, ULONG length
,
62 volume
->iotd
->iotd_Req
.io_Command
= command
;
63 volume
->iotd
->iotd_Req
.io_Length
= length
;
64 volume
->iotd
->iotd_Req
.io_Data
= buffer
;
65 offset
= (UQUAD
)(volume
->startblock
+block
)*(volume
->SizeBlock
*4);
66 volume
->iotd
->iotd_Req
.io_Offset
= offset
& 0xFFFFFFFF;
67 volume
->iotd
->iotd_Req
.io_Actual
= offset
>>32;
68 retval
= DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
69 if (volume
->flags
& VF_IS_TRACKDISK
)
71 volume
->iotd
->iotd_Req
.io_Command
= TD_MOTOR
;
72 volume
->iotd
->iotd_Req
.io_Length
= 0;
73 DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
78 ULONG
collectBlockList(struct Volume
*volume
, ULONG block
, struct BlockNode
*blocklist
) {
79 ULONG retval
, first_block
;
83 #warning "TODO: logical/physical blocks"
85 initialze stage2-blocklist
86 (it is NULL-terminated)
88 for (blk_count
=-1;blocklist
[blk_count
].sector
!=0;blk_count
--)
89 blocklist
[blk_count
].sector
= 0;
91 the first block of stage2 will be stored in stage1
92 so skip the first filekey in the first loop
94 #warning "Block read twice"
97 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
100 i
= volume
->SizeBlock
- 52;
101 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
104 retval
=readwriteBlock
106 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
111 printf("ReadError %ld\n", retval
);
114 while ((i
>=6) && (volume
->blockbuffer
[i
]))
117 if current sector follows right after last sector
118 then we don't need a new element
121 (blocklist
[blk_count
].sector
) &&
122 ((blocklist
[blk_count
].sector
+blocklist
[blk_count
].count
)==
123 AROS_BE2LONG(volume
->blockbuffer
[i
]))
126 blocklist
[blk_count
].count
+= 1;
130 blk_count
--; /* decrement first */
131 if (blocklist
[blk_count
-1].sector
!= 0)
133 printf("There is no more space to save blocklist in stage2\n");
136 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
137 blocklist
[blk_count
].count
= 1;
141 i
= volume
->SizeBlock
- 51;
142 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
145 blocks in blocklist are relative to the first
146 sector of the HD (not partition)
149 for (count
=-1;count
>=blk_count
;count
--)
151 blocklist
[count
].sector
+= volume
->startblock
;
152 blocklist
[count
].seg_adr
= 0x820 + (i
*32);
153 i
+= blocklist
[count
].count
;
158 /*************************************
159 Name : installStageFiles
160 Descr.: install stage1 and initialize stage2
161 Input : volume - the volume to install on
162 use_mbr - flag to use MBR
163 stage2_drive - the unit stage2 is located
164 **************************************/
165 void installStageFiles(struct Volume
*volume
, LONG use_mbr
, UBYTE stage2_drive
) {
167 struct FileInfoBlock fib
;
174 strcpy(stagename
, (char *)volume
->drivename
);
175 strcat(stagename
, "Boot/grub/stage2");
176 fh
= Open(stagename
,MODE_OLDFILE
);
179 if (Examine(fh
, &fib
))
181 if (Read(fh
, stage2_firstblock
, 512) == 512)
183 if ((volume
->flags
& VF_MOVE_BB
) && !use_mbr
)
187 volume
, 1, volume
->blockbuffer
, 512,
193 block
=collectBlockList
195 volume
, fib
.fib_DiskKey
,
196 (struct BlockNode
*)&stage2_firstblock
[128]
201 if (Seek(fh
, 0, OFFSET_BEGINNING
)!=-1)
203 if (Write(fh
, stage2_firstblock
, 512)==512)
205 strcpy(stagename
, (char *)volume
->drivename
);
206 strcat(stagename
, "Boot/grub/stage1");
207 fh2
= Open(stagename
, MODE_OLDFILE
);
210 if (Read(fh2
, volume
->blockbuffer
, 512) == 512)
212 volume
->blockbuffer
[17]=block
;
216 volume
->blockbuffer
[17] += volume
->startblock
;
217 volume
->startblock
= 0;
218 retval
= readwriteBlock
221 stage2_firstblock
, 512, volume
->readcommand
223 /* copy BPB (BIOS Parameter Block)*/
226 (APTR
)((char *)stage2_firstblock
+0x3),
227 (APTR
)((char *)volume
->blockbuffer
+0x3),
230 /* copy partition table */
233 (APTR
)((char *)stage2_firstblock
+0x1BE),
234 (APTR
)((char *)volume
->blockbuffer
+0x1BE),
237 /* store the drive num stage2 is stored on */
238 ((char *)volume
->blockbuffer
)[0x40] = stage2_drive
+0x80;
242 retval
= readwriteBlock
245 volume
->blockbuffer
, 512, volume
->writecommand
248 printf("WriteError %ld\n", retval
);
251 printf("WriteErrro %ld\n", retval
);
289 PrintFault(error
, errstr
);
292 void nsdCheck(struct Volume
*volume
) {
293 struct NSDeviceQueryResult nsdq
;
297 (volume
->startblock
+volume
->countblock
)* /* last block */
298 (volume
->SizeBlock
*4/512) /* 1 portion (block) equals 512 (bytes) */
301 nsdq
.SizeAvailable
=0;
302 nsdq
.DevQueryFormat
=0;
303 volume
->iotd
->iotd_Req
.io_Command
=NSCMD_DEVICEQUERY
;
304 volume
->iotd
->iotd_Req
.io_Data
=&nsdq
;
305 volume
->iotd
->iotd_Req
.io_Length
=sizeof(struct NSDeviceQueryResult
);
306 if (DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
)==IOERR_NOCMD
)
308 printf("Device doesn't understand NSD-Query\n");
313 (volume
->iotd
->iotd_Req
.io_Actual
>sizeof(struct NSDeviceQueryResult
)) ||
314 (volume
->iotd
->iotd_Req
.io_Actual
==0) ||
315 (volume
->iotd
->iotd_Req
.io_Actual
!=nsdq
.SizeAvailable
)
318 printf("WARNING wrong io_Actual using NSD\n");
322 if (nsdq
.DeviceType
!= NSDEVTYPE_TRACKDISK
)
323 printf("WARNING no trackdisk type\n");
324 for (cmdcheck
=nsdq
.SupportedCommands
;*cmdcheck
;cmdcheck
++)
326 if (*cmdcheck
== NSCMD_TD_READ64
)
327 volume
->readcommand
= NSCMD_TD_READ64
;
328 if (*cmdcheck
== NSCMD_TD_WRITE64
);
329 volume
->writecommand
= NSCMD_TD_WRITE64
;
332 (volume
->readcommand
!=NSCMD_TD_READ64
) ||
333 (volume
->writecommand
!=NSCMD_TD_WRITE64
)
335 printf("WARNING no READ64/WRITE64\n");
341 struct Volume
*initVolume(STRPTR drivename
, LONG use_mbr
) {
342 struct Volume
*volume
=0;
343 struct FileSysStartupMsg
*fssm
;
346 struct DeviceNode
*dn
;
349 ULONG error
=0,retval
;
352 for (i
=0;(drivename
[i
]) && (drivename
[i
]!=':');i
++)
353 dname
[i
]=drivename
[i
];
355 dl
= LockDosList(LDF_READ
| LDF_DEVICES
);
358 dn
= (struct DeviceNode
*)FindDosEntry(dl
, dname
, LDF_DEVICES
);
359 UnLockDosList(LDF_READ
| LDF_DEVICES
);
362 if (IsFileSystem(drivename
))
364 fssm
= (struct FileSysStartupMsg
*)BADDR(dn
->dn_Startup
);
367 if (strcmp(AROS_BSTR_ADDR(fssm
->fssm_Device
),"ide.device")!=0)
369 error
= ERROR_OBJECT_WRONG_TYPE
;
370 errstr
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
374 if (fssm
->fssm_Unit
!=0)
376 error
= ERROR_OBJECT_WRONG_TYPE
;
377 errstr
= "MBR can only be stored on the first HD";
383 volume
= AllocVec(sizeof(struct Volume
), MEMF_PUBLIC
| MEMF_CLEAR
);
387 volume
->drivename
= drivename
;
388 volume
->mp
= CreateMsgPort();
391 volume
->iotd
= (struct IOExtTD
*)CreateIORequest(volume
->mp
, sizeof(struct IOExtTD
));
394 de
= volume
->fssm
->fssm_Environ
;
395 volume
->SizeBlock
= de
->de_SizeBlock
;
396 volume
->blockbuffer
= AllocVec(volume
->SizeBlock
*4, MEMF_PUBLIC
| MEMF_CLEAR
);
397 if (volume
->blockbuffer
)
402 AROS_BSTR_ADDR(volume
->fssm
->fssm_Device
),
403 volume
->fssm
->fssm_Unit
,
404 (struct IORequest
*)&volume
->iotd
->iotd_Req
,
405 volume
->fssm
->fssm_Flags
409 if (strcmp(AROS_BSTR_ADDR(volume
->fssm
->fssm_Device
), "trackdisk.device") == 0)
410 volume
->flags
|= VF_IS_TRACKDISK
;
414 de
->de_BlocksPerTrack
;
418 de
->de_HighCyl
-de
->de_LowCyl
+1
419 )*de
->de_Surfaces
*de
->de_BlocksPerTrack
421 volume
->readcommand
= CMD_READ
;
422 volume
->writecommand
= CMD_WRITE
;
424 retval
= readwriteBlock
427 volume
->blockbuffer
, 512, volume
->readcommand
431 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300)
433 retval
= readwriteBlock
436 volume
->blockbuffer
, 512, volume
->readcommand
440 volume
->flags
|= VF_MOVE_BB
;
442 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300) &&
443 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF)>0)
449 error
= ERROR_NOT_A_DOS_DISK
;
453 error
= ERROR_UNKNOWN
;
454 errstr
= "Read Error";
459 error
= ERROR_UNKNOWN
;
460 errstr
= "OpenDevice() Error";
462 FreeVec(volume
->blockbuffer
);
465 error
= ERROR_NO_FREE_STORE
;
468 error
= ERROR_NO_FREE_STORE
;
469 DeleteMsgPort(volume
->mp
);
472 error
= ERROR_NO_FREE_STORE
;
477 error
= ERROR_NO_FREE_STORE
;
485 error
= ERROR_OBJECT_NOT_FOUND
;
491 error
= ERROR_UNKNOWN
;
492 errstr
= "LockDosList Error";
494 PrintFault(error
, errstr
);
498 void uninitVolume(struct Volume
*volume
) {
500 FreeVec(volume
->blockbuffer
);
501 CloseDevice((struct IORequest
*)&volume
->iotd
->iotd_Req
);
502 DeleteIORequest((struct IORequest
*)volume
->iotd
);
503 DeleteMsgPort(volume
->mp
);
507 void checkBootCode(struct Volume
*volume
) {
508 printf("CHECK not implemented yet\n");
511 void removeBootCode(struct Volume
*volume
) {
514 retval
= readwriteBlock
517 volume
->blockbuffer
, 512, volume
->readcommand
520 printf("ReadError %ld\n", retval
);
523 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
525 retval
= readwriteBlock
528 volume
->blockbuffer
, 512, volume
->writecommand
531 printf("WriteError %ld\n", retval
);
537 LONG myargs
[5]={0,0,0,0,0};
538 struct RDArgs
*rdargs
;
539 struct Volume
*volume
;
541 rdargs
= ReadArgs("DRIVE/A,NOBOOT/S,CHECK/S,FFS/S,MBR/S",myargs
,NULL
);
544 volume
= initVolume((STRPTR
)myargs
[0], myargs
[4]);
548 removeBootCode(volume
);
550 checkBootCode(volume
);
552 installStageFiles(volume
, myargs
[4], volume
->fssm
->fssm_Unit
);
553 uninitVolume(volume
);
558 PrintFault(IoErr(), NULL
);