2 Copyright © 1995-2007, 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 (eg. 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
48 ******************************************************************************/
52 #include <proto/dos.h>
53 #include <proto/exec.h>
54 #include <proto/partition.h>
55 #include <aros/macros.h>
56 #include <devices/hardblocks.h>
57 #include <devices/newstyle.h>
59 #include <exec/errors.h>
60 #include <exec/memory.h>
61 #include <libraries/partition.h>
64 #include <aros/debug.h>
66 /* Defines for grub data */
67 /* Stage 1 pointers */
68 #define MBR_BPBEND 0x3e
69 #define GRUB_BOOT_DRIVE 0x40
70 #define GRUB_FORCE_LBA 0x41
71 #define GRUB_STAGE2_SECTOR 0x44
72 #define MBR_PARTSTART 0x1be
73 #define MBR_PARTEND 0x1fe
74 /* Stage 2 pointers */
77 #define BIOS_HDISK_FLAG 0x80
79 #define MBR_MAX_PARTITIONS 4
80 #define MBRT_EXTENDED 0x05
81 #define MBRT_EXTENDED2 0x0f
97 #define VF_IS_TRACKDISK (1<<0)
98 #define VF_IS_RDB (1<<1)
109 "PARTITIONNUMBER=PN/K/N," /* Partition whose boot block we should install stage1 in */
112 IPTR myargs
[7] = {0,0,0,0,0,0};
114 struct FileSysStartupMsg
*getDiskFSSM(STRPTR path
) {
116 struct DeviceNode
*dn
;
120 D(bug("[install-i386] getDiskFSSM('%s')\n", path
));
122 for (i
=0;(path
[i
]) && (path
[i
]!=':');i
++)
127 dl
= LockDosList(LDF_READ
);
130 dn
= (struct DeviceNode
*)FindDosEntry(dl
, dname
, LDF_DEVICES
);
131 UnLockDosList(LDF_READ
);
134 if (IsFileSystem(dname
))
136 return (struct FileSysStartupMsg
*)BADDR(dn
->dn_Startup
);
139 printf("device '%s' doesn't contain a file system\n", dname
);
142 PrintFault(ERROR_OBJECT_NOT_FOUND
, dname
);
146 printf("'%s' doesn't contain a device name\n",path
);
150 void fillGeometry(struct Volume
*volume
, struct DosEnvec
*de
) {
153 D(bug("[install-i386] fillGeometry(%x)\n", volume
));
155 spc
= de
->de_Surfaces
*de
->de_BlocksPerTrack
;
156 volume
->SizeBlock
= de
->de_SizeBlock
;
157 volume
->startblock
= de
->de_LowCyl
*spc
;
158 volume
->countblock
=((de
->de_HighCyl
-de
->de_LowCyl
+1)*spc
)-1+de
->de_Reserved
;
161 void nsdCheck(struct Volume
*volume
) {
162 struct NSDeviceQueryResult nsdq
;
165 D(bug("[install-i386] nsdCheck(%x)\n", volume
));
169 (volume
->startblock
+volume
->countblock
)* /* last block */
170 ((volume
->SizeBlock
<<2)/512) /* 1 portion (block) equals 512 (bytes) */
173 nsdq
.SizeAvailable
=0;
174 nsdq
.DevQueryFormat
=0;
175 volume
->iotd
->iotd_Req
.io_Command
=NSCMD_DEVICEQUERY
;
176 volume
->iotd
->iotd_Req
.io_Data
=&nsdq
;
177 volume
->iotd
->iotd_Req
.io_Length
=sizeof(struct NSDeviceQueryResult
);
178 if (DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
)==IOERR_NOCMD
)
180 printf("Device doesn't understand NSD-Query\n");
185 (volume
->iotd
->iotd_Req
.io_Actual
>sizeof(struct NSDeviceQueryResult
)) ||
186 (volume
->iotd
->iotd_Req
.io_Actual
==0) ||
187 (volume
->iotd
->iotd_Req
.io_Actual
!=nsdq
.SizeAvailable
)
190 printf("WARNING wrong io_Actual using NSD\n");
194 if (nsdq
.DeviceType
!= NSDEVTYPE_TRACKDISK
)
195 printf("WARNING no trackdisk type\n");
196 for (cmdcheck
=nsdq
.SupportedCommands
;*cmdcheck
;cmdcheck
++)
198 if (*cmdcheck
== NSCMD_TD_READ64
)
199 volume
->readcmd
= NSCMD_TD_READ64
;
200 if (*cmdcheck
== NSCMD_TD_WRITE64
);
201 volume
->writecmd
= NSCMD_TD_WRITE64
;
204 (volume
->readcmd
!=NSCMD_TD_READ64
) ||
205 (volume
->writecmd
!=NSCMD_TD_WRITE64
)
207 printf("WARNING no READ64/WRITE64\n");
214 struct Volume
*initVolume(STRPTR device
, ULONG unit
, ULONG flags
, struct DosEnvec
*de
) {
215 struct Volume
*volume
;
218 D(bug("[install-i386] initVolume(%s:%d)\n", device
, unit
));
220 volume
= AllocVec(sizeof(struct Volume
), MEMF_PUBLIC
| MEMF_CLEAR
);
223 volume
->mp
= CreateMsgPort();
226 volume
->iotd
= (struct IOExtTD
*)CreateIORequest(volume
->mp
, sizeof(struct IOExtTD
));
229 volume
->blockbuffer
= AllocVec(de
->de_SizeBlock
<<2, MEMF_PUBLIC
| MEMF_CLEAR
);
230 if (volume
->blockbuffer
)
237 (struct IORequest
*)volume
->iotd
,
242 if (strcmp(device
, "trackdisk.device")==0)
243 volume
->flags
|= VF_IS_TRACKDISK
;
245 volume
->flags
|= VF_IS_RDB
; /* just assume we have RDB */
246 volume
->readcmd
= CMD_READ
;
247 volume
->writecmd
= CMD_WRITE
;
248 volume
->unitnum
= unit
;
249 fillGeometry(volume
, de
);
254 error
= ERROR_NO_FREE_STORE
;
255 FreeVec(volume
->blockbuffer
);
258 error
= ERROR_NO_FREE_STORE
;
259 DeleteIORequest((struct IORequest
*)volume
->iotd
);
262 error
= ERROR_NO_FREE_STORE
;
263 DeleteMsgPort(volume
->mp
);
266 error
= ERROR_NO_FREE_STORE
;
270 error
= ERROR_NO_FREE_STORE
;
271 PrintFault(error
, NULL
);
275 void uninitVolume(struct Volume
*volume
)
278 D(bug("[install-i386] uninitVolume(%x)\n", volume
));
280 CloseDevice((struct IORequest
*)volume
->iotd
);
281 FreeVec(volume
->blockbuffer
);
282 DeleteIORequest((struct IORequest
*)volume
->iotd
);
283 DeleteMsgPort(volume
->mp
);
289 struct Volume
*volume
,
290 ULONG block
, APTR buffer
, ULONG length
,
297 D(bug("[install-i386] readwriteBlock(vol:%x, block:%d, %d bytes)\n", volume
, block
, length
));
299 volume
->iotd
->iotd_Req
.io_Command
= command
;
300 volume
->iotd
->iotd_Req
.io_Length
= length
;
301 volume
->iotd
->iotd_Req
.io_Data
= buffer
;
302 offset
= (UQUAD
)(volume
->startblock
+block
)*(volume
->SizeBlock
<<2);
303 volume
->iotd
->iotd_Req
.io_Offset
= offset
& 0xFFFFFFFF;
304 volume
->iotd
->iotd_Req
.io_Actual
= offset
>>32;
305 retval
= DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
306 if (volume
->flags
& VF_IS_TRACKDISK
)
308 volume
->iotd
->iotd_Req
.io_Command
= TD_MOTOR
;
309 volume
->iotd
->iotd_Req
.io_Length
= 0;
310 DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
315 BOOL
isvalidFileSystem(struct Volume
*volume
, STRPTR device
, ULONG unit
) {
317 struct PartitionBase
*PartitionBase
;
318 struct PartitionHandle
*ph
;
320 D(bug("[install-i386] isvalidFileSystem(%x, %s, %d)\n", volume
, device
, unit
));
322 if (readwriteBlock(volume
, 0, volume
->blockbuffer
, 512, volume
->readcmd
))
324 printf("Read Error\n");
328 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300) ||
329 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF) == 0)
332 /* first block has no DOS\x so we don't have RDB for sure */
333 volume
->flags
&= ~VF_IS_RDB
;
334 if (readwriteBlock(volume
, 1, volume
->blockbuffer
, 512, volume
->readcmd
))
336 printf("Read Error\n");
340 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300) ||
341 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF) == 0)
345 volume
->partnum
= -1;
346 PartitionBase
= (struct PartitionBase
*)OpenLibrary("partition.library", 1);
349 ph
= OpenRootPartition(device
, unit
);
352 if (OpenPartitionTable(ph
) == 0)
354 struct TagItem tags
[3];
357 tags
[1].ti_Tag
= TAG_DONE
;
358 tags
[0].ti_Tag
= PTT_TYPE
;
359 tags
[0].ti_Data
= (STACKIPTR
)&type
;
360 GetPartitionTableAttrs(ph
, tags
);
361 if (type
== PHPTT_MBR
)
363 struct PartitionHandle
*pn
;
365 struct PartitionHandle
*extph
= NULL
;
366 struct PartitionType ptype
= {0};
368 tags
[0].ti_Tag
= PT_DOSENVEC
;
369 tags
[0].ti_Data
= (STACKIPTR
)&de
;
370 tags
[1].ti_Tag
= PT_TYPE
;
371 tags
[1].ti_Data
= (STACKIPTR
)&ptype
;
372 tags
[2].ti_Tag
= TAG_DONE
;
373 pn
= (struct PartitionHandle
*)ph
->table
->list
.lh_Head
;
374 while (pn
->ln
.ln_Succ
)
378 GetPartitionAttrs(pn
, tags
);
379 if (ptype
.id
[0] == MBRT_EXTENDED
|| ptype
.id
[0] == MBRT_EXTENDED2
)
383 scp
= de
.de_Surfaces
*de
.de_BlocksPerTrack
;
385 (volume
->startblock
>=(de
.de_LowCyl
*scp
)) &&
386 (volume
->startblock
<=(((de
.de_HighCyl
+1)*scp
)-1))
390 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
394 tags
[0].ti_Tag
= PT_POSITION
;
395 tags
[0].ti_Data
= (STACKIPTR
)&type
;
396 tags
[1].ti_Tag
= TAG_DONE
;
397 GetPartitionAttrs(pn
, tags
);
398 volume
->partnum
= (UBYTE
)type
;
400 D(bug("[install-i386] Primary partition found: partnum=%ld\n", volume
->partnum
));
402 else if (extph
!= NULL
)
404 if (OpenPartitionTable(extph
) == 0)
406 tags
[0].ti_Tag
= PTT_TYPE
;
407 tags
[0].ti_Data
= (STACKIPTR
)&type
;
408 tags
[1].ti_Tag
= TAG_DONE
;
409 GetPartitionTableAttrs(extph
, tags
);
410 if (type
== PHPTT_EBR
)
412 tags
[0].ti_Tag
= PT_DOSENVEC
;
413 tags
[0].ti_Data
= (STACKIPTR
)&de
;
414 tags
[1].ti_Tag
= TAG_DONE
;
415 pn
= (struct PartitionHandle
*)extph
->table
->list
.lh_Head
;
416 while (pn
->ln
.ln_Succ
)
420 offset
= extph
->de
.de_LowCyl
421 * extph
->de
.de_Surfaces
422 * extph
->de
.de_BlocksPerTrack
;
423 GetPartitionAttrs(pn
, tags
);
424 scp
= de
.de_Surfaces
*de
.de_BlocksPerTrack
;
426 (volume
->startblock
>=offset
+(de
.de_LowCyl
*scp
)) &&
427 (volume
->startblock
<=offset
+(((de
.de_HighCyl
+1)*scp
)-1))
430 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
434 tags
[0].ti_Tag
= PT_POSITION
;
435 tags
[0].ti_Data
= (STACKIPTR
)&type
;
436 GetPartitionAttrs(pn
, tags
);
437 volume
->partnum
= MBR_MAX_PARTITIONS
+ (UBYTE
)type
;
439 D(bug("[install-i386] Logical partition found: partnum=%ld\n", volume
->partnum
));
442 ClosePartitionTable(extph
);
448 if (type
== PHPTT_RDB
)
450 /* just use whole hard disk */
454 printf("only MBR and RDB partition tables are supported\n");
456 ClosePartitionTable(ph
);
460 /* just use whole hard disk */
463 CloseRootPartition(ph
);
466 printf("Error OpenRootPartition(%s,%ld)\n", device
, unit
);
467 CloseLibrary((struct Library
*)PartitionBase
);
470 printf("Couldn't open partition.library\n");
474 struct Volume
*getGrubStageVolume
482 struct Volume
*volume
;
484 volume
= initVolume(device
, unit
, flags
, de
);
486 D(bug("[install-i386] getGrubStageVolume(): volume=%x\n", volume
));
490 if (isvalidFileSystem(volume
, device
, unit
))
494 printf("stage2 is on an unsupported file system\n");
495 PrintFault(ERROR_OBJECT_WRONG_TYPE
, NULL
);
497 uninitVolume(volume
);
502 BOOL isvalidPartition
510 struct PartitionBase
*PartitionBase
;
511 struct PartitionHandle
*ph
;
515 D(bug("[install-i386] isvalidPartition(%s:%d, part:%d)\n", device
, unit
, pnum
));
517 PartitionBase
= (struct PartitionBase
*)OpenLibrary("partition.library", 1);
520 ph
= OpenRootPartition(device
, unit
);
523 struct TagItem tags
[2];
525 tags
[1].ti_Tag
= TAG_DONE
;
526 /* is there a partition table? */
527 if (OpenPartitionTable(ph
) == 0)
531 /* install into partition bootblock */
532 tags
[0].ti_Tag
= PTT_TYPE
;
533 tags
[0].ti_Data
= (STACKIPTR
)&type
;
534 GetPartitionTableAttrs(ph
, tags
);
535 if (type
== PHPTT_MBR
)
537 struct PartitionHandle
*pn
;
539 /* search for partition */
540 tags
[0].ti_Tag
= PT_POSITION
;
541 tags
[0].ti_Data
= (STACKIPTR
)&type
;
542 pn
= (struct PartitionHandle
*)ph
->table
->list
.lh_Head
;
543 while (pn
->ln
.ln_Succ
)
545 GetPartitionAttrs(pn
, tags
);
548 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
552 struct PartitionType ptype
;
554 /* is it an AROS partition? */
555 tags
[0].ti_Tag
= PT_TYPE
;
556 tags
[0].ti_Data
= (STACKIPTR
)&ptype
;
557 GetPartitionAttrs(pn
, tags
);
558 if (ptype
.id
[0] == 0x30)
560 tags
[0].ti_Tag
= PT_DOSENVEC
;
561 tags
[0].ti_Data
= (STACKIPTR
)de
;
562 GetPartitionAttrs(pn
, tags
);
566 printf("partition is not of type AROS (0x30)\n");
572 "partition %ld not found on device %s unit %ld\n",
578 printf("you can only install in partitions which are MBR partitioned\n");
582 /* install into MBR */
583 tags
[0].ti_Tag
= PTT_TYPE
;
584 tags
[0].ti_Data
= (STACKIPTR
)&type
;
585 GetPartitionTableAttrs(ph
, tags
);
586 if ((type
== PHPTT_MBR
) || (type
== PHPTT_RDB
))
588 tags
[0].ti_Tag
= PT_DOSENVEC
;
589 tags
[0].ti_Data
= (STACKIPTR
)de
;
590 GetPartitionAttrs(ph
, tags
);
594 printf("partition table type must be either MBR or RDB\n");
596 ClosePartitionTable(ph
);
600 #warning "FIXME: GetPartitionAttr() should always work for root partition"
601 CopyMem(&ph
->de
, de
, sizeof(struct DosEnvec
));
604 CloseRootPartition(ph
);
607 printf("Error OpenRootPartition(%s,%ld)\n", device
, unit
);
608 CloseLibrary((struct Library
*)PartitionBase
);
611 printf("Couldn't open partition.library\n");
615 struct Volume
*getBBVolume(STRPTR device
, ULONG unit
, LONG
*partnum
) {
616 struct Volume
*volume
;
619 D(bug("[install-i386] getBBVolume(%s:%d, %d)\n", device
, unit
, partnum
));
621 if (isvalidPartition(device
, unit
, partnum
, &de
))
623 volume
= initVolume(device
, unit
, 0, &de
);
624 volume
->partnum
= partnum
? *partnum
: -1;
625 readwriteBlock(volume
, 0, volume
->blockbuffer
, 512, volume
->readcmd
);
626 if (AROS_BE2LONG(volume
->blockbuffer
[0]) != IDNAME_RIGIDDISK
)
628 memset(volume
->blockbuffer
,0x00, 446); /* Clear the boot sector region! */
632 printf("no space for bootblock (RDB is on block 0)\n");
637 ULONG collectBlockList
639 struct Volume
*volume
,
641 struct BlockNode
*blocklist
644 ULONG retval
, first_block
;
645 WORD blk_count
,count
;
648 D(bug("[install-i386] collectBlockList(%x, %d, %x)\n", volume
, block
, blocklist
));
650 #warning "TODO: logical/physical blocks"
652 initialze stage2-blocklist
653 (it is NULL-terminated)
655 // for (blk_count=-1;blocklist[blk_count].sector!=0;blk_count--)
656 // blocklist[blk_count].sector = 0;
658 memset((char *)&blocklist
[-20],0x00, 20*sizeof(struct BlockNode
)); /* Clear the stage2 sector pointers region! */
659 D(bug("[install-i386] collectBlockList: Cleared sector list (20 entries) [start: %x, end %x]\n", &blocklist
[-20], &blocklist
[-1]));
662 the first block of stage2 will be stored in stage1
663 so skip the first filekey in the first loop
665 #warning "Block read twice"
666 retval
=readwriteBlock
668 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
<<2,
673 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld\n", retval
));
674 printf("ReadError %ld\n", retval
);
678 i
= volume
->SizeBlock
- 52;
679 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
682 D(bug("[install-i386] collectBlockList: First block @ %x, i:%d\n", first_block
, i
));
687 retval
=readwriteBlock
689 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
<<2,
694 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld)\n", retval
));
695 printf("ReadError %ld\n", retval
);
698 D(bug("[install-i386] collectBlockList: read block %lx, i = %d\n", block
, i
));
699 while ((i
>=6) && (volume
->blockbuffer
[i
]))
701 D(bug("[install-i386] collectBlockList: i = %d\n", i
));
703 if current sector follows right after last sector
704 then we don't need a new element
707 (blocklist
[blk_count
].sector
) &&
708 ((blocklist
[blk_count
].sector
+blocklist
[blk_count
].count
)==
709 AROS_BE2LONG(volume
->blockbuffer
[i
]))
712 blocklist
[blk_count
].count
+= 1;
713 D(bug("[install-i386] collectBlockList: sector %d follows previous - increasing count of block %d to %d\n", i
, blk_count
, blocklist
[blk_count
].count
));
717 blk_count
--; /* decrement first */
718 D(bug("[install-i386] collectBlockList: store new block (%d)\n", blk_count
));
719 if (blocklist
[blk_count
-1].sector
!= 0)
721 D(bug("[install-i386] collectBlockList: ERROR: out of block space at sector %d, block %d\n", i
, blk_count
));
722 printf("There is no more space to save blocklist in stage2\n");
725 D(bug("[install-i386] collectBlockList: storing sector pointer for %d in block %d\n", i
, blk_count
));
726 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
727 blocklist
[blk_count
].count
= 1;
731 i
= volume
->SizeBlock
- 51;
732 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
733 D(bug("[install-i386] collectBlockList: next block %d, i = %d\n", block
, i
));
736 blocks in blocklist are relative to the first
737 sector of the HD (not partition)
739 D(bug("[install-i386] collectBlockList: successfully updated pointers for %d blocks\n", blk_count
));
742 for (count
=-1;count
>=blk_count
;count
--)
744 blocklist
[count
].sector
+= volume
->startblock
;
745 blocklist
[count
].seg_adr
= 0x820 + (i
*32);
746 i
+= blocklist
[count
].count
;
747 D(bug("[install-i386] collectBlockList: correcting block %d for partition start\n", count
));
748 D(bug("[install-i386] collectBlockList: sector : %x seg_adr : %x\n", blocklist
[count
].sector
, blocklist
[count
].seg_adr
));
753 void copyRootPath(char *dst
, char *rpdos
, BOOL isRDB
) {
755 D(bug("[install-i386] copyRootPath()\n"));
759 /* we have an RDB so use devicename */
761 while ((*rpdos
) && (*rpdos
!=':'))
766 while ((*rpdos
) && (*rpdos
!=':'))
769 rpdos
++; /* skip colon */
780 UBYTE
*memstr(UBYTE
*mem
, UBYTE
*str
, LONG len
) {
793 while ((*search
) && (left
) && (*next
++ == *search
++))
807 struct Volume
*volume
813 D(bug("[install-i386] writeStage2(%x)\n", volume
));
815 if (Seek(fh
, 0, OFFSET_BEGINNING
) != -1)
817 /* write back first block */
818 if (Write(fh
, buffer
, 512)==512)
820 /* read second stage2 block */
821 if (Read(fh
, buffer
, 512) == 512)
823 /* set partition number where stage2 is on */
826 buffer
[10] = volume
->partnum
;
828 /* get ptr to version string */
829 menuname
= buffer
+18;
830 while (*menuname
++); /* skip version string */
831 copyRootPath(menuname
, grubpath
, volume
->flags
& VF_IS_RDB
);
832 strcat(menuname
, "/menu.lst");
833 /* write second stage2 block back */
834 if (Seek(fh
, -512, OFFSET_CURRENT
) != -1)
836 if (Write(fh
, buffer
, 512) == 512)
841 printf("%s: Write Error\n", menuname
);
844 printf("%s: Seek Error\n", menuname
);
847 printf("Read Error\n");
850 printf("Write Error\n");
853 PrintFault(IoErr(), NULL
);
859 STRPTR grubpath
, /* path of grub dir */
860 struct Volume
*volume
, /* volume stage2 is on */
861 ULONG
*buffer
/* a buffer of at least 512 bytes */
865 struct FileInfoBlock fib
;
867 char stage2path
[256];
869 D(bug("[install-i386] changeStage2(%x)\n", volume
));
871 AddPart(stage2path
, grubpath
, 256);
872 AddPart(stage2path
, "stage2", 256);
873 fh
= Open(stage2path
, MODE_OLDFILE
);
876 if (Examine(fh
, &fib
))
878 if (Read(fh
, buffer
, 512) == 512)
881 get and store all blocks of stage2 in first block of stage2
882 first block of stage2 will be returned
884 block
= collectBlockList
885 (volume
, fib
.fib_DiskKey
, (struct BlockNode
*)&buffer
[128]);
889 if (!writeStage2(fh
, (UBYTE
*)buffer
, grubpath
, volume
))
894 printf("%s: Read Error\n", stage2path
);
897 PrintFault(IoErr(), stage2path
);
901 PrintFault(IoErr(), stage2path
);
908 struct Volume
*volume
,
909 struct Volume
*s2vol
,
910 ULONG block
, /* first block of stage2 file */
918 D(bug("[install-i386] writeStage1(%x)\n", volume
));
920 fh
= Open(stage1path
, MODE_OLDFILE
);
923 if (Read(fh
, volume
->blockbuffer
, 512) == 512)
925 /* install into MBR ? */
926 if ((volume
->startblock
== 0) && (!(volume
->flags
& VF_IS_TRACKDISK
)))
928 D(bug("[install-i386] writeStage1: Install to HARDDISK\n"));
930 error
= readwriteBlock
931 (volume
, 0, s2vol
->blockbuffer
, 512, volume
->readcmd
);
933 D(bug("[install-i386] writeStage1: MBR Buffer @ %x\n", volume
->blockbuffer
));
934 D(bug("[install-i386] writeStage1: Copying MBR BPB to %x\n", (char *)volume
->blockbuffer
+ 0x04));
935 // copy BPB (BIOS Parameter Block)
938 (APTR
)((char *)s2vol
->blockbuffer
+ 0x04),
939 (APTR
)((char *)volume
->blockbuffer
+ 0x04),
942 // copy partition table - [Overwrites Floppy boot code]
943 D(bug("[install-i386] writeStage1: Copying MBR Partitions to %x\n", (char *)volume
->blockbuffer
+ MBR_PARTSTART
));
946 (APTR
)((char *)s2vol
->blockbuffer
+ MBR_PARTSTART
),
947 (APTR
)((char *)volume
->blockbuffer
+ MBR_PARTSTART
),
948 (MBR_PARTEND
- MBR_PARTSTART
)
950 // store the drive num stage2 is stored on
951 ((char *)volume
->blockbuffer
)[GRUB_BOOT_DRIVE
] = unit
+ BIOS_HDISK_FLAG
;
952 // Store the stage 2 pointer ..
953 ULONG
* stage2_sector_start
= (ULONG
*)((char *)volume
->blockbuffer
+ GRUB_STAGE2_SECTOR
);
954 D(bug("[install-i386] writeStage1: writing stage2 pointer @ %x\n", stage2_sector_start
));
955 stage2_sector_start
[0] = block
;
956 D(bug("[install-i386] writeStage1: stage2 pointer = %x\n", stage2_sector_start
[0]));
957 stage2_sector_start
[0] += s2vol
->startblock
;
958 D(bug("[install-i386] writeStage1: + offset [%d] = %x\n", s2vol
->startblock
, stage2_sector_start
[0]));
962 D(bug("[install-i386] writeStage1: Forcing LBA\n"));
963 ((char *)volume
->blockbuffer
)[GRUB_FORCE_LBA
] = 1;
967 D(bug("[install-i386] writeStage1: NOT Forcing LBA\n"));
968 ((char *)volume
->blockbuffer
)[GRUB_FORCE_LBA
] = 0;
973 D(bug("[install-i386] writeStage1: Install to FLOPPY\n"));
978 error
= readwriteBlock
979 (volume
, 0, volume
->blockbuffer
, 512, volume
->writecmd
);
981 printf("WriteError %ld\n", error
);
986 printf("WriteError %ld\n", error
);
989 printf("%s: Read Error\n", stage1path
);
993 PrintFault(IoErr(), stage1path
);
997 /* Flushes the cache on the volume containing the specified path. */
998 VOID
flushFS(CONST TEXT
*path
)
1003 for (i
= 0; path
[i
] != ':'; i
++)
1004 devname
[i
] = path
[i
];
1007 if (Inhibit(devname
, DOSTRUE
))
1008 Inhibit(devname
, DOSFALSE
);
1011 BOOL installStageFiles
1013 struct Volume
*s2vol
, /* stage2 volume */
1014 STRPTR stagepath
, /* path to stage* files */
1015 ULONG unit
, /* unit stage2 is on */
1016 struct Volume
*s1vol
/* device on which stage1 will be stored */
1019 BOOL retval
= FALSE
;
1020 char stagename
[256];
1023 D(bug("[install-i386] installStageFiles(%x)\n", s1vol
));
1025 /* Flush GRUB volume's cache */
1028 block
= changeStage2(stagepath
, s2vol
, s1vol
->blockbuffer
);
1031 AddPart(stagename
, stagepath
, 256);
1032 AddPart(stagename
, "stage1", 256);
1033 if (writeStage1(stagename
, s1vol
, s2vol
, block
, unit
))
1039 int main(int argc
, char **argv
) {
1041 struct RDArgs
*rdargs
;
1042 struct Volume
*grubvol
;
1043 struct Volume
*bbvol
;
1044 struct FileSysStartupMsg
*fssm
;
1046 D(bug("[install-i386] main()\n"));
1048 rdargs
= ReadArgs(template, myargs
, NULL
);
1051 D(bug("[install-i386] FORCELBA = %d\n",myargs
[4]));
1053 fssm
= getDiskFSSM((STRPTR
)myargs
[3]);
1057 (strcmp(AROS_BSTR_ADDR(fssm
->fssm_Device
),(char*)myargs
[0])==0)
1060 grubvol
= getGrubStageVolume
1062 AROS_BSTR_ADDR(fssm
->fssm_Device
),
1065 (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
)
1072 *((LONG
*)myargs
[1]),
1079 getBBVolume() read block 0
1080 if the partition directly contains a filesystem
1081 (currently only DOS\x is supported) we have
1082 to move block 0 to block 1 to make space for stage1
1085 (grubvol
->startblock
== bbvol
->startblock
) &&
1086 ((AROS_BE2LONG(bbvol
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
1089 grubvol
->flags
&= ~VF_IS_RDB
;
1090 retval
= readwriteBlock
1091 (bbvol
, 0, bbvol
->blockbuffer
, 512, bbvol
->readcmd
);
1098 (STRPTR
)myargs
[3], /* grub path (stage1/2) */
1104 printf("Read Error: %ld\n", retval
);
1105 uninitVolume(bbvol
);
1107 uninitVolume(grubvol
);
1114 "%s is not on device %s unit %ld\n",
1115 (STRPTR
)myargs
[3], (STRPTR
)myargs
[0], *((LONG
*)myargs
[1])
1121 printf("kernel path must begin with a device name\n");
1125 PrintFault(IoErr(), argv
[0]);