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 ******************************************************************************/
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
98 #define VF_IS_TRACKDISK (1<<0)
99 #define VF_IS_RDB (1<<1)
107 const TEXT version
[] = "$VER: Install-i386-pc 41.2 (4.6.2009)";
112 "PARTITIONNUMBER=PN/K/N," /* Partition whose boot block we should install stage1 in */
115 IPTR myargs
[7] = {0,0,0,0,0,0};
117 struct FileSysStartupMsg
*getDiskFSSM(STRPTR path
) {
119 struct DeviceNode
*dn
;
123 D(bug("[install-i386] getDiskFSSM('%s')\n", path
));
125 for (i
=0;(path
[i
]) && (path
[i
]!=':');i
++)
130 dl
= LockDosList(LDF_READ
);
133 dn
= (struct DeviceNode
*)FindDosEntry(dl
, dname
, LDF_DEVICES
);
134 UnLockDosList(LDF_READ
);
137 if (IsFileSystem(dname
))
139 return (struct FileSysStartupMsg
*)BADDR(dn
->dn_Startup
);
142 printf("device '%s' doesn't contain a file system\n", dname
);
145 PrintFault(ERROR_OBJECT_NOT_FOUND
, dname
);
149 printf("'%s' doesn't contain a device name\n",path
);
153 void fillGeometry(struct Volume
*volume
, struct DosEnvec
*de
) {
156 D(bug("[install-i386] fillGeometry(%x)\n", volume
));
158 spc
= de
->de_Surfaces
*de
->de_BlocksPerTrack
;
159 volume
->SizeBlock
= de
->de_SizeBlock
;
160 volume
->startblock
= de
->de_LowCyl
*spc
;
161 volume
->countblock
=((de
->de_HighCyl
-de
->de_LowCyl
+1)*spc
)-1+de
->de_Reserved
;
164 void nsdCheck(struct Volume
*volume
) {
165 struct NSDeviceQueryResult nsdq
;
168 D(bug("[install-i386] nsdCheck(%x)\n", volume
));
172 (volume
->startblock
+volume
->countblock
)* /* last block */
173 ((volume
->SizeBlock
<<2)/512) /* 1 portion (block) equals 512 (bytes) */
176 nsdq
.SizeAvailable
=0;
177 nsdq
.DevQueryFormat
=0;
178 volume
->iotd
->iotd_Req
.io_Command
=NSCMD_DEVICEQUERY
;
179 volume
->iotd
->iotd_Req
.io_Data
=&nsdq
;
180 volume
->iotd
->iotd_Req
.io_Length
=sizeof(struct NSDeviceQueryResult
);
181 if (DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
)==IOERR_NOCMD
)
183 printf("Device doesn't understand NSD-Query\n");
188 (volume
->iotd
->iotd_Req
.io_Actual
>sizeof(struct NSDeviceQueryResult
)) ||
189 (volume
->iotd
->iotd_Req
.io_Actual
==0) ||
190 (volume
->iotd
->iotd_Req
.io_Actual
!=nsdq
.SizeAvailable
)
193 printf("WARNING wrong io_Actual using NSD\n");
197 if (nsdq
.DeviceType
!= NSDEVTYPE_TRACKDISK
)
198 printf("WARNING no trackdisk type\n");
199 for (cmdcheck
=nsdq
.SupportedCommands
;*cmdcheck
;cmdcheck
++)
201 if (*cmdcheck
== NSCMD_TD_READ64
)
202 volume
->readcmd
= NSCMD_TD_READ64
;
203 if (*cmdcheck
== NSCMD_TD_WRITE64
);
204 volume
->writecmd
= NSCMD_TD_WRITE64
;
207 (volume
->readcmd
!=NSCMD_TD_READ64
) ||
208 (volume
->writecmd
!=NSCMD_TD_WRITE64
)
210 printf("WARNING no READ64/WRITE64\n");
217 struct Volume
*initVolume(STRPTR device
, ULONG unit
, ULONG flags
, struct DosEnvec
*de
) {
218 struct Volume
*volume
;
221 D(bug("[install-i386] initVolume(%s:%d)\n", device
, unit
));
223 volume
= AllocVec(sizeof(struct Volume
), MEMF_PUBLIC
| MEMF_CLEAR
);
226 volume
->mp
= CreateMsgPort();
229 volume
->iotd
= (struct IOExtTD
*)CreateIORequest(volume
->mp
, sizeof(struct IOExtTD
));
232 volume
->blockbuffer
= AllocVec(de
->de_SizeBlock
<<2, MEMF_PUBLIC
| MEMF_CLEAR
);
233 if (volume
->blockbuffer
)
240 (struct IORequest
*)volume
->iotd
,
245 if (strcmp(device
, "trackdisk.device")==0)
246 volume
->flags
|= VF_IS_TRACKDISK
;
248 volume
->flags
|= VF_IS_RDB
; /* just assume we have RDB */
249 volume
->readcmd
= CMD_READ
;
250 volume
->writecmd
= CMD_WRITE
;
251 volume
->device
= device
;
252 volume
->unitnum
= unit
;
253 fillGeometry(volume
, de
);
258 error
= ERROR_NO_FREE_STORE
;
259 FreeVec(volume
->blockbuffer
);
262 error
= ERROR_NO_FREE_STORE
;
263 DeleteIORequest((struct IORequest
*)volume
->iotd
);
266 error
= ERROR_NO_FREE_STORE
;
267 DeleteMsgPort(volume
->mp
);
270 error
= ERROR_NO_FREE_STORE
;
274 error
= ERROR_NO_FREE_STORE
;
275 PrintFault(error
, NULL
);
279 void uninitVolume(struct Volume
*volume
)
282 D(bug("[install-i386] uninitVolume(%x)\n", volume
));
284 CloseDevice((struct IORequest
*)volume
->iotd
);
285 FreeVec(volume
->blockbuffer
);
286 DeleteIORequest((struct IORequest
*)volume
->iotd
);
287 DeleteMsgPort(volume
->mp
);
293 struct Volume
*volume
,
294 ULONG block
, APTR buffer
, ULONG length
,
301 D(bug("[install-i386] readwriteBlock(vol:%x, block:%d, %d bytes)\n", volume
, block
, length
));
303 volume
->iotd
->iotd_Req
.io_Command
= command
;
304 volume
->iotd
->iotd_Req
.io_Length
= length
;
305 volume
->iotd
->iotd_Req
.io_Data
= buffer
;
306 offset
= (UQUAD
)(volume
->startblock
+block
)*(volume
->SizeBlock
<<2);
307 volume
->iotd
->iotd_Req
.io_Offset
= offset
& 0xFFFFFFFF;
308 volume
->iotd
->iotd_Req
.io_Actual
= offset
>>32;
309 retval
= DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
310 if (volume
->flags
& VF_IS_TRACKDISK
)
312 volume
->iotd
->iotd_Req
.io_Command
= TD_MOTOR
;
313 volume
->iotd
->iotd_Req
.io_Length
= 0;
314 DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
319 BOOL
isvalidFileSystem(struct Volume
*volume
, STRPTR device
, ULONG unit
) {
321 struct PartitionBase
*PartitionBase
;
322 struct PartitionHandle
*ph
;
324 D(bug("[install-i386] isvalidFileSystem(%x, %s, %d)\n", volume
, device
, unit
));
326 if (readwriteBlock(volume
, 0, volume
->blockbuffer
, 512, volume
->readcmd
))
328 printf("Read Error\n");
332 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300) ||
333 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF) == 0)
336 /* first block has no DOS\x so we don't have RDB for sure */
337 volume
->flags
&= ~VF_IS_RDB
;
338 if (readwriteBlock(volume
, 1, volume
->blockbuffer
, 512, volume
->readcmd
))
340 printf("Read Error\n");
344 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300) ||
345 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF) == 0)
349 volume
->partnum
= -1;
350 PartitionBase
= (struct PartitionBase
*)OpenLibrary("partition.library", 1);
353 ph
= OpenRootPartition(device
, unit
);
356 if (OpenPartitionTable(ph
) == 0)
358 struct TagItem tags
[3];
361 tags
[1].ti_Tag
= TAG_DONE
;
362 tags
[0].ti_Tag
= PTT_TYPE
;
363 tags
[0].ti_Data
= (STACKIPTR
)&type
;
364 GetPartitionTableAttrs(ph
, tags
);
365 if (type
== PHPTT_MBR
)
367 struct PartitionHandle
*pn
;
369 struct PartitionHandle
*extph
= NULL
;
370 struct PartitionType ptype
= {{0}};
372 tags
[0].ti_Tag
= PT_DOSENVEC
;
373 tags
[0].ti_Data
= (STACKIPTR
)&de
;
374 tags
[1].ti_Tag
= PT_TYPE
;
375 tags
[1].ti_Data
= (STACKIPTR
)&ptype
;
376 tags
[2].ti_Tag
= TAG_DONE
;
377 pn
= (struct PartitionHandle
*)ph
->table
->list
.lh_Head
;
378 while (pn
->ln
.ln_Succ
)
382 GetPartitionAttrs(pn
, tags
);
383 if (ptype
.id
[0] == MBRT_EXTENDED
|| ptype
.id
[0] == MBRT_EXTENDED2
)
387 scp
= de
.de_Surfaces
*de
.de_BlocksPerTrack
;
389 (volume
->startblock
>=(de
.de_LowCyl
*scp
)) &&
390 (volume
->startblock
<=(((de
.de_HighCyl
+1)*scp
)-1))
394 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
398 tags
[0].ti_Tag
= PT_POSITION
;
399 tags
[0].ti_Data
= (STACKIPTR
)&type
;
400 tags
[1].ti_Tag
= TAG_DONE
;
401 GetPartitionAttrs(pn
, tags
);
402 volume
->partnum
= (UBYTE
)type
;
404 D(bug("[install-i386] Primary partition found: partnum=%ld\n", volume
->partnum
));
406 else if (extph
!= NULL
)
408 if (OpenPartitionTable(extph
) == 0)
410 tags
[0].ti_Tag
= PTT_TYPE
;
411 tags
[0].ti_Data
= (STACKIPTR
)&type
;
412 tags
[1].ti_Tag
= TAG_DONE
;
413 GetPartitionTableAttrs(extph
, tags
);
414 if (type
== PHPTT_EBR
)
416 tags
[0].ti_Tag
= PT_DOSENVEC
;
417 tags
[0].ti_Data
= (STACKIPTR
)&de
;
418 tags
[1].ti_Tag
= TAG_DONE
;
419 pn
= (struct PartitionHandle
*)extph
->table
->list
.lh_Head
;
420 while (pn
->ln
.ln_Succ
)
424 offset
= extph
->de
.de_LowCyl
425 * extph
->de
.de_Surfaces
426 * extph
->de
.de_BlocksPerTrack
;
427 GetPartitionAttrs(pn
, tags
);
428 scp
= de
.de_Surfaces
*de
.de_BlocksPerTrack
;
430 (volume
->startblock
>=offset
+(de
.de_LowCyl
*scp
)) &&
431 (volume
->startblock
<=offset
+(((de
.de_HighCyl
+1)*scp
)-1))
434 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
438 tags
[0].ti_Tag
= PT_POSITION
;
439 tags
[0].ti_Data
= (STACKIPTR
)&type
;
440 GetPartitionAttrs(pn
, tags
);
441 volume
->partnum
= MBR_MAX_PARTITIONS
+ (UBYTE
)type
;
443 D(bug("[install-i386] Logical partition found: partnum=%ld\n", volume
->partnum
));
446 ClosePartitionTable(extph
);
452 if (type
== PHPTT_RDB
)
454 /* just use whole hard disk */
458 printf("only MBR and RDB partition tables are supported\n");
460 ClosePartitionTable(ph
);
464 /* just use whole hard disk */
467 CloseRootPartition(ph
);
470 printf("Error OpenRootPartition(%s,%ld)\n", device
, unit
);
471 CloseLibrary((struct Library
*)PartitionBase
);
474 printf("Couldn't open partition.library\n");
478 struct Volume
*getGrubStageVolume
486 struct Volume
*volume
;
488 volume
= initVolume(device
, unit
, flags
, de
);
490 D(bug("[install-i386] getGrubStageVolume(): volume=%x\n", volume
));
494 if (isvalidFileSystem(volume
, device
, unit
))
498 printf("stage2 is on an unsupported file system\n");
499 PrintFault(ERROR_OBJECT_WRONG_TYPE
, NULL
);
501 uninitVolume(volume
);
506 BOOL isvalidPartition
514 struct PartitionBase
*PartitionBase
;
515 struct PartitionHandle
*ph
;
519 D(bug("[install-i386] isvalidPartition(%s:%d, part:%d)\n", device
, unit
, pnum
));
521 PartitionBase
= (struct PartitionBase
*)OpenLibrary("partition.library", 1);
524 ph
= OpenRootPartition(device
, unit
);
527 struct TagItem tags
[2];
529 tags
[1].ti_Tag
= TAG_DONE
;
530 /* is there a partition table? */
531 if (OpenPartitionTable(ph
) == 0)
535 /* install into partition bootblock */
536 tags
[0].ti_Tag
= PTT_TYPE
;
537 tags
[0].ti_Data
= (STACKIPTR
)&type
;
538 GetPartitionTableAttrs(ph
, tags
);
539 if (type
== PHPTT_MBR
)
541 struct PartitionHandle
*pn
;
543 /* search for partition */
544 tags
[0].ti_Tag
= PT_POSITION
;
545 tags
[0].ti_Data
= (STACKIPTR
)&type
;
546 pn
= (struct PartitionHandle
*)ph
->table
->list
.lh_Head
;
547 while (pn
->ln
.ln_Succ
)
549 GetPartitionAttrs(pn
, tags
);
552 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
556 struct PartitionType ptype
;
558 /* is it an AROS partition? */
559 tags
[0].ti_Tag
= PT_TYPE
;
560 tags
[0].ti_Data
= (STACKIPTR
)&ptype
;
561 GetPartitionAttrs(pn
, tags
);
562 if (ptype
.id
[0] == 0x30)
564 tags
[0].ti_Tag
= PT_DOSENVEC
;
565 tags
[0].ti_Data
= (STACKIPTR
)de
;
566 GetPartitionAttrs(pn
, tags
);
570 printf("partition is not of type AROS (0x30)\n");
576 "partition %ld not found on device %s unit %ld\n",
582 printf("you can only install in partitions which are MBR partitioned\n");
586 /* install into MBR */
587 tags
[0].ti_Tag
= PTT_TYPE
;
588 tags
[0].ti_Data
= (STACKIPTR
)&type
;
589 GetPartitionTableAttrs(ph
, tags
);
590 if ((type
== PHPTT_MBR
) || (type
== PHPTT_RDB
))
592 tags
[0].ti_Tag
= PT_DOSENVEC
;
593 tags
[0].ti_Data
= (STACKIPTR
)de
;
594 GetPartitionAttrs(ph
, tags
);
598 printf("partition table type must be either MBR or RDB\n");
600 ClosePartitionTable(ph
);
604 #warning "FIXME: GetPartitionAttr() should always work for root partition"
605 CopyMem(&ph
->de
, de
, sizeof(struct DosEnvec
));
608 CloseRootPartition(ph
);
611 printf("Error OpenRootPartition(%s,%ld)\n", device
, unit
);
612 CloseLibrary((struct Library
*)PartitionBase
);
615 printf("Couldn't open partition.library\n");
619 struct Volume
*getBBVolume(STRPTR device
, ULONG unit
, LONG
*partnum
) {
620 struct Volume
*volume
;
623 D(bug("[install-i386] getBBVolume(%s:%d, %d)\n", device
, unit
, partnum
));
625 if (isvalidPartition(device
, unit
, partnum
, &de
))
627 volume
= initVolume(device
, unit
, 0, &de
);
628 volume
->partnum
= partnum
? *partnum
: -1;
629 readwriteBlock(volume
, 0, volume
->blockbuffer
, 512, volume
->readcmd
);
630 if (AROS_BE2LONG(volume
->blockbuffer
[0]) != IDNAME_RIGIDDISK
)
632 memset(volume
->blockbuffer
,0x00, 446); /* Clear the boot sector region! */
636 printf("no space for bootblock (RDB is on block 0)\n");
641 ULONG collectBlockList
643 struct Volume
*volume
,
645 struct BlockNode
*blocklist
648 ULONG retval
, first_block
;
649 WORD blk_count
,count
;
652 D(bug("[install-i386] collectBlockList(%x, %d, %x)\n", volume
, block
, blocklist
));
654 #warning "TODO: logical/physical blocks"
656 initialze stage2-blocklist
657 (it is NULL-terminated)
659 // for (blk_count=-1;blocklist[blk_count].sector!=0;blk_count--)
660 // blocklist[blk_count].sector = 0;
662 memset((char *)&blocklist
[-20],0x00, 20*sizeof(struct BlockNode
)); /* Clear the stage2 sector pointers region! */
663 D(bug("[install-i386] collectBlockList: Cleared sector list (20 entries) [start: %x, end %x]\n", &blocklist
[-20], &blocklist
[-1]));
666 the first block of stage2 will be stored in stage1
667 so skip the first filekey in the first loop
669 #warning "Block read twice"
670 retval
=readwriteBlock
672 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
<<2,
677 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld\n", retval
));
678 printf("ReadError %ld\n", retval
);
682 i
= volume
->SizeBlock
- 52;
683 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
686 D(bug("[install-i386] collectBlockList: First block @ %x, i:%d\n", first_block
, i
));
691 retval
=readwriteBlock
693 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
<<2,
698 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld)\n", retval
));
699 printf("ReadError %ld\n", retval
);
702 D(bug("[install-i386] collectBlockList: read block %lx, i = %d\n", block
, i
));
703 while ((i
>=6) && (volume
->blockbuffer
[i
]))
705 D(bug("[install-i386] collectBlockList: i = %d\n", i
));
707 if current sector follows right after last sector
708 then we don't need a new element
711 (blocklist
[blk_count
].sector
) &&
712 ((blocklist
[blk_count
].sector
+blocklist
[blk_count
].count
)==
713 AROS_BE2LONG(volume
->blockbuffer
[i
]))
716 blocklist
[blk_count
].count
+= 1;
717 D(bug("[install-i386] collectBlockList: sector %d follows previous - increasing count of block %d to %d\n", i
, blk_count
, blocklist
[blk_count
].count
));
721 blk_count
--; /* decrement first */
722 D(bug("[install-i386] collectBlockList: store new block (%d)\n", blk_count
));
723 if (blocklist
[blk_count
-1].sector
!= 0)
725 D(bug("[install-i386] collectBlockList: ERROR: out of block space at sector %d, block %d\n", i
, blk_count
));
726 printf("There is no more space to save blocklist in stage2\n");
729 D(bug("[install-i386] collectBlockList: storing sector pointer for %d in block %d\n", i
, blk_count
));
730 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
731 blocklist
[blk_count
].count
= 1;
735 i
= volume
->SizeBlock
- 51;
736 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
737 D(bug("[install-i386] collectBlockList: next block %d, i = %d\n", block
, i
));
740 blocks in blocklist are relative to the first
741 sector of the HD (not partition)
743 D(bug("[install-i386] collectBlockList: successfully updated pointers for %d blocks\n", blk_count
));
746 for (count
=-1;count
>=blk_count
;count
--)
748 blocklist
[count
].sector
+= volume
->startblock
;
749 blocklist
[count
].seg_adr
= 0x820 + (i
*32);
750 i
+= blocklist
[count
].count
;
751 D(bug("[install-i386] collectBlockList: correcting block %d for partition start\n", count
));
752 D(bug("[install-i386] collectBlockList: sector : %x seg_adr : %x\n", blocklist
[count
].sector
, blocklist
[count
].seg_adr
));
757 void copyRootPath(char *dst
, char *rpdos
, BOOL isRDB
) {
759 D(bug("[install-i386] copyRootPath()\n"));
763 /* we have an RDB so use devicename */
765 while ((*rpdos
) && (*rpdos
!=':'))
770 while ((*rpdos
) && (*rpdos
!=':'))
773 rpdos
++; /* skip colon */
784 /* Convert a unit number into a drive number as understood by GRUB */
785 UWORD
getDriveNumber(CONST_STRPTR device
, ULONG unit
)
787 struct PartitionHandle
*ph
;
791 for (i
= 0; i
< unit
; i
++)
793 ph
= OpenRootPartition(device
, i
);
797 CloseRootPartition(ph
);
804 UBYTE
*memstr(UBYTE
*mem
, UBYTE
*str
, LONG len
) {
817 while ((*search
) && (left
) && (*next
++ == *search
++))
831 struct Volume
*volume
837 D(bug("[install-i386] writeStage2(%x)\n", volume
));
839 if (Seek(fh
, 0, OFFSET_BEGINNING
) != -1)
841 /* write back first block */
842 if (Write(fh
, buffer
, 512)==512)
844 /* read second stage2 block */
845 if (Read(fh
, buffer
, 512) == 512)
847 /* set partition number where stage2 is on */
850 buffer
[10] = volume
->partnum
;
852 /* get ptr to version string */
853 menuname
= buffer
+18;
854 while (*menuname
++); /* skip version string */
855 copyRootPath(menuname
, grubpath
, volume
->flags
& VF_IS_RDB
);
856 strcat(menuname
, "/menu.lst");
857 /* write second stage2 block back */
858 if (Seek(fh
, -512, OFFSET_CURRENT
) != -1)
860 if (Write(fh
, buffer
, 512) == 512)
865 printf("%s: Write Error\n", menuname
);
868 printf("%s: Seek Error\n", menuname
);
871 printf("Read Error\n");
874 printf("Write Error\n");
877 PrintFault(IoErr(), NULL
);
883 STRPTR grubpath
, /* path of grub dir */
884 struct Volume
*volume
, /* volume stage2 is on */
885 ULONG
*buffer
/* a buffer of at least 512 bytes */
889 struct FileInfoBlock fib
;
891 char stage2path
[256];
893 D(bug("[install-i386] changeStage2(%x)\n", volume
));
895 AddPart(stage2path
, grubpath
, 256);
896 AddPart(stage2path
, "stage2", 256);
897 fh
= Open(stage2path
, MODE_OLDFILE
);
900 if (Examine(fh
, &fib
))
902 if (Read(fh
, buffer
, 512) == 512)
905 get and store all blocks of stage2 in first block of stage2
906 first block of stage2 will be returned
908 block
= collectBlockList
909 (volume
, fib
.fib_DiskKey
, (struct BlockNode
*)&buffer
[128]);
913 if (!writeStage2(fh
, (UBYTE
*)buffer
, grubpath
, volume
))
918 printf("%s: Read Error\n", stage2path
);
921 PrintFault(IoErr(), stage2path
);
925 PrintFault(IoErr(), stage2path
);
932 struct Volume
*volume
,
933 struct Volume
*s2vol
,
934 ULONG block
, /* first block of stage2 file */
942 D(bug("[install-i386] writeStage1(%x)\n", volume
));
944 fh
= Open(stage1path
, MODE_OLDFILE
);
947 if (Read(fh
, volume
->blockbuffer
, 512) == 512)
949 /* install into MBR ? */
950 if ((volume
->startblock
== 0) && (!(volume
->flags
& VF_IS_TRACKDISK
)))
952 D(bug("[install-i386] writeStage1: Install to HARDDISK\n"));
954 error
= readwriteBlock
955 (volume
, 0, s2vol
->blockbuffer
, 512, volume
->readcmd
);
957 D(bug("[install-i386] writeStage1: MBR Buffer @ %x\n", volume
->blockbuffer
));
958 D(bug("[install-i386] writeStage1: Copying MBR BPB to %x\n", (char *)volume
->blockbuffer
+ 0x04));
959 // copy BPB (BIOS Parameter Block)
962 (APTR
)((char *)s2vol
->blockbuffer
+ 0x04),
963 (APTR
)((char *)volume
->blockbuffer
+ 0x04),
966 // copy partition table - [Overwrites Floppy boot code]
967 D(bug("[install-i386] writeStage1: Copying MBR Partitions to %x\n", (char *)volume
->blockbuffer
+ MBR_PARTSTART
));
970 (APTR
)((char *)s2vol
->blockbuffer
+ MBR_PARTSTART
),
971 (APTR
)((char *)volume
->blockbuffer
+ MBR_PARTSTART
),
972 (MBR_PARTEND
- MBR_PARTSTART
)
974 // store the drive num stage2 is stored on
975 ((char *)volume
->blockbuffer
)[GRUB_BOOT_DRIVE
] =
976 getDriveNumber(volume
->device
, unit
) | BIOS_HDISK_FLAG
;
977 // Store the stage 2 pointer ..
978 ULONG
* stage2_sector_start
= (ULONG
*)((char *)volume
->blockbuffer
+ GRUB_STAGE2_SECTOR
);
979 D(bug("[install-i386] writeStage1: writing stage2 pointer @ %x\n", stage2_sector_start
));
980 stage2_sector_start
[0] = block
;
981 D(bug("[install-i386] writeStage1: stage2 pointer = %x\n", stage2_sector_start
[0]));
982 stage2_sector_start
[0] += s2vol
->startblock
;
983 D(bug("[install-i386] writeStage1: + offset [%d] = %x\n", s2vol
->startblock
, stage2_sector_start
[0]));
987 D(bug("[install-i386] writeStage1: Forcing LBA\n"));
988 ((char *)volume
->blockbuffer
)[GRUB_FORCE_LBA
] = 1;
992 D(bug("[install-i386] writeStage1: NOT Forcing LBA\n"));
993 ((char *)volume
->blockbuffer
)[GRUB_FORCE_LBA
] = 0;
998 D(bug("[install-i386] writeStage1: Install to FLOPPY\n"));
1003 error
= readwriteBlock
1004 (volume
, 0, volume
->blockbuffer
, 512, volume
->writecmd
);
1006 printf("WriteError %ld\n", error
);
1011 printf("WriteError %ld\n", error
);
1014 printf("%s: Read Error\n", stage1path
);
1018 PrintFault(IoErr(), stage1path
);
1022 /* Flushes the cache on the volume containing the specified path. */
1023 VOID
flushFS(CONST TEXT
*path
)
1028 for (i
= 0; path
[i
] != ':'; i
++)
1029 devname
[i
] = path
[i
];
1032 if (Inhibit(devname
, DOSTRUE
))
1033 Inhibit(devname
, DOSFALSE
);
1036 BOOL installStageFiles
1038 struct Volume
*s2vol
, /* stage2 volume */
1039 STRPTR stagepath
, /* path to stage* files */
1040 ULONG unit
, /* unit stage2 is on */
1041 struct Volume
*s1vol
/* device on which stage1 will be stored */
1044 BOOL retval
= FALSE
;
1045 char stagename
[256];
1048 D(bug("[install-i386] installStageFiles(%x)\n", s1vol
));
1050 /* Flush GRUB volume's cache */
1053 block
= changeStage2(stagepath
, s2vol
, s1vol
->blockbuffer
);
1056 AddPart(stagename
, stagepath
, 256);
1057 AddPart(stagename
, "stage1", 256);
1058 if (writeStage1(stagename
, s1vol
, s2vol
, block
, unit
))
1064 int main(int argc
, char **argv
) {
1066 struct RDArgs
*rdargs
;
1067 struct Volume
*grubvol
;
1068 struct Volume
*bbvol
;
1069 struct FileSysStartupMsg
*fssm
;
1071 D(bug("[install-i386] main()\n"));
1073 rdargs
= ReadArgs(template, myargs
, NULL
);
1076 D(bug("[install-i386] FORCELBA = %d\n",myargs
[4]));
1078 fssm
= getDiskFSSM((STRPTR
)myargs
[3]);
1082 (strcmp(AROS_BSTR_ADDR(fssm
->fssm_Device
),(char*)myargs
[0])==0)
1085 grubvol
= getGrubStageVolume
1087 AROS_BSTR_ADDR(fssm
->fssm_Device
),
1090 (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
)
1097 *((LONG
*)myargs
[1]),
1104 getBBVolume() read block 0
1105 if the partition directly contains a filesystem
1106 (currently only DOS\x is supported) we have
1107 to move block 0 to block 1 to make space for stage1
1110 (grubvol
->startblock
== bbvol
->startblock
) &&
1111 ((AROS_BE2LONG(bbvol
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
1114 grubvol
->flags
&= ~VF_IS_RDB
;
1115 retval
= readwriteBlock
1116 (bbvol
, 0, bbvol
->blockbuffer
, 512, bbvol
->readcmd
);
1123 (STRPTR
)myargs
[3], /* grub path (stage1/2) */
1129 printf("Read Error: %ld\n", retval
);
1130 uninitVolume(bbvol
);
1132 uninitVolume(grubvol
);
1139 "%s is not on device %s unit %ld\n",
1140 (STRPTR
)myargs
[3], (STRPTR
)myargs
[0], *((LONG
*)myargs
[1])
1146 printf("kernel path must begin with a device name\n");
1150 PrintFault(IoErr(), argv
[0]);