2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
5 /******************************************************************************
14 DEVICE/A, UNIT/N/K/A, PARTITIONNUMBER=PN/K/N, GRUB/K/A, FORCELBA/S
22 Installs the GRUB bootloader to the bootblock of the specified disk.
26 DEVICE -- Device name (e.g. ata.device)
28 PN -- Partition number (advice: the first AROS FFS partition)
29 GRUB -- Path to GRUB directory.
30 FORCELBA -- Force use of LBA mode.
38 install-i386-pc DEVICE ata.device UNIT 0 PN 1 grub dh0:boot/grub
44 Partition, Sys:System/Format
48 ******************************************************************************/
51 #include <proto/dos.h>
52 #include <proto/exec.h>
53 #include <proto/partition.h>
54 #include <aros/macros.h>
55 #include <devices/hardblocks.h>
56 #include <devices/newstyle.h>
58 #include <exec/errors.h>
59 #include <exec/memory.h>
60 #include <libraries/partition.h>
63 #include <aros/debug.h>
65 /* Defines for grub data */
66 /* Stage 1 pointers */
67 #define MBR_BPBEND 0x3e
68 #define GRUB_BOOT_DRIVE 0x40
69 #define GRUB_FORCE_LBA 0x41
70 #define GRUB_STAGE2_SECTOR 0x44
71 #define MBR_PARTSTART 0x1be
72 #define MBR_PARTEND 0x1fe
73 /* Stage 2 pointers */
76 #define BIOS_HDISK_FLAG 0x80
78 #define MBR_MAX_PARTITIONS 4
79 #define MBRT_EXTENDED 0x05
80 #define MBRT_EXTENDED2 0x0f
97 #define VF_IS_TRACKDISK (1<<0)
98 #define VF_IS_RDB (1<<1)
106 const TEXT version
[] = "$VER: Install-i386-pc 41.2 (4.6.2009)";
111 "PARTITIONNUMBER=PN/K/N," /* Partition whose boot block we should install stage1 in */
114 IPTR myargs
[7] = {0,0,0,0,0,0};
116 struct FileSysStartupMsg
*getDiskFSSM(STRPTR path
) {
118 struct DeviceNode
*dn
;
122 D(bug("[install-i386] getDiskFSSM('%s')\n", path
));
124 for (i
=0;(path
[i
]) && (path
[i
]!=':');i
++)
129 dl
= LockDosList(LDF_READ
);
132 dn
= (struct DeviceNode
*)FindDosEntry(dl
, dname
, LDF_DEVICES
);
133 UnLockDosList(LDF_READ
);
138 if (IsFileSystem(dname
))
140 return (struct FileSysStartupMsg
*)BADDR(dn
->dn_Startup
);
143 Printf("device '%s' doesn't contain a file system\n", dname
);
146 PrintFault(ERROR_OBJECT_NOT_FOUND
, dname
);
150 Printf("'%s' doesn't contain a device name\n",path
);
154 void fillGeometry(struct Volume
*volume
, struct DosEnvec
*de
) {
157 D(bug("[install-i386] fillGeometry(%x)\n", volume
));
159 spc
= de
->de_Surfaces
*de
->de_BlocksPerTrack
;
160 volume
->SizeBlock
= de
->de_SizeBlock
;
161 volume
->startblock
= de
->de_LowCyl
*spc
;
162 volume
->countblock
=((de
->de_HighCyl
-de
->de_LowCyl
+1)*spc
)-1+de
->de_Reserved
;
165 void nsdCheck(struct Volume
*volume
) {
166 struct NSDeviceQueryResult nsdq
;
169 D(bug("[install-i386] nsdCheck(%x)\n", volume
));
173 (volume
->startblock
+volume
->countblock
)* /* last block */
174 ((volume
->SizeBlock
<<2)/512) /* 1 portion (block) equals 512 (bytes) */
177 nsdq
.SizeAvailable
=0;
178 nsdq
.DevQueryFormat
=0;
179 volume
->iotd
->iotd_Req
.io_Command
=NSCMD_DEVICEQUERY
;
180 volume
->iotd
->iotd_Req
.io_Data
=&nsdq
;
181 volume
->iotd
->iotd_Req
.io_Length
=sizeof(struct NSDeviceQueryResult
);
182 if (DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
)==IOERR_NOCMD
)
184 Printf("Device doesn't understand NSD-Query\n");
189 (volume
->iotd
->iotd_Req
.io_Actual
>sizeof(struct NSDeviceQueryResult
)) ||
190 (volume
->iotd
->iotd_Req
.io_Actual
==0) ||
191 (volume
->iotd
->iotd_Req
.io_Actual
!=nsdq
.SizeAvailable
)
194 Printf("WARNING wrong io_Actual using NSD\n");
198 if (nsdq
.DeviceType
!= NSDEVTYPE_TRACKDISK
)
199 Printf("WARNING no trackdisk type\n");
200 for (cmdcheck
=nsdq
.SupportedCommands
;*cmdcheck
;cmdcheck
++)
202 if (*cmdcheck
== NSCMD_TD_READ64
)
203 volume
->readcmd
= NSCMD_TD_READ64
;
204 if (*cmdcheck
== NSCMD_TD_WRITE64
)
205 volume
->writecmd
= NSCMD_TD_WRITE64
;
208 (volume
->readcmd
!=NSCMD_TD_READ64
) ||
209 (volume
->writecmd
!=NSCMD_TD_WRITE64
)
211 Printf("WARNING no READ64/WRITE64\n");
218 struct Volume
*initVolume(STRPTR device
, ULONG unit
, ULONG flags
, struct DosEnvec
*de
) {
219 struct Volume
*volume
;
222 D(bug("[install-i386] initVolume(%s:%d)\n", device
, unit
));
224 volume
= AllocVec(sizeof(struct Volume
), MEMF_PUBLIC
| MEMF_CLEAR
);
227 volume
->mp
= CreateMsgPort();
230 volume
->iotd
= (struct IOExtTD
*)CreateIORequest(volume
->mp
, sizeof(struct IOExtTD
));
233 volume
->blockbuffer
= AllocVec(de
->de_SizeBlock
<<2, MEMF_PUBLIC
| MEMF_CLEAR
);
234 if (volume
->blockbuffer
)
241 (struct IORequest
*)volume
->iotd
,
246 if (strcmp(device
, "trackdisk.device")==0)
247 volume
->flags
|= VF_IS_TRACKDISK
;
249 volume
->flags
|= VF_IS_RDB
; /* just assume we have RDB */
250 volume
->readcmd
= CMD_READ
;
251 volume
->writecmd
= CMD_WRITE
;
252 volume
->device
= device
;
253 volume
->unitnum
= unit
;
254 fillGeometry(volume
, de
);
259 error
= ERROR_NO_FREE_STORE
;
260 FreeVec(volume
->blockbuffer
);
263 error
= ERROR_NO_FREE_STORE
;
264 DeleteIORequest((struct IORequest
*)volume
->iotd
);
267 error
= ERROR_NO_FREE_STORE
;
268 DeleteMsgPort(volume
->mp
);
271 error
= ERROR_NO_FREE_STORE
;
275 error
= ERROR_NO_FREE_STORE
;
276 PrintFault(error
, NULL
);
280 void uninitVolume(struct Volume
*volume
)
283 D(bug("[install-i386] uninitVolume(%x)\n", volume
));
285 CloseDevice((struct IORequest
*)volume
->iotd
);
286 FreeVec(volume
->blockbuffer
);
287 DeleteIORequest((struct IORequest
*)volume
->iotd
);
288 DeleteMsgPort(volume
->mp
);
294 struct Volume
*volume
,
295 ULONG block
, APTR buffer
, ULONG length
,
302 D(bug("[install-i386] readwriteBlock(vol:%x, block:%d, %d bytes)\n", volume
, block
, length
));
304 volume
->iotd
->iotd_Req
.io_Command
= command
;
305 volume
->iotd
->iotd_Req
.io_Length
= length
;
306 volume
->iotd
->iotd_Req
.io_Data
= buffer
;
307 offset
= (UQUAD
)(volume
->startblock
+block
)*(volume
->SizeBlock
<<2);
308 volume
->iotd
->iotd_Req
.io_Offset
= offset
& 0xFFFFFFFF;
309 volume
->iotd
->iotd_Req
.io_Actual
= offset
>>32;
310 retval
= DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
311 if (volume
->flags
& VF_IS_TRACKDISK
)
313 volume
->iotd
->iotd_Req
.io_Command
= TD_MOTOR
;
314 volume
->iotd
->iotd_Req
.io_Length
= 0;
315 DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
320 BOOL
isvalidFileSystem(struct Volume
*volume
, STRPTR device
, ULONG unit
) {
322 struct PartitionBase
*PartitionBase
;
323 struct PartitionHandle
*ph
;
325 D(bug("[install-i386] isvalidFileSystem(%x, %s, %d)\n", volume
, device
, unit
));
327 if (readwriteBlock(volume
, 0, volume
->blockbuffer
, 512, volume
->readcmd
))
329 Printf("Read Error\n");
333 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300) ||
334 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF) == 0)
337 /* first block has no DOS\x so we don't have RDB for sure */
338 volume
->flags
&= ~VF_IS_RDB
;
339 if (readwriteBlock(volume
, 1, volume
->blockbuffer
, 512, volume
->readcmd
))
341 Printf("Read Error\n");
345 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300) ||
346 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF) == 0)
350 volume
->partnum
= -1;
351 PartitionBase
= (struct PartitionBase
*)OpenLibrary("partition.library", 1);
354 ph
= OpenRootPartition(device
, unit
);
357 if (OpenPartitionTable(ph
) == 0)
359 struct TagItem tags
[3];
362 tags
[1].ti_Tag
= TAG_DONE
;
363 tags
[0].ti_Tag
= PTT_TYPE
;
364 tags
[0].ti_Data
= (STACKIPTR
)&type
;
365 GetPartitionTableAttrs(ph
, tags
);
366 if (type
== PHPTT_MBR
)
368 struct PartitionHandle
*pn
;
370 struct PartitionHandle
*extph
= NULL
;
371 struct PartitionType ptype
= {{0}};
373 tags
[0].ti_Tag
= PT_DOSENVEC
;
374 tags
[0].ti_Data
= (STACKIPTR
)&de
;
375 tags
[1].ti_Tag
= PT_TYPE
;
376 tags
[1].ti_Data
= (STACKIPTR
)&ptype
;
377 tags
[2].ti_Tag
= TAG_DONE
;
378 pn
= (struct PartitionHandle
*)ph
->table
->list
.lh_Head
;
379 while (pn
->ln
.ln_Succ
)
383 GetPartitionAttrs(pn
, tags
);
384 if (ptype
.id
[0] == MBRT_EXTENDED
|| ptype
.id
[0] == MBRT_EXTENDED2
)
388 scp
= de
.de_Surfaces
*de
.de_BlocksPerTrack
;
390 (volume
->startblock
>=(de
.de_LowCyl
*scp
)) &&
391 (volume
->startblock
<=(((de
.de_HighCyl
+1)*scp
)-1))
395 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
399 tags
[0].ti_Tag
= PT_POSITION
;
400 tags
[0].ti_Data
= (STACKIPTR
)&type
;
401 tags
[1].ti_Tag
= TAG_DONE
;
402 GetPartitionAttrs(pn
, tags
);
403 volume
->partnum
= (UBYTE
)type
;
405 D(bug("[install-i386] Primary partition found: partnum=%ld\n", volume
->partnum
));
407 else if (extph
!= NULL
)
409 if (OpenPartitionTable(extph
) == 0)
411 tags
[0].ti_Tag
= PTT_TYPE
;
412 tags
[0].ti_Data
= (STACKIPTR
)&type
;
413 tags
[1].ti_Tag
= TAG_DONE
;
414 GetPartitionTableAttrs(extph
, tags
);
415 if (type
== PHPTT_EBR
)
417 tags
[0].ti_Tag
= PT_DOSENVEC
;
418 tags
[0].ti_Data
= (STACKIPTR
)&de
;
419 tags
[1].ti_Tag
= TAG_DONE
;
420 pn
= (struct PartitionHandle
*)extph
->table
->list
.lh_Head
;
421 while (pn
->ln
.ln_Succ
)
425 offset
= extph
->de
.de_LowCyl
426 * extph
->de
.de_Surfaces
427 * extph
->de
.de_BlocksPerTrack
;
428 GetPartitionAttrs(pn
, tags
);
429 scp
= de
.de_Surfaces
*de
.de_BlocksPerTrack
;
431 (volume
->startblock
>=offset
+(de
.de_LowCyl
*scp
)) &&
432 (volume
->startblock
<=offset
+(((de
.de_HighCyl
+1)*scp
)-1))
435 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
439 tags
[0].ti_Tag
= PT_POSITION
;
440 tags
[0].ti_Data
= (STACKIPTR
)&type
;
441 GetPartitionAttrs(pn
, tags
);
442 volume
->partnum
= MBR_MAX_PARTITIONS
+ (UBYTE
)type
;
444 D(bug("[install-i386] Logical partition found: partnum=%ld\n", volume
->partnum
));
447 ClosePartitionTable(extph
);
453 if (type
== PHPTT_RDB
)
455 /* just use whole hard disk */
459 Printf("only MBR and RDB partition tables are supported\n");
461 ClosePartitionTable(ph
);
465 /* just use whole hard disk */
468 CloseRootPartition(ph
);
471 Printf("Error OpenRootPartition(%s,%lu)\n", device
, (long)unit
);
472 CloseLibrary((struct Library
*)PartitionBase
);
475 Printf("Couldn't open partition.library\n");
479 struct Volume
*getGrubStageVolume
487 struct Volume
*volume
;
489 volume
= initVolume(device
, unit
, flags
, de
);
491 D(bug("[install-i386] getGrubStageVolume(): volume=%x\n", volume
));
495 if (isvalidFileSystem(volume
, device
, unit
))
499 Printf("stage2 is on an unsupported file system\n");
500 PrintFault(ERROR_OBJECT_WRONG_TYPE
, NULL
);
502 uninitVolume(volume
);
507 BOOL isvalidPartition
515 struct PartitionBase
*PartitionBase
;
516 struct PartitionHandle
*ph
;
520 D(bug("[install-i386] isvalidPartition(%s:%d, part:%d)\n", device
, unit
, pnum
));
522 PartitionBase
= (struct PartitionBase
*)OpenLibrary("partition.library", 1);
525 ph
= OpenRootPartition(device
, unit
);
528 struct TagItem tags
[2];
530 tags
[1].ti_Tag
= TAG_DONE
;
531 /* is there a partition table? */
532 if (OpenPartitionTable(ph
) == 0)
536 /* install into partition bootblock */
537 tags
[0].ti_Tag
= PTT_TYPE
;
538 tags
[0].ti_Data
= (STACKIPTR
)&type
;
539 GetPartitionTableAttrs(ph
, tags
);
540 if (type
== PHPTT_MBR
)
542 struct PartitionHandle
*pn
;
544 /* search for partition */
545 tags
[0].ti_Tag
= PT_POSITION
;
546 tags
[0].ti_Data
= (STACKIPTR
)&type
;
547 pn
= (struct PartitionHandle
*)ph
->table
->list
.lh_Head
;
548 while (pn
->ln
.ln_Succ
)
550 GetPartitionAttrs(pn
, tags
);
553 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
557 struct PartitionType ptype
;
559 /* is it an AROS partition? */
560 tags
[0].ti_Tag
= PT_TYPE
;
561 tags
[0].ti_Data
= (STACKIPTR
)&ptype
;
562 GetPartitionAttrs(pn
, tags
);
563 if (ptype
.id
[0] == 0x30)
565 tags
[0].ti_Tag
= PT_DOSENVEC
;
566 tags
[0].ti_Data
= (STACKIPTR
)de
;
567 GetPartitionAttrs(pn
, tags
);
571 Printf("partition is not of type AROS (0x30)\n");
577 "partition %ld not found on device %s unit %lu\n",
578 (long)*pnum
, device
, (long)unit
583 Printf("you can only install in partitions which are MBR partitioned\n");
587 /* install into MBR */
588 tags
[0].ti_Tag
= PTT_TYPE
;
589 tags
[0].ti_Data
= (STACKIPTR
)&type
;
590 GetPartitionTableAttrs(ph
, tags
);
591 if ((type
== PHPTT_MBR
) || (type
== PHPTT_RDB
))
593 tags
[0].ti_Tag
= PT_DOSENVEC
;
594 tags
[0].ti_Data
= (STACKIPTR
)de
;
595 GetPartitionAttrs(ph
, tags
);
599 Printf("partition table type must be either MBR or RDB\n");
601 ClosePartitionTable(ph
);
605 /* FIXME: GetPartitionAttr() should always work for root partition */
606 CopyMem(&ph
->de
, de
, sizeof(struct DosEnvec
));
609 CloseRootPartition(ph
);
612 Printf("Error OpenRootPartition(%s,%lu)\n", device
, (long)unit
);
613 CloseLibrary((struct Library
*)PartitionBase
);
616 Printf("Couldn't open partition.library\n");
620 struct Volume
*getBBVolume(STRPTR device
, ULONG unit
, LONG
*partnum
) {
621 struct Volume
*volume
;
624 D(bug("[install-i386] getBBVolume(%s:%d, %d)\n", device
, unit
, partnum
));
626 if (isvalidPartition(device
, unit
, partnum
, &de
))
628 volume
= initVolume(device
, unit
, 0, &de
);
629 volume
->partnum
= partnum
? *partnum
: -1;
630 readwriteBlock(volume
, 0, volume
->blockbuffer
, 512, volume
->readcmd
);
631 if (AROS_BE2LONG(volume
->blockbuffer
[0]) != IDNAME_RIGIDDISK
)
633 memset(volume
->blockbuffer
,0x00, 446); /* Clear the boot sector region! */
637 Printf("no space for bootblock (RDB is on block 0)\n");
642 ULONG collectBlockList
644 struct Volume
*volume
,
646 struct BlockNode
*blocklist
649 ULONG retval
, first_block
;
650 WORD blk_count
,count
;
653 D(bug("[install-i386] collectBlockList(%x, %d, %x)\n", volume
, block
, blocklist
));
655 /* TODO: logical/physical blocks */
657 initialze stage2-blocklist
658 (it is NULL-terminated)
660 // for (blk_count=-1;blocklist[blk_count].sector!=0;blk_count--)
661 // blocklist[blk_count].sector = 0;
663 memset((char *)&blocklist
[-20],0x00, 20*sizeof(struct BlockNode
)); /* Clear the stage2 sector pointers region! */
664 D(bug("[install-i386] collectBlockList: Cleared sector list (20 entries) [start: %x, end %x]\n", &blocklist
[-20], &blocklist
[-1]));
667 the first block of stage2 will be stored in stage1
668 so skip the first filekey in the first loop
670 /* FIXME: Block read twice */
671 retval
=readwriteBlock
673 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
<<2,
678 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld\n", retval
));
679 Printf("ReadError %lu\n", (long)retval
);
683 i
= volume
->SizeBlock
- 52;
684 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
687 D(bug("[install-i386] collectBlockList: First block @ %x, i:%d\n", first_block
, i
));
692 retval
=readwriteBlock
694 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
<<2,
699 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld)\n", retval
));
700 Printf("ReadError %lu\n", (long)retval
);
703 D(bug("[install-i386] collectBlockList: read block %lx, i = %d\n", block
, i
));
704 while ((i
>=6) && (volume
->blockbuffer
[i
]))
706 D(bug("[install-i386] collectBlockList: i = %d\n", i
));
708 if current sector follows right after last sector
709 then we don't need a new element
712 (blocklist
[blk_count
].sector
) &&
713 ((blocklist
[blk_count
].sector
+blocklist
[blk_count
].count
)==
714 AROS_BE2LONG(volume
->blockbuffer
[i
]))
717 blocklist
[blk_count
].count
+= 1;
718 D(bug("[install-i386] collectBlockList: sector %d follows previous - increasing count of block %d to %d\n", i
, blk_count
, blocklist
[blk_count
].count
));
722 blk_count
--; /* decrement first */
723 D(bug("[install-i386] collectBlockList: store new block (%d)\n", blk_count
));
724 if (blocklist
[blk_count
-1].sector
!= 0)
726 D(bug("[install-i386] collectBlockList: ERROR: out of block space at sector %d, block %d\n", i
, blk_count
));
727 Printf("There is no more space to save blocklist in stage2\n");
730 D(bug("[install-i386] collectBlockList: storing sector pointer for %d in block %d\n", i
, blk_count
));
731 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
732 blocklist
[blk_count
].count
= 1;
736 i
= volume
->SizeBlock
- 51;
737 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
738 D(bug("[install-i386] collectBlockList: next block %d, i = %d\n", block
, i
));
741 blocks in blocklist are relative to the first
742 sector of the HD (not partition)
744 D(bug("[install-i386] collectBlockList: successfully updated pointers for %d blocks\n", blk_count
));
747 for (count
=-1;count
>=blk_count
;count
--)
749 blocklist
[count
].sector
+= volume
->startblock
;
750 blocklist
[count
].seg_adr
= 0x820 + (i
*32);
751 i
+= blocklist
[count
].count
;
752 D(bug("[install-i386] collectBlockList: correcting block %d for partition start\n", count
));
753 D(bug("[install-i386] collectBlockList: sector : %x seg_adr : %x\n", blocklist
[count
].sector
, blocklist
[count
].seg_adr
));
758 void copyRootPath(char *dst
, char *rpdos
, BOOL isRDB
) {
760 D(bug("[install-i386] copyRootPath()\n"));
764 /* we have an RDB so use devicename */
766 while ((*rpdos
) && (*rpdos
!=':'))
771 while ((*rpdos
) && (*rpdos
!=':'))
774 rpdos
++; /* skip colon */
785 /* Convert a unit number into a drive number as understood by GRUB */
786 UWORD
getDriveNumber(CONST_STRPTR device
, ULONG unit
)
788 struct PartitionHandle
*ph
;
792 for (i
= 0; i
< unit
; i
++)
794 ph
= OpenRootPartition(device
, i
);
798 CloseRootPartition(ph
);
805 UBYTE
*memstr(UBYTE
*mem
, UBYTE
*str
, LONG len
) {
818 while ((*search
) && (left
) && (*next
++ == *search
++))
832 struct Volume
*volume
838 D(bug("[install-i386] writeStage2(%x)\n", volume
));
840 if (Seek(fh
, 0, OFFSET_BEGINNING
) != -1)
842 /* write back first block */
843 if (Write(fh
, buffer
, 512)==512)
845 /* read second stage2 block */
846 if (Read(fh
, buffer
, 512) == 512)
848 /* set partition number where stage2 is on */
851 buffer
[10] = volume
->partnum
;
853 /* get ptr to version string */
854 menuname
= buffer
+18;
855 while (*menuname
++); /* skip version string */
856 copyRootPath(menuname
, grubpath
, volume
->flags
& VF_IS_RDB
);
857 strcat(menuname
, "/menu.lst");
858 /* write second stage2 block back */
859 if (Seek(fh
, -512, OFFSET_CURRENT
) != -1)
861 if (Write(fh
, buffer
, 512) == 512)
866 Printf("%s: Write Error\n", menuname
);
869 Printf("%s: Seek Error\n", menuname
);
872 Printf("Read Error\n");
875 Printf("Write Error\n");
878 PrintFault(IoErr(), NULL
);
884 STRPTR grubpath
, /* path of grub dir */
885 struct Volume
*volume
, /* volume stage2 is on */
886 ULONG
*buffer
/* a buffer of at least 512 bytes */
890 struct FileInfoBlock fib
;
892 char stage2path
[256];
894 D(bug("[install-i386] changeStage2(%x)\n", volume
));
896 AddPart(stage2path
, grubpath
, 256);
897 AddPart(stage2path
, "stage2", 256);
898 fh
= Open(stage2path
, MODE_OLDFILE
);
901 if (ExamineFH(fh
, &fib
))
903 if (Read(fh
, buffer
, 512) == 512)
906 get and store all blocks of stage2 in first block of stage2
907 first block of stage2 will be returned
909 block
= collectBlockList
910 (volume
, fib
.fib_DiskKey
, (struct BlockNode
*)&buffer
[128]);
914 if (!writeStage2(fh
, (UBYTE
*)buffer
, grubpath
, volume
))
919 Printf("%s: Read Error\n", stage2path
);
922 PrintFault(IoErr(), stage2path
);
926 PrintFault(IoErr(), stage2path
);
933 struct Volume
*volume
,
934 struct Volume
*s2vol
,
935 ULONG block
, /* first block of stage2 file */
943 D(bug("[install-i386] writeStage1(%x)\n", volume
));
945 fh
= Open(stage1path
, MODE_OLDFILE
);
948 if (Read(fh
, volume
->blockbuffer
, 512) == 512)
950 /* install into MBR ? */
951 if ((volume
->startblock
== 0) && (!(volume
->flags
& VF_IS_TRACKDISK
)))
953 D(bug("[install-i386] writeStage1: Install to HARDDISK\n"));
955 error
= readwriteBlock
956 (volume
, 0, s2vol
->blockbuffer
, 512, volume
->readcmd
);
958 D(bug("[install-i386] writeStage1: MBR Buffer @ %x\n", volume
->blockbuffer
));
959 D(bug("[install-i386] writeStage1: Copying MBR BPB to %x\n", (char *)volume
->blockbuffer
+ 0x04));
960 // copy BPB (BIOS Parameter Block)
963 (APTR
)((char *)s2vol
->blockbuffer
+ 0x04),
964 (APTR
)((char *)volume
->blockbuffer
+ 0x04),
967 // copy partition table - [Overwrites Floppy boot code]
968 D(bug("[install-i386] writeStage1: Copying MBR Partitions to %x\n", (char *)volume
->blockbuffer
+ MBR_PARTSTART
));
971 (APTR
)((char *)s2vol
->blockbuffer
+ MBR_PARTSTART
),
972 (APTR
)((char *)volume
->blockbuffer
+ MBR_PARTSTART
),
973 (MBR_PARTEND
- MBR_PARTSTART
)
975 // store the drive num stage2 is stored on
976 ((char *)volume
->blockbuffer
)[GRUB_BOOT_DRIVE
] =
977 getDriveNumber(volume
->device
, unit
) | BIOS_HDISK_FLAG
;
978 // Store the stage 2 pointer ..
979 ULONG
* stage2_sector_start
= (ULONG
*)((char *)volume
->blockbuffer
+ GRUB_STAGE2_SECTOR
);
980 D(bug("[install-i386] writeStage1: writing stage2 pointer @ %x\n", stage2_sector_start
));
981 stage2_sector_start
[0] = block
;
982 D(bug("[install-i386] writeStage1: stage2 pointer = %x\n", stage2_sector_start
[0]));
983 stage2_sector_start
[0] += s2vol
->startblock
;
984 D(bug("[install-i386] writeStage1: + offset [%d] = %x\n", s2vol
->startblock
, stage2_sector_start
[0]));
988 D(bug("[install-i386] writeStage1: Forcing LBA\n"));
989 ((char *)volume
->blockbuffer
)[GRUB_FORCE_LBA
] = 1;
993 D(bug("[install-i386] writeStage1: NOT Forcing LBA\n"));
994 ((char *)volume
->blockbuffer
)[GRUB_FORCE_LBA
] = 0;
999 D(bug("[install-i386] writeStage1: Install to FLOPPY\n"));
1004 error
= readwriteBlock
1005 (volume
, 0, volume
->blockbuffer
, 512, volume
->writecmd
);
1007 Printf("WriteError %lu\n", (long)error
);
1012 Printf("WriteError %lu\n", (long)error
);
1015 Printf("%s: Read Error\n", stage1path
);
1019 PrintFault(IoErr(), stage1path
);
1023 /* Flushes the cache on the volume containing the specified path. */
1024 VOID
flushFS(CONST TEXT
*path
)
1029 for (i
= 0; path
[i
] != ':'; i
++)
1030 devname
[i
] = path
[i
];
1033 if (Inhibit(devname
, DOSTRUE
))
1034 Inhibit(devname
, DOSFALSE
);
1037 BOOL installStageFiles
1039 struct Volume
*s2vol
, /* stage2 volume */
1040 STRPTR stagepath
, /* path to stage* files */
1041 ULONG unit
, /* unit stage2 is on */
1042 struct Volume
*s1vol
/* device on which stage1 will be stored */
1045 BOOL retval
= FALSE
;
1046 char stagename
[256];
1049 D(bug("[install-i386] installStageFiles(%x)\n", s1vol
));
1051 /* Flush GRUB volume's cache */
1054 block
= changeStage2(stagepath
, s2vol
, s1vol
->blockbuffer
);
1057 AddPart(stagename
, stagepath
, 256);
1058 AddPart(stagename
, "stage1", 256);
1059 if (writeStage1(stagename
, s1vol
, s2vol
, block
, unit
))
1065 int main(int argc
, char **argv
) {
1067 struct RDArgs
*rdargs
;
1068 struct Volume
*grubvol
;
1069 struct Volume
*bbvol
;
1070 struct FileSysStartupMsg
*fssm
;
1072 D(bug("[install-i386] main()\n"));
1074 rdargs
= ReadArgs(template, myargs
, NULL
);
1077 D(bug("[install-i386] FORCELBA = %d\n",myargs
[4]));
1079 fssm
= getDiskFSSM((STRPTR
)myargs
[3]);
1083 (strcmp(AROS_BSTR_ADDR(fssm
->fssm_Device
),(char*)myargs
[0])==0)
1086 grubvol
= getGrubStageVolume
1088 AROS_BSTR_ADDR(fssm
->fssm_Device
),
1091 (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
)
1098 *((LONG
*)myargs
[1]),
1105 getBBVolume() read block 0
1106 if the partition directly contains a filesystem
1107 (currently only DOS\x is supported) we have
1108 to move block 0 to block 1 to make space for stage1
1111 (grubvol
->startblock
== bbvol
->startblock
) &&
1112 ((AROS_BE2LONG(bbvol
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
1115 grubvol
->flags
&= ~VF_IS_RDB
;
1116 retval
= readwriteBlock
1117 (bbvol
, 0, bbvol
->blockbuffer
, 512, bbvol
->readcmd
);
1124 (STRPTR
)myargs
[3], /* grub path (stage1/2) */
1130 Printf("Read Error: %lu\n", (long)retval
);
1131 uninitVolume(bbvol
);
1133 uninitVolume(grubvol
);
1140 "%s is not on device %s unit %lu\n",
1141 (STRPTR
)myargs
[3], (STRPTR
)myargs
[0], (long)*((ULONG
*)myargs
[1])
1147 Printf("kernel path must begin with a device name\n");
1151 PrintFault(IoErr(), argv
[0]);