2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Install CLI command
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>
76 #define ERROR_UNKNOWN 100
77 #define AROS_BSTR_ADDR(s) (((STRPTR)BADDR(s))+1)
80 const TEXT version
[] = "$VER: Install 42.1 (19.2.2015)\n";
86 struct FileSysStartupMsg
*fssm
;
96 #define VF_IS_TRACKDISK (1<<0)
97 #define VF_MOVE_BB (1<<1)
105 ULONG stage2_firstblock
[128];
109 struct Volume
*volume
,
110 ULONG block
, APTR buffer
, ULONG length
,
117 volume
->iotd
->iotd_Req
.io_Command
= command
;
118 volume
->iotd
->iotd_Req
.io_Length
= length
;
119 volume
->iotd
->iotd_Req
.io_Data
= buffer
;
120 offset
= (UQUAD
)(volume
->startblock
+block
)*(volume
->SizeBlock
*4);
121 volume
->iotd
->iotd_Req
.io_Offset
= offset
& 0xFFFFFFFF;
122 volume
->iotd
->iotd_Req
.io_Actual
= offset
>>32;
123 retval
= DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
124 if (volume
->flags
& VF_IS_TRACKDISK
)
126 volume
->iotd
->iotd_Req
.io_Command
= TD_MOTOR
;
127 volume
->iotd
->iotd_Req
.io_Length
= 0;
128 DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
133 ULONG
collectBlockList(struct Volume
*volume
, ULONG block
, struct BlockNode
*blocklist
) {
134 ULONG retval
, first_block
;
135 WORD blk_count
,count
;
138 /* TODO: logical/physical blocks */
140 initialze stage2-blocklist
141 (it is NULL-terminated)
143 for (blk_count
=-1;blocklist
[blk_count
].sector
!=0;blk_count
--)
144 blocklist
[blk_count
].sector
= 0;
146 the first block of stage2 will be stored in stage1
147 so skip the first filekey in the first loop
149 /* FIXME: Block read twice */
150 retval
=readwriteBlock
152 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
155 i
= volume
->SizeBlock
- 52;
156 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
159 retval
=readwriteBlock
161 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
*4,
166 Printf("ReadError %lu\n", (long)retval
);
169 while ((i
>=6) && (volume
->blockbuffer
[i
]))
172 if current sector follows right after last sector
173 then we don't need a new element
176 (blocklist
[blk_count
].sector
) &&
177 ((blocklist
[blk_count
].sector
+blocklist
[blk_count
].count
)==
178 AROS_BE2LONG(volume
->blockbuffer
[i
]))
181 blocklist
[blk_count
].count
+= 1;
185 blk_count
--; /* decrement first */
186 if (blocklist
[blk_count
-1].sector
!= 0)
188 Printf("There is no more space to save blocklist in stage2\n");
191 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
192 blocklist
[blk_count
].count
= 1;
196 i
= volume
->SizeBlock
- 51;
197 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
200 blocks in blocklist are relative to the first
201 sector of the HD (not partition)
204 for (count
=-1;count
>=blk_count
;count
--)
206 blocklist
[count
].sector
+= volume
->startblock
;
207 blocklist
[count
].seg_adr
= 0x820 + (i
*32);
208 i
+= blocklist
[count
].count
;
213 /*************************************
214 Name : installStageFiles
215 Descr.: install stage1 and initialize stage2
216 Input : volume - the volume to install on
217 use_mbr - flag to use MBR
218 stage2_drive - the unit stage2 is located
219 **************************************/
220 void installStageFiles(struct Volume
*volume
, LONG use_mbr
, UBYTE stage2_drive
) {
222 struct FileInfoBlock fib
;
229 strcpy(stagename
, (char *)volume
->drivename
);
230 strcat(stagename
, "Boot/grub/stage2");
231 fh
= Open(stagename
,MODE_OLDFILE
);
234 if (ExamineFH(fh
, &fib
))
236 if (Read(fh
, stage2_firstblock
, 512) == 512)
238 if ((volume
->flags
& VF_MOVE_BB
) && !use_mbr
)
242 volume
, 1, volume
->blockbuffer
, 512,
248 block
=collectBlockList
250 volume
, fib
.fib_DiskKey
,
251 (struct BlockNode
*)&stage2_firstblock
[128]
256 if (Seek(fh
, 0, OFFSET_BEGINNING
)!=-1)
258 if (Write(fh
, stage2_firstblock
, 512)==512)
260 strcpy(stagename
, (char *)volume
->drivename
);
261 strcat(stagename
, "Boot/grub/stage1");
262 fh2
= Open(stagename
, MODE_OLDFILE
);
265 if (Read(fh2
, volume
->blockbuffer
, 512) == 512)
267 volume
->blockbuffer
[17]=block
;
271 volume
->blockbuffer
[17] += volume
->startblock
;
272 volume
->startblock
= 0;
273 retval
= readwriteBlock
276 stage2_firstblock
, 512, volume
->readcommand
278 /* copy BPB (BIOS Parameter Block)*/
281 (APTR
)((char *)stage2_firstblock
+0x3),
282 (APTR
)((char *)volume
->blockbuffer
+0x3),
285 /* copy partition table */
288 (APTR
)((char *)stage2_firstblock
+0x1BE),
289 (APTR
)((char *)volume
->blockbuffer
+0x1BE),
292 /* store the drive num stage2 is stored on */
293 ((char *)volume
->blockbuffer
)[0x40] = stage2_drive
+0x80;
297 retval
= readwriteBlock
300 volume
->blockbuffer
, 512, volume
->writecommand
303 Printf("WriteError %lu\n", (long)retval
);
306 Printf("WriteErrro %lu\n", (long)retval
);
344 PrintFault(error
, errstr
);
347 void nsdCheck(struct Volume
*volume
) {
348 struct NSDeviceQueryResult nsdq
;
352 (volume
->startblock
+volume
->countblock
)* /* last block */
353 (volume
->SizeBlock
*4/512) /* 1 portion (block) equals 512 (bytes) */
356 nsdq
.SizeAvailable
=0;
357 nsdq
.DevQueryFormat
=0;
358 volume
->iotd
->iotd_Req
.io_Command
=NSCMD_DEVICEQUERY
;
359 volume
->iotd
->iotd_Req
.io_Data
=&nsdq
;
360 volume
->iotd
->iotd_Req
.io_Length
=sizeof(struct NSDeviceQueryResult
);
361 if (DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
)==IOERR_NOCMD
)
363 Printf("Device doesn't understand NSD-Query\n");
368 (volume
->iotd
->iotd_Req
.io_Actual
>sizeof(struct NSDeviceQueryResult
)) ||
369 (volume
->iotd
->iotd_Req
.io_Actual
==0) ||
370 (volume
->iotd
->iotd_Req
.io_Actual
!=nsdq
.SizeAvailable
)
373 Printf("WARNING wrong io_Actual using NSD\n");
377 if (nsdq
.DeviceType
!= NSDEVTYPE_TRACKDISK
)
378 Printf("WARNING no trackdisk type\n");
379 for (cmdcheck
=nsdq
.SupportedCommands
;*cmdcheck
;cmdcheck
++)
381 if (*cmdcheck
== NSCMD_TD_READ64
)
382 volume
->readcommand
= NSCMD_TD_READ64
;
383 if (*cmdcheck
== NSCMD_TD_WRITE64
);
384 volume
->writecommand
= NSCMD_TD_WRITE64
;
387 (volume
->readcommand
!=NSCMD_TD_READ64
) ||
388 (volume
->writecommand
!=NSCMD_TD_WRITE64
)
390 Printf("WARNING no READ64/WRITE64\n");
396 struct Volume
*initVolume(STRPTR drivename
, IPTR use_mbr
) {
397 struct Volume
*volume
=0;
398 struct FileSysStartupMsg
*fssm
;
401 struct DeviceNode
*dn
;
404 ULONG error
=0,retval
;
407 for (i
=0;(drivename
[i
]) && (drivename
[i
]!=':');i
++)
408 dname
[i
]=drivename
[i
];
410 dl
= LockDosList(LDF_READ
| LDF_DEVICES
);
413 dn
= (struct DeviceNode
*)FindDosEntry(dl
, dname
, LDF_DEVICES
);
414 UnLockDosList(LDF_READ
| LDF_DEVICES
);
417 if (IsFileSystem(drivename
))
419 fssm
= (struct FileSysStartupMsg
*)BADDR(dn
->dn_Startup
);
422 if (strcmp(AROS_BSTR_ADDR(fssm
->fssm_Device
),"ide.device")!=0)
424 error
= ERROR_OBJECT_WRONG_TYPE
;
425 errstr
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
429 if (fssm
->fssm_Unit
!=0)
431 error
= ERROR_OBJECT_WRONG_TYPE
;
432 errstr
= "MBR can only be stored on the first HD";
438 volume
= AllocVec(sizeof(struct Volume
), MEMF_PUBLIC
| MEMF_CLEAR
);
442 volume
->drivename
= drivename
;
443 volume
->mp
= CreateMsgPort();
446 volume
->iotd
= (struct IOExtTD
*)CreateIORequest(volume
->mp
, sizeof(struct IOExtTD
));
449 de
= BADDR(volume
->fssm
->fssm_Environ
);
450 volume
->SizeBlock
= de
->de_SizeBlock
;
451 volume
->blockbuffer
= AllocVec(volume
->SizeBlock
*4, MEMF_PUBLIC
| MEMF_CLEAR
);
452 if (volume
->blockbuffer
)
457 AROS_BSTR_ADDR(volume
->fssm
->fssm_Device
),
458 volume
->fssm
->fssm_Unit
,
459 (struct IORequest
*)&volume
->iotd
->iotd_Req
,
460 volume
->fssm
->fssm_Flags
464 if (strcmp(AROS_BSTR_ADDR(volume
->fssm
->fssm_Device
), "trackdisk.device") == 0)
465 volume
->flags
|= VF_IS_TRACKDISK
;
469 de
->de_BlocksPerTrack
;
473 de
->de_HighCyl
-de
->de_LowCyl
+1
474 )*de
->de_Surfaces
*de
->de_BlocksPerTrack
476 volume
->readcommand
= CMD_READ
;
477 volume
->writecommand
= CMD_WRITE
;
479 retval
= readwriteBlock
482 volume
->blockbuffer
, 512, volume
->readcommand
486 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300)
488 retval
= readwriteBlock
491 volume
->blockbuffer
, 512, volume
->readcommand
495 volume
->flags
|= VF_MOVE_BB
;
497 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300) &&
498 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF)>0)
504 error
= ERROR_NOT_A_DOS_DISK
;
508 error
= ERROR_UNKNOWN
;
509 errstr
= "Read Error";
514 error
= ERROR_UNKNOWN
;
515 errstr
= "OpenDevice() Error";
517 FreeVec(volume
->blockbuffer
);
520 error
= ERROR_NO_FREE_STORE
;
523 error
= ERROR_NO_FREE_STORE
;
524 DeleteMsgPort(volume
->mp
);
527 error
= ERROR_NO_FREE_STORE
;
532 error
= ERROR_NO_FREE_STORE
;
540 error
= ERROR_OBJECT_NOT_FOUND
;
546 error
= ERROR_UNKNOWN
;
547 errstr
= "LockDosList Error";
549 PrintFault(error
, errstr
);
553 void uninitVolume(struct Volume
*volume
) {
555 FreeVec(volume
->blockbuffer
);
556 CloseDevice((struct IORequest
*)&volume
->iotd
->iotd_Req
);
557 DeleteIORequest((struct IORequest
*)volume
->iotd
);
558 DeleteMsgPort(volume
->mp
);
562 void checkBootCode(struct Volume
*volume
) {
563 Printf("CHECK not implemented yet\n");
566 void removeBootCode(struct Volume
*volume
) {
569 retval
= readwriteBlock
572 volume
->blockbuffer
, 512, volume
->readcommand
575 Printf("ReadError %lu\n", (long)retval
);
578 if ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
580 retval
= readwriteBlock
583 volume
->blockbuffer
, 512, volume
->writecommand
586 Printf("WriteError %lu\n", (long)retval
);
592 IPTR myargs
[5]={0,0,0,0,0};
593 struct RDArgs
*rdargs
;
594 struct Volume
*volume
;
596 rdargs
= ReadArgs("DRIVE/A,NOBOOT/S,CHECK/S,FFS/S,MBR/S",myargs
,NULL
);
599 volume
= initVolume((STRPTR
)myargs
[0], myargs
[4]);
603 removeBootCode(volume
);
605 checkBootCode(volume
);
607 installStageFiles(volume
, myargs
[4], volume
->fssm
->fssm_Unit
);
608 uninitVolume(volume
);
613 PrintFault(IoErr(), NULL
);