2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
8 /******************************************************************************
17 DRIVE/A, NOBOOT/S, CHECK/S, FFS/S
25 Saves a bootblock to a floppy disk. If the NOBOOT is appointed it
26 will not be able to be boot on computer startup (Amiga only)
30 DRIVE -- Show information on file system devices
31 NOBOOT -- Should be set on PC Floppy drives
32 CHECK -- Verify the existing bootblock
33 FFS -- For FFS formatted Floppy disks
39 This is a pretty useless command for PC-Drives, since most systems
40 require grub to be present on disk for AROS to boot.
44 Install df0: NOBOOT FFS
50 Install-i386-pc, Sys:System/Format
56 ******************************************************************************/
60 #include <proto/dos.h>
61 #include <proto/exec.h>
62 #include <proto/alib.h>
64 #include <devices/newstyle.h>
65 #include <devices/trackdisk.h>
67 #include <dos/dosextens.h>
68 #include <dos/filehandler.h>
69 #include <exec/errors.h>
71 #include <exec/memory.h>
72 #include <exec/types.h>
73 #include <exec/ports.h>
74 #include <aros/macros.h>
80 struct FileSysStartupMsg
*fssm
;
90 #define VF_IS_TRACKDISK (1<<0)
91 #define VF_MOVE_BB (1<<1)
99 ULONG stage2_firstblock
[128];
103 struct Volume
*volume
,
104 ULONG block
, APTR buffer
, ULONG length
,
111 volume
->iotd
->iotd_Req
.io_Command
= command
;
112 volume
->iotd
->iotd_Req
.io_Length
= length
;
113 volume
->iotd
->iotd_Req
.io_Data
= buffer
;
114 offset
= (UQUAD
)(volume
->startblock
+block
)*(volume
->SizeBlock
*4);
115 volume
->iotd
->iotd_Req
.io_Offset
= offset
& 0xFFFFFFFF;
116 volume
->iotd
->iotd_Req
.io_Actual
= offset
>>32;
117 retval
= DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
118 if (volume
->flags
& VF_IS_TRACKDISK
)
120 volume
->iotd
->iotd_Req
.io_Command
= TD_MOTOR
;
121 volume
->iotd
->iotd_Req
.io_Length
= 0;
122 DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
127 ULONG
collectBlockList(struct Volume
*volume
, ULONG block
, struct BlockNode
*blocklist
) {
128 ULONG retval
, first_block
;
129 WORD blk_count
,count
;
132 /* TODO: logical/physical blocks */
134 initialze stage2-blocklist
135 (it is NULL-terminated)
137 for (blk_count
=-1;blocklist
[blk_count
].sector
!=0;blk_count
--)
138 blocklist
[blk_count
].sector
= 0;
140 the first block of stage2 will be stored in stage1
141 so skip the first filekey in the first loop
143 /* FIXME: Block read twice */
144 retval
=readwriteBlock
146 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
149 i
= volume
->SizeBlock
- 52;
150 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
153 retval
=readwriteBlock
155 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
160 Printf("ReadError %lu\n", (long)retval
);
163 while ((i
>=6) && (volume
->blockbuffer
[i
]))
166 if current sector follows right after last sector
167 then we don't need a new element
170 (blocklist
[blk_count
].sector
) &&
171 ((blocklist
[blk_count
].sector
+blocklist
[blk_count
].count
)==
172 AROS_BE2LONG(volume
->blockbuffer
[i
]))
175 blocklist
[blk_count
].count
+= 1;
179 blk_count
--; /* decrement first */
180 if (blocklist
[blk_count
-1].sector
!= 0)
182 Printf("There is no more space to save blocklist in stage2\n");
185 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
186 blocklist
[blk_count
].count
= 1;
190 i
= volume
->SizeBlock
- 51;
191 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
194 blocks in blocklist are relative to the first
195 sector of the HD (not partition)
198 for (count
=-1;count
>=blk_count
;count
--)
200 blocklist
[count
].sector
+= volume
->startblock
;
201 blocklist
[count
].seg_adr
= 0x820 + (i
*32);
202 i
+= blocklist
[count
].count
;
207 /*************************************
208 Name : installStageFiles
209 Descr.: install stage1 and initialize stage2
210 Input : volume - the volume to install on
211 use_mbr - flag to use MBR
212 stage2_drive - the unit stage2 is located
213 **************************************/
214 void installStageFiles(struct Volume
*volume
, LONG use_mbr
, UBYTE stage2_drive
) {
216 struct FileInfoBlock fib
;
223 strcpy(stagename
, (char *)volume
->drivename
);
224 strcat(stagename
, "Boot/grub/stage2");
225 fh
= Open(stagename
,MODE_OLDFILE
);
228 if (ExamineFH(fh
, &fib
))
230 if (Read(fh
, stage2_firstblock
, 512) == 512)
232 if ((volume
->flags
& VF_MOVE_BB
) && !use_mbr
)
236 volume
, 1, volume
->blockbuffer
, 512,
242 block
=collectBlockList
244 volume
, fib
.fib_DiskKey
,
245 (struct BlockNode
*)&stage2_firstblock
[128]
250 if (Seek(fh
, 0, OFFSET_BEGINNING
)!=-1)
252 if (Write(fh
, stage2_firstblock
, 512)==512)
254 strcpy(stagename
, (char *)volume
->drivename
);
255 strcat(stagename
, "Boot/grub/stage1");
256 fh2
= Open(stagename
, MODE_OLDFILE
);
259 if (Read(fh2
, volume
->blockbuffer
, 512) == 512)
261 volume
->blockbuffer
[17]=block
;
265 volume
->blockbuffer
[17] += volume
->startblock
;
266 volume
->startblock
= 0;
267 retval
= readwriteBlock
270 stage2_firstblock
, 512, volume
->readcommand
272 /* copy BPB (BIOS Parameter Block)*/
275 (APTR
)((char *)stage2_firstblock
+0x3),
276 (APTR
)((char *)volume
->blockbuffer
+0x3),
279 /* copy partition table */
282 (APTR
)((char *)stage2_firstblock
+0x1BE),
283 (APTR
)((char *)volume
->blockbuffer
+0x1BE),
286 /* store the drive num stage2 is stored on */
287 ((char *)volume
->blockbuffer
)[0x40] = stage2_drive
+0x80;
291 retval
= readwriteBlock
294 volume
->blockbuffer
, 512, volume
->writecommand
297 Printf("WriteError %lu\n", (long)retval
);
300 Printf("WriteErrro %lu\n", (long)retval
);
338 PrintFault(error
, errstr
);
341 void nsdCheck(struct Volume
*volume
) {
342 struct NSDeviceQueryResult nsdq
;
346 (volume
->startblock
+volume
->countblock
)* /* last block */
347 (volume
->SizeBlock
*4/512) /* 1 portion (block) equals 512 (bytes) */
350 nsdq
.SizeAvailable
=0;
351 nsdq
.DevQueryFormat
=0;
352 volume
->iotd
->iotd_Req
.io_Command
=NSCMD_DEVICEQUERY
;
353 volume
->iotd
->iotd_Req
.io_Data
=&nsdq
;
354 volume
->iotd
->iotd_Req
.io_Length
=sizeof(struct NSDeviceQueryResult
);
355 if (DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
)==IOERR_NOCMD
)
357 Printf("Device doesn't understand NSD-Query\n");
362 (volume
->iotd
->iotd_Req
.io_Actual
>sizeof(struct NSDeviceQueryResult
)) ||
363 (volume
->iotd
->iotd_Req
.io_Actual
==0) ||
364 (volume
->iotd
->iotd_Req
.io_Actual
!=nsdq
.SizeAvailable
)
367 Printf("WARNING wrong io_Actual using NSD\n");
371 if (nsdq
.DeviceType
!= NSDEVTYPE_TRACKDISK
)
372 Printf("WARNING no trackdisk type\n");
373 for (cmdcheck
=nsdq
.SupportedCommands
;*cmdcheck
;cmdcheck
++)
375 if (*cmdcheck
== NSCMD_TD_READ64
)
376 volume
->readcommand
= NSCMD_TD_READ64
;
377 if (*cmdcheck
== NSCMD_TD_WRITE64
);
378 volume
->writecommand
= NSCMD_TD_WRITE64
;
381 (volume
->readcommand
!=NSCMD_TD_READ64
) ||
382 (volume
->writecommand
!=NSCMD_TD_WRITE64
)
384 Printf("WARNING no READ64/WRITE64\n");
390 struct Volume
*initVolume(STRPTR drivename
, IPTR use_mbr
) {
391 struct Volume
*volume
=0;
392 struct FileSysStartupMsg
*fssm
;
395 struct DeviceNode
*dn
;
398 ULONG error
=0,retval
;
401 for (i
=0;(drivename
[i
]) && (drivename
[i
]!=':');i
++)
402 dname
[i
]=drivename
[i
];
404 dl
= LockDosList(LDF_READ
| LDF_DEVICES
);
407 dn
= (struct DeviceNode
*)FindDosEntry(dl
, dname
, LDF_DEVICES
);
408 UnLockDosList(LDF_READ
| LDF_DEVICES
);
411 if (IsFileSystem(drivename
))
413 fssm
= (struct FileSysStartupMsg
*)BADDR(dn
->dn_Startup
);
416 if (strcmp(AROS_BSTR_ADDR(fssm
->fssm_Device
),"ide.device")!=0)
418 error
= ERROR_OBJECT_WRONG_TYPE
;
419 errstr
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
423 if (fssm
->fssm_Unit
!=0)
425 error
= ERROR_OBJECT_WRONG_TYPE
;
426 errstr
= "MBR can only be stored on the first HD";
432 volume
= AllocVec(sizeof(struct Volume
), MEMF_PUBLIC
| MEMF_CLEAR
);
436 volume
->drivename
= drivename
;
437 volume
->mp
= CreateMsgPort();
440 volume
->iotd
= (struct IOExtTD
*)CreateIORequest(volume
->mp
, sizeof(struct IOExtTD
));
443 de
= BADDR(volume
->fssm
->fssm_Environ
);
444 volume
->SizeBlock
= de
->de_SizeBlock
;
445 volume
->blockbuffer
= AllocVec(volume
->SizeBlock
*4, MEMF_PUBLIC
| MEMF_CLEAR
);
446 if (volume
->blockbuffer
)
451 AROS_BSTR_ADDR(volume
->fssm
->fssm_Device
),
452 volume
->fssm
->fssm_Unit
,
453 (struct IORequest
*)&volume
->iotd
->iotd_Req
,
454 volume
->fssm
->fssm_Flags
458 if (strcmp(AROS_BSTR_ADDR(volume
->fssm
->fssm_Device
), "trackdisk.device") == 0)
459 volume
->flags
|= VF_IS_TRACKDISK
;
463 de
->de_BlocksPerTrack
;
467 de
->de_HighCyl
-de
->de_LowCyl
+1
468 )*de
->de_Surfaces
*de
->de_BlocksPerTrack
470 volume
->readcommand
= CMD_READ
;
471 volume
->writecommand
= CMD_WRITE
;
473 retval
= readwriteBlock
476 volume
->blockbuffer
, 512, volume
->readcommand
480 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300)
482 retval
= readwriteBlock
485 volume
->blockbuffer
, 512, volume
->readcommand
489 volume
->flags
|= VF_MOVE_BB
;
491 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300) &&
492 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF)>0)
498 error
= ERROR_NOT_A_DOS_DISK
;
502 error
= ERROR_UNKNOWN
;
503 errstr
= "Read Error";
508 error
= ERROR_UNKNOWN
;
509 errstr
= "OpenDevice() Error";
511 FreeVec(volume
->blockbuffer
);
514 error
= ERROR_NO_FREE_STORE
;
517 error
= ERROR_NO_FREE_STORE
;
518 DeleteMsgPort(volume
->mp
);
521 error
= ERROR_NO_FREE_STORE
;
526 error
= ERROR_NO_FREE_STORE
;
534 error
= ERROR_OBJECT_NOT_FOUND
;
540 error
= ERROR_UNKNOWN
;
541 errstr
= "LockDosList Error";
543 PrintFault(error
, errstr
);
547 void uninitVolume(struct Volume
*volume
) {
549 FreeVec(volume
->blockbuffer
);
550 CloseDevice((struct IORequest
*)&volume
->iotd
->iotd_Req
);
551 DeleteIORequest((struct IORequest
*)volume
->iotd
);
552 DeleteMsgPort(volume
->mp
);
556 void checkBootCode(struct Volume
*volume
) {
557 Printf("CHECK not implemented yet\n");
560 void removeBootCode(struct Volume
*volume
) {
563 retval
= readwriteBlock
566 volume
->blockbuffer
, 512, volume
->readcommand
569 Printf("ReadError %lu\n", (long)retval
);
572 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
574 retval
= readwriteBlock
577 volume
->blockbuffer
, 512, volume
->writecommand
580 Printf("WriteError %lu\n", (long)retval
);
586 IPTR myargs
[5]={0,0,0,0,0};
587 struct RDArgs
*rdargs
;
588 struct Volume
*volume
;
590 rdargs
= ReadArgs("DRIVE/A,NOBOOT/S,CHECK/S,FFS/S,MBR/S",myargs
,NULL
);
593 volume
= initVolume((STRPTR
)myargs
[0], myargs
[4]);
597 removeBootCode(volume
);
599 checkBootCode(volume
);
601 installStageFiles(volume
, myargs
[4], volume
->fssm
->fssm_Unit
);
602 uninitVolume(volume
);
607 PrintFault(IoErr(), NULL
);