2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
9 #include <proto/exec.h>
10 #include <proto/partition.h>
11 #include <aros/macros.h>
12 #include <devices/hardblocks.h>
13 #include <devices/newstyle.h>
15 #include <exec/errors.h>
16 #include <exec/memory.h>
17 #include <libraries/partition.h>
20 #include <aros/debug.h>
22 /* Defines for grub data */
23 /* Stage 1 pointers */
24 #define MBR_BPBEND 0x3e
25 #define GRUB_BOOT_DRIVE 0x40
26 #define GRUB_FORCE_LBA 0x41
27 #define GRUB_STAGE2_SECTOR 0x44
28 #define MBR_PARTSTART 0x1be
29 #define MBR_PARTEND 0x1fe
30 /* Stage 2 pointers */
33 #define BIOS_HDISK_FLAG 0x80
49 #define VF_IS_TRACKDISK (1<<0)
50 #define VF_IS_RDB (1<<1)
58 #warning "TODO: Rename FORCELBA to USELBA and add a FORCE switch that causes install to not check for existing bootloader"
62 "PARTITIONNUMBER=PN/K/N,"
66 IPTR myargs
[7] = {0,0,0,0,0,0};
68 struct FileSysStartupMsg
*getDiskFSSM(STRPTR path
) {
70 struct DeviceNode
*dn
;
74 D(bug("[install-i386] getDiskFSSM('%s')\n", path
));
76 for (i
=0;(path
[i
]) && (path
[i
]!=':');i
++)
81 dl
= LockDosList(LDF_READ
);
84 dn
= (struct DeviceNode
*)FindDosEntry(dl
, dname
, LDF_DEVICES
);
85 UnLockDosList(LDF_READ
);
88 if (IsFileSystem(dname
))
90 return (struct FileSysStartupMsg
*)BADDR(dn
->dn_Startup
);
93 printf("device '%s' doesn't contain a file system\n", dname
);
96 PrintFault(ERROR_OBJECT_NOT_FOUND
, dname
);
100 printf("'%s' doesn't contain a device name\n",path
);
104 void fillGeometry(struct Volume
*volume
, struct DosEnvec
*de
) {
107 D(bug("[install-i386] fillGeometry(%x)\n", volume
));
109 spc
= de
->de_Surfaces
*de
->de_BlocksPerTrack
;
110 volume
->SizeBlock
= de
->de_SizeBlock
;
111 volume
->startblock
= de
->de_LowCyl
*spc
;
112 volume
->countblock
=((de
->de_HighCyl
-de
->de_LowCyl
+1)*spc
)-1+de
->de_Reserved
;
115 void nsdCheck(struct Volume
*volume
) {
116 struct NSDeviceQueryResult nsdq
;
119 D(bug("[install-i386] nsdCheck(%x)\n", volume
));
123 (volume
->startblock
+volume
->countblock
)* /* last block */
124 ((volume
->SizeBlock
<<2)/512) /* 1 portion (block) equals 512 (bytes) */
127 nsdq
.SizeAvailable
=0;
128 nsdq
.DevQueryFormat
=0;
129 volume
->iotd
->iotd_Req
.io_Command
=NSCMD_DEVICEQUERY
;
130 volume
->iotd
->iotd_Req
.io_Data
=&nsdq
;
131 volume
->iotd
->iotd_Req
.io_Length
=sizeof(struct NSDeviceQueryResult
);
132 if (DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
)==IOERR_NOCMD
)
134 printf("Device doesn't understand NSD-Query\n");
139 (volume
->iotd
->iotd_Req
.io_Actual
>sizeof(struct NSDeviceQueryResult
)) ||
140 (volume
->iotd
->iotd_Req
.io_Actual
==0) ||
141 (volume
->iotd
->iotd_Req
.io_Actual
!=nsdq
.SizeAvailable
)
144 printf("WARNING wrong io_Actual using NSD\n");
148 if (nsdq
.DeviceType
!= NSDEVTYPE_TRACKDISK
)
149 printf("WARNING no trackdisk type\n");
150 for (cmdcheck
=nsdq
.SupportedCommands
;*cmdcheck
;cmdcheck
++)
152 if (*cmdcheck
== NSCMD_TD_READ64
)
153 volume
->readcmd
= NSCMD_TD_READ64
;
154 if (*cmdcheck
== NSCMD_TD_WRITE64
);
155 volume
->writecmd
= NSCMD_TD_WRITE64
;
158 (volume
->readcmd
!=NSCMD_TD_READ64
) ||
159 (volume
->writecmd
!=NSCMD_TD_WRITE64
)
161 printf("WARNING no READ64/WRITE64\n");
168 struct Volume
*initVolume(STRPTR device
, ULONG unit
, ULONG flags
, struct DosEnvec
*de
) {
169 struct Volume
*volume
;
172 D(bug("[install-i386] initVolume(%s:%d)\n", device
, unit
));
174 volume
= AllocVec(sizeof(struct Volume
), MEMF_PUBLIC
| MEMF_CLEAR
);
177 volume
->mp
= CreateMsgPort();
180 volume
->iotd
= (struct IOExtTD
*)CreateIORequest(volume
->mp
, sizeof(struct IOExtTD
));
183 volume
->blockbuffer
= AllocVec(de
->de_SizeBlock
<<2, MEMF_PUBLIC
| MEMF_CLEAR
);
184 if (volume
->blockbuffer
)
191 (struct IORequest
*)volume
->iotd
,
196 if (strcmp(device
, "trackdisk.device")==0)
197 volume
->flags
|= VF_IS_TRACKDISK
;
199 volume
->flags
|= VF_IS_RDB
; /* just assume we have RDB */
200 volume
->readcmd
= CMD_READ
;
201 volume
->writecmd
= CMD_WRITE
;
202 volume
->unitnum
= unit
;
203 fillGeometry(volume
, de
);
208 error
= ERROR_NO_FREE_STORE
;
209 FreeVec(volume
->blockbuffer
);
212 error
= ERROR_NO_FREE_STORE
;
213 DeleteIORequest((struct IORequest
*)volume
->iotd
);
216 error
= ERROR_NO_FREE_STORE
;
217 DeleteMsgPort(volume
->mp
);
220 error
= ERROR_NO_FREE_STORE
;
224 error
= ERROR_NO_FREE_STORE
;
225 PrintFault(error
, NULL
);
229 void uninitVolume(struct Volume
*volume
)
232 D(bug("[install-i386] uninitVolume(%x)\n", volume
));
234 CloseDevice((struct IORequest
*)volume
->iotd
);
235 FreeVec(volume
->blockbuffer
);
236 DeleteIORequest((struct IORequest
*)volume
->iotd
);
237 DeleteMsgPort(volume
->mp
);
243 struct Volume
*volume
,
244 ULONG block
, APTR buffer
, ULONG length
,
251 D(bug("[install-i386] readwriteBlock(vol:%x, block:%d, %d bytes)\n", volume
, block
, length
));
253 volume
->iotd
->iotd_Req
.io_Command
= command
;
254 volume
->iotd
->iotd_Req
.io_Length
= length
;
255 volume
->iotd
->iotd_Req
.io_Data
= buffer
;
256 offset
= (UQUAD
)(volume
->startblock
+block
)*(volume
->SizeBlock
<<2);
257 volume
->iotd
->iotd_Req
.io_Offset
= offset
& 0xFFFFFFFF;
258 volume
->iotd
->iotd_Req
.io_Actual
= offset
>>32;
259 retval
= DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
260 if (volume
->flags
& VF_IS_TRACKDISK
)
262 volume
->iotd
->iotd_Req
.io_Command
= TD_MOTOR
;
263 volume
->iotd
->iotd_Req
.io_Length
= 0;
264 DoIO((struct IORequest
*)&volume
->iotd
->iotd_Req
);
269 BOOL
isvalidFileSystem(struct Volume
*volume
, STRPTR device
, ULONG unit
) {
271 struct PartitionBase
*PartitionBase
;
272 struct PartitionHandle
*ph
;
274 D(bug("[install-i386] isvalidFileSystem(%x, %s, %d)\n", volume
, device
, unit
));
276 if (readwriteBlock(volume
, 0, volume
->blockbuffer
, 512, volume
->readcmd
))
278 printf("Read Error\n");
282 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300) ||
283 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF) == 0)
286 /* first block has no DOS\x so we don't have RDB for sure */
287 volume
->flags
&= ~VF_IS_RDB
;
288 if (readwriteBlock(volume
, 1, volume
->blockbuffer
, 512, volume
->readcmd
))
290 printf("Read Error\n");
294 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFFFFFF00)!=0x444F5300) ||
295 ((AROS_BE2LONG(volume
->blockbuffer
[0]) & 0xFF) == 0)
299 volume
->partnum
= -1;
300 PartitionBase
= (struct PartitionBase
*)OpenLibrary("partition.library", 1);
303 ph
= OpenRootPartition(device
, unit
);
306 if (OpenPartitionTable(ph
) == 0)
308 struct TagItem tags
[2];
311 tags
[1].ti_Tag
= TAG_DONE
;
312 tags
[0].ti_Tag
= PTT_TYPE
;
313 tags
[0].ti_Data
= (STACKIPTR
)&type
;
314 GetPartitionTableAttrs(ph
, tags
);
315 if (type
== PHPTT_MBR
)
317 struct PartitionHandle
*pn
;
320 tags
[0].ti_Tag
= PT_DOSENVEC
;
321 tags
[0].ti_Data
= (STACKIPTR
)&de
;
322 pn
= (struct PartitionHandle
*)ph
->table
->list
.lh_Head
;
323 while (pn
->ln
.ln_Succ
)
327 GetPartitionAttrs(pn
, tags
);
328 scp
= de
.de_Surfaces
*de
.de_BlocksPerTrack
;
330 (volume
->startblock
>=(de
.de_LowCyl
*scp
)) &&
331 (volume
->startblock
<=(((de
.de_HighCyl
+1)*scp
)-1))
334 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
338 tags
[0].ti_Tag
= PT_POSITION
;
339 tags
[0].ti_Data
= (STACKIPTR
)&type
;
340 GetPartitionAttrs(pn
, tags
);
341 volume
->partnum
= (UBYTE
)type
;
347 if (type
== PHPTT_RDB
)
349 /* just use whole hard disk */
353 printf("only MBR and RDB partition tables are supported\n");
355 ClosePartitionTable(ph
);
359 /* just use whole hard disk */
362 CloseRootPartition(ph
);
365 printf("Error OpenRootPartition(%s,%ld)\n", device
, unit
);
366 CloseLibrary((struct Library
*)PartitionBase
);
369 printf("Couldn't open partition.library\n");
373 struct Volume
*getGrubStageVolume
381 struct Volume
*volume
;
383 volume
= initVolume(device
, unit
, flags
, de
);
385 D(bug("[install-i386] getGrubStageVolume(): volume=%x\n", volume
));
389 if (isvalidFileSystem(volume
, device
, unit
))
393 printf("stage2 is on an unsupported file system\n");
394 PrintFault(ERROR_OBJECT_WRONG_TYPE
, NULL
);
396 uninitVolume(volume
);
401 BOOL isvalidPartition
409 struct PartitionBase
*PartitionBase
;
410 struct PartitionHandle
*ph
;
414 D(bug("[install-i386] isvalidPartition(%s:%d, part:%d)\n", device
, unit
, pnum
));
416 PartitionBase
= (struct PartitionBase
*)OpenLibrary("partition.library", 1);
419 ph
= OpenRootPartition(device
, unit
);
422 struct TagItem tags
[2];
424 tags
[1].ti_Tag
= TAG_DONE
;
425 /* is there a partition table? */
426 if (OpenPartitionTable(ph
) == 0)
430 /* install into partition bootblock */
431 tags
[0].ti_Tag
= PTT_TYPE
;
432 tags
[0].ti_Data
= (STACKIPTR
)&type
;
433 GetPartitionTableAttrs(ph
, tags
);
434 if (type
== PHPTT_MBR
)
436 struct PartitionHandle
*pn
;
438 /* search for partition */
439 tags
[0].ti_Tag
= PT_POSITION
;
440 tags
[0].ti_Data
= (STACKIPTR
)&type
;
441 pn
= (struct PartitionHandle
*)ph
->table
->list
.lh_Head
;
442 while (pn
->ln
.ln_Succ
)
444 GetPartitionAttrs(pn
, tags
);
447 pn
= (struct PartitionHandle
*)pn
->ln
.ln_Succ
;
451 struct PartitionType ptype
;
453 /* is it an AROS partition? */
454 tags
[0].ti_Tag
= PT_TYPE
;
455 tags
[0].ti_Data
= (STACKIPTR
)&ptype
;
456 GetPartitionAttrs(pn
, tags
);
457 if (ptype
.id
[0] == 0x30)
459 tags
[0].ti_Tag
= PT_DOSENVEC
;
460 tags
[0].ti_Data
= (STACKIPTR
)de
;
461 GetPartitionAttrs(pn
, tags
);
465 printf("partition is not of type AROS (0x30)\n");
471 "partition %ld not found on device %s unit %ld\n",
477 printf("you can only install in partitions which are MBR partitioned\n");
481 /* install into MBR */
482 tags
[0].ti_Tag
= PTT_TYPE
;
483 tags
[0].ti_Data
= (STACKIPTR
)&type
;
484 GetPartitionTableAttrs(ph
, tags
);
485 if ((type
== PHPTT_MBR
) || (type
== PHPTT_RDB
))
487 tags
[0].ti_Tag
= PT_DOSENVEC
;
488 tags
[0].ti_Data
= (STACKIPTR
)de
;
489 GetPartitionAttrs(ph
, tags
);
493 printf("partition table type must be either MBR or RDB\n");
495 ClosePartitionTable(ph
);
499 #warning "FIXME: GetPartitionAttr() should always work for root partition"
500 CopyMem(&ph
->de
, de
, sizeof(struct DosEnvec
));
503 CloseRootPartition(ph
);
506 printf("Error OpenRootPartition(%s,%ld)\n", device
, unit
);
507 CloseLibrary((struct Library
*)PartitionBase
);
510 printf("Couldn't open partition.library\n");
514 struct Volume
*getBBVolume(STRPTR device
, ULONG unit
, LONG
*partnum
) {
515 struct Volume
*volume
;
518 D(bug("[install-i386] getBBVolume(%s:%d, %d)\n", device
, unit
, partnum
));
520 if (isvalidPartition(device
, unit
, partnum
, &de
))
522 volume
= initVolume(device
, unit
, 0, &de
);
523 volume
->partnum
= partnum
? *partnum
: -1;
524 readwriteBlock(volume
, 0, volume
->blockbuffer
, 512, volume
->readcmd
);
525 if (AROS_BE2LONG(volume
->blockbuffer
[0]) != IDNAME_RIGIDDISK
)
527 memset(volume
->blockbuffer
,0x00, 446); /* Clear the boot sector region! */
531 printf("no space for bootblock (RDB is on block 0)\n");
536 ULONG collectBlockList
538 struct Volume
*volume
,
540 struct BlockNode
*blocklist
543 ULONG retval
, first_block
;
544 WORD blk_count
,count
;
547 D(bug("[install-i386] collectBlockList(%x, %d, %x)\n", volume
, block
, blocklist
));
549 #warning "TODO: logical/physical blocks"
551 initialze stage2-blocklist
552 (it is NULL-terminated)
554 // for (blk_count=-1;blocklist[blk_count].sector!=0;blk_count--)
555 // blocklist[blk_count].sector = 0;
557 memset((char *)&blocklist
[-20],0x00, 20*sizeof(struct BlockNode
)); /* Clear the stage2 sector pointers region! */
558 D(bug("[install-i386] collectBlockList: Cleared sector list (20 entries) [start: %x, end %x]\n", &blocklist
[-20], &blocklist
[-1]));
561 the first block of stage2 will be stored in stage1
562 so skip the first filekey in the first loop
564 #warning "Block read twice"
565 retval
=readwriteBlock
567 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
<<2,
572 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld\n", retval
));
573 printf("ReadError %ld\n", retval
);
577 i
= volume
->SizeBlock
- 52;
578 first_block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
-51]);
581 D(bug("[install-i386] collectBlockList: First block @ %x, i:%d\n", first_block
, i
));
586 retval
=readwriteBlock
588 volume
, block
, volume
->blockbuffer
, volume
->SizeBlock
<<2,
593 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld)\n", retval
));
594 printf("ReadError %ld\n", retval
);
597 D(bug("[install-i386] collectBlockList: read block %lx, i = %d\n", block
, i
));
598 while ((i
>=6) && (volume
->blockbuffer
[i
]))
600 D(bug("[install-i386] collectBlockList: i = %d\n", i
));
602 if current sector follows right after last sector
603 then we don't need a new element
606 (blocklist
[blk_count
].sector
) &&
607 ((blocklist
[blk_count
].sector
+blocklist
[blk_count
].count
)==
608 AROS_BE2LONG(volume
->blockbuffer
[i
]))
611 blocklist
[blk_count
].count
+= 1;
612 D(bug("[install-i386] collectBlockList: sector %d follows previous - increasing count of block %d to %d\n", i
, blk_count
, blocklist
[blk_count
].count
));
616 blk_count
--; /* decrement first */
617 D(bug("[install-i386] collectBlockList: store new block (%d)\n", blk_count
));
618 if (blocklist
[blk_count
-1].sector
!= 0)
620 D(bug("[install-i386] collectBlockList: ERROR: out of block space at sector %d, block %d\n", i
, blk_count
));
621 printf("There is no more space to save blocklist in stage2\n");
624 D(bug("[install-i386] collectBlockList: storing sector pointer for %d in block %d\n", i
, blk_count
));
625 blocklist
[blk_count
].sector
= AROS_BE2LONG(volume
->blockbuffer
[i
]);
626 blocklist
[blk_count
].count
= 1;
630 i
= volume
->SizeBlock
- 51;
631 block
= AROS_BE2LONG(volume
->blockbuffer
[volume
->SizeBlock
- 2]);
632 D(bug("[install-i386] collectBlockList: next block %d, i = %d\n", block
, i
));
635 blocks in blocklist are relative to the first
636 sector of the HD (not partition)
638 D(bug("[install-i386] collectBlockList: successfully updated pointers for %d blocks\n", blk_count
));
641 for (count
=-1;count
>=blk_count
;count
--)
643 blocklist
[count
].sector
+= volume
->startblock
;
644 blocklist
[count
].seg_adr
= 0x820 + (i
*32);
645 i
+= blocklist
[count
].count
;
646 D(bug("[install-i386] collectBlockList: correcting block %d for partition start\n", count
));
647 D(bug("[install-i386] collectBlockList: sector : %x seg_adr : %x\n", blocklist
[count
].sector
, blocklist
[count
].seg_adr
));
652 void copyRootPath(char *dst
, char *rpdos
, BOOL isRDB
) {
654 D(bug("[install-i386] copyRootPath()\n"));
658 /* we have an RDB so use devicename */
660 while ((*rpdos
) && (*rpdos
!=':'))
665 while ((*rpdos
) && (*rpdos
!=':'))
668 rpdos
++; /* skip colon */
679 UBYTE
*memstr(UBYTE
*mem
, UBYTE
*str
, LONG len
) {
692 while ((*search
) && (left
) && (*next
++ == *search
++))
701 BOOL
setUpMenu(BPTR fh
, struct Volume
*volume
)
704 LONG config_length
= 0;
706 UBYTE
*buffer
= NULL
;
709 UBYTE
*position
= NULL
;
716 "configfile /dh0/boot/grub/menu.lst\n";
718 D(bug("[install-i386] setUpMenu(%x, %x)\n", fh
, volume
));
720 /* Get the filesize and reset the position */
721 Seek(fh
, 0, OFFSET_END
);
722 length
= Seek(fh
, 0, OFFSET_BEGINNING
);
724 /* Allocate memory for file data */
725 buffer
= AllocVec(length
, MEMF_ANY
);
726 if (buffer
== NULL
) goto error
;
728 /* Read in the entire file */
729 read
= Read(fh
, buffer
, length
);
732 printf("ERROR: Could not read entire file.\n");
736 /* Find begin marker */
737 start
= memstr(buffer
, "# [B] (DO NOT REMOVE THIS LINE!)", length
);
740 printf("ERROR: Could not find start marker!?\n");
743 start
+= strlen("# [B] (DO NOT REMOVE THIS LINE!)") + 2;
745 /* Find end marker */
746 stop
= memstr(buffer
, "# [E] (DO NOT REMOVE THIS LINE!)", length
);
749 printf("ERROR: Could not find stop marker!?\n");
753 /* Write the new menu config */
754 config_length
= snprintf(start
, stop
- start
- 1, line
,
755 volume
->unitnum
, volume
->partnum
);
757 /* Check if there was enough space */
758 if ((stop
- start
) <= config_length
)
760 printf("ERROR: Not enough space to set up menu.\n");
765 for (position
= start
+ config_length
; position
< stop
; position
++)
770 /* Write the new file out */
771 Seek(fh
, 0, OFFSET_BEGINNING
);
772 Write(fh
, buffer
, length
);
779 if (buffer
!= NULL
) FreeVec(buffer
);
789 struct Volume
*volume
796 D(bug("[install-i386] writeStage2(%x)\n", volume
));
798 if (Seek(fh
, 0, OFFSET_BEGINNING
) != -1)
800 /* write back first block */
801 if (Write(fh
, buffer
, 512)==512)
803 /* read second stage2 block */
804 if (Read(fh
, buffer
, 512) == 512)
806 /* set partition number where stage2 is on */
809 buffer
[10] = volume
->partnum
;
811 /* get ptr to version string */
812 menuname
= buffer
+18;
813 while (*menuname
++); /* skip version string */
814 copyRootPath(menuname
, menupath
, volume
->flags
& VF_IS_RDB
);
815 strcat(menuname
, "/menu.lst");
816 /* write second stage2 block back */
817 if (Seek(fh
, -512, OFFSET_CURRENT
) != -1)
819 if (Write(fh
, buffer
, 512) == 512)
821 setUpMenu(fh
, volume
);
825 printf("%s: Write Error\n", menuname
);
828 printf("%s: Seek Error\n", menuname
);
831 printf("Read Error\n");
834 printf("Write Error\n");
837 PrintFault(IoErr(), NULL
);
843 STRPTR stage2path
, /* path of stage2 file */
844 STRPTR kernelpath
, /* path of the kernel image */
845 struct Volume
*volume
, /* volume stage2 is on */
846 ULONG
*buffer
/* a buffer of at least 512 bytes */
850 struct FileInfoBlock fib
;
853 D(bug("[install-i386] changeStage2(%x)\n", volume
));
855 fh
= Open(stage2path
, MODE_OLDFILE
);
858 if (Examine(fh
, &fib
))
860 if (Read(fh
, buffer
, 512) == 512)
863 get and store all blocks of stage2 in first block of stage2
864 first block of stage2 will be returned
866 block
= collectBlockList
867 (volume
, fib
.fib_DiskKey
, (struct BlockNode
*)&buffer
[128]);
871 if (!writeStage2(fh
, (UBYTE
*)buffer
, kernelpath
, volume
))
876 printf("%s: Read Error\n", stage2path
);
879 PrintFault(IoErr(), stage2path
);
883 PrintFault(IoErr(), stage2path
);
890 struct Volume
*volume
,
891 struct Volume
*s2vol
,
892 ULONG block
, /* first block of stage2 file */
900 D(bug("[install-i386] writeStage1(%x)\n", volume
));
902 fh
= Open(stage1path
, MODE_OLDFILE
);
905 if (Read(fh
, volume
->blockbuffer
, 512) == 512)
907 /* install into MBR ? */
908 if ((volume
->startblock
== 0) && (!(volume
->flags
& VF_IS_TRACKDISK
)))
910 D(bug("[install-i386] writeStage1: Install to HARDDISK\n"));
912 error
= readwriteBlock
913 (volume
, 0, s2vol
->blockbuffer
, 512, volume
->readcmd
);
915 D(bug("[install-i386] writeStage1: MBR Buffer @ %x\n", volume
->blockbuffer
));
916 D(bug("[install-i386] writeStage1: Copying MBR BPB to %x\n", (char *)volume
->blockbuffer
+ 0x04));
917 // copy BPB (BIOS Parameter Block)
920 (APTR
)((char *)s2vol
->blockbuffer
+ 0x04),
921 (APTR
)((char *)volume
->blockbuffer
+ 0x04),
924 // copy partition table - [Overwrites Floppy boot code]
925 D(bug("[install-i386] writeStage1: Copying MBR Partitions to %x\n", (char *)volume
->blockbuffer
+ MBR_PARTSTART
));
928 (APTR
)((char *)s2vol
->blockbuffer
+ MBR_PARTSTART
),
929 (APTR
)((char *)volume
->blockbuffer
+ MBR_PARTSTART
),
930 (MBR_PARTEND
- MBR_PARTSTART
)
932 // store the drive num stage2 is stored on
933 ((char *)volume
->blockbuffer
)[GRUB_BOOT_DRIVE
] = unit
+ BIOS_HDISK_FLAG
;
934 // Store the stage 2 pointer ..
935 ULONG
* stage2_sector_start
= (ULONG
*)((char *)volume
->blockbuffer
+ GRUB_STAGE2_SECTOR
);
936 D(bug("[install-i386] writeStage1: writing stage2 pointer @ %x\n", stage2_sector_start
));
937 stage2_sector_start
[0] = block
;
938 D(bug("[install-i386] writeStage1: stage2 pointer = %x\n", stage2_sector_start
[0]));
939 stage2_sector_start
[0] += s2vol
->startblock
;
940 D(bug("[install-i386] writeStage1: + offset [%d] = %x\n", s2vol
->startblock
, stage2_sector_start
[0]));
944 D(bug("[install-i386] writeStage1: Forcing LBA\n"));
945 ((char *)volume
->blockbuffer
)[GRUB_FORCE_LBA
] = 1;
949 D(bug("[install-i386] writeStage1: NOT Forcing LBA\n"));
950 ((char *)volume
->blockbuffer
)[GRUB_FORCE_LBA
] = 0;
955 D(bug("[install-i386] writeStage1: Install to FLOPPY\n"));
960 error
= readwriteBlock
961 (volume
, 0, volume
->blockbuffer
, 512, volume
->writecmd
);
963 printf("WriteError %ld\n", error
);
968 printf("WriteError %ld\n", error
);
971 printf("%s: Read Error\n", stage1path
);
975 PrintFault(IoErr(), stage1path
);
979 /* Flushes the cache on the volume containing the specified path. */
980 VOID
flushFS(CONST TEXT
*path
)
985 for (i
= 0; path
[i
] != ':'; i
++)
986 devname
[i
] = path
[i
];
989 if (Inhibit(devname
, DOSTRUE
))
990 Inhibit(devname
, DOSFALSE
);
993 BOOL installStageFiles
995 struct Volume
*s2vol
, /* stage2 volume */
996 STRPTR stagepath
, /* path to stage* files */
997 STRPTR kernelpath
, /* path to kernel image */
998 ULONG unit
, /* unit stage2 is on */
999 struct Volume
*s1vol
/* device on which stage1 will be stored */
1002 BOOL retval
= FALSE
;
1003 char stagename
[256];
1006 D(bug("[install-i386] installStageFiles(%x)\n", s1vol
));
1008 /* Flush GRUB and kernel volumes' caches */
1010 flushFS(kernelpath
);
1012 AddPart(stagename
, stagepath
, 256);
1013 AddPart(stagename
, "stage2", 256);
1014 block
= changeStage2(stagename
, kernelpath
, s2vol
, s1vol
->blockbuffer
);
1017 AddPart(stagename
, stagepath
, 256);
1018 AddPart(stagename
, "stage1", 256);
1019 if (writeStage1(stagename
, s1vol
, s2vol
, block
, unit
))
1025 int main(int argc
, char **argv
) {
1027 struct RDArgs
*rdargs
;
1028 struct Volume
*grubvol
;
1029 struct Volume
*bbvol
;
1030 struct FileSysStartupMsg
*fssm
;
1032 D(bug("[install-i386] main()\n"));
1034 rdargs
= ReadArgs(template, myargs
, NULL
);
1037 D(bug("[install-i386] FORCELBA = %d\n",myargs
[5]));
1039 fssm
= getDiskFSSM((STRPTR
)myargs
[3]);
1040 if ((fssm
) && (getDiskFSSM((STRPTR
)myargs
[4])))
1043 (strcmp(AROS_BSTR_ADDR(fssm
->fssm_Device
),(char*)myargs
[0])==0)
1044 // && (fssm->fssm_Unit == *((LONG *)myargs[1]))
1047 grubvol
= getGrubStageVolume
1049 AROS_BSTR_ADDR(fssm
->fssm_Device
),
1052 (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
)
1059 *((LONG
*)myargs
[1]),
1066 getBBVolume() read block 0
1067 if the partition directly contains a filesystem
1068 (currently only DOS\x is supported) we have
1069 to move block 0 to block 1 to make space for stage1
1072 (grubvol
->startblock
== bbvol
->startblock
) &&
1073 ((AROS_BE2LONG(bbvol
->blockbuffer
[0]) & 0xFFFFFF00)==0x444F5300)
1076 grubvol
->flags
&= ~VF_IS_RDB
;
1077 retval
= readwriteBlock
1078 (bbvol
, 0, bbvol
->blockbuffer
, 512, bbvol
->readcmd
);
1085 (STRPTR
)myargs
[3], /* grub path (stage1/2) */
1086 (STRPTR
)myargs
[4], /* kernel path */
1092 printf("Read Error: %ld\n", retval
);
1093 uninitVolume(bbvol
);
1095 uninitVolume(grubvol
);
1102 "%s is not on device %s unit %ld\n",
1103 (STRPTR
)myargs
[3], (STRPTR
)myargs
[0], *((LONG
*)myargs
[1])
1109 printf("kernel path must begin with a device name\n");
1113 PrintFault(IoErr(), argv
[0]);