Some fix for scrolling with lasso.
[tangerine.git] / workbench / c / install-i386-pc.c
bloba2d946d9fc29703f35e18c9ef06ab303bfa07f73
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <stdio.h>
7 #include <string.h>
8 #include <proto/dos.h>
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>
14 #include <dos/dos.h>
15 #include <exec/errors.h>
16 #include <exec/memory.h>
17 #include <libraries/partition.h>
19 #define DEBUG 0
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 */
32 /* BIOS drive flag */
33 #define BIOS_HDISK_FLAG 0x80
35 struct Volume {
36 struct MsgPort *mp;
37 struct IOExtTD *iotd;
38 ULONG readcmd;
39 ULONG writecmd;
40 ULONG startblock;
41 ULONG countblock;
42 ULONG unitnum;
43 UWORD SizeBlock;
44 UBYTE flags;
45 BYTE partnum;
46 ULONG *blockbuffer;
49 #define VF_IS_TRACKDISK (1<<0)
50 #define VF_IS_RDB (1<<1)
52 struct BlockNode {
53 ULONG sector;
54 UWORD count;
55 UWORD seg_adr;
58 #warning "TODO: Rename FORCELBA to USELBA and add a FORCE switch that causes install to not check for existing bootloader"
59 char *template =
60 "DEVICE/A,"
61 "UNIT/N/K/A,"
62 "PARTITIONNUMBER=PN/K/N,"
63 "GRUB/K/A,"
64 "KERNEL/K/A,"
65 "FORCELBA/S";
66 IPTR myargs[7] = {0,0,0,0,0,0};
68 struct FileSysStartupMsg *getDiskFSSM(STRPTR path) {
69 struct DosList *dl;
70 struct DeviceNode *dn;
71 char dname[32];
72 UBYTE i;
74 D(bug("[install-i386] getDiskFSSM('%s')\n", path));
76 for (i=0;(path[i]) && (path[i]!=':');i++)
77 dname[i] = path[i];
78 if (path[i] == ':')
80 dname[i] = 0;
81 dl = LockDosList(LDF_READ);
82 if (dl)
84 dn = (struct DeviceNode *)FindDosEntry(dl, dname, LDF_DEVICES);
85 UnLockDosList(LDF_READ);
86 if (dn)
88 if (IsFileSystem(dname))
90 return (struct FileSysStartupMsg *)BADDR(dn->dn_Startup);
92 else
93 printf("device '%s' doesn't contain a file system\n", dname);
95 else
96 PrintFault(ERROR_OBJECT_NOT_FOUND, dname);
99 else
100 printf("'%s' doesn't contain a device name\n",path);
101 return 0;
104 void fillGeometry(struct Volume *volume, struct DosEnvec *de) {
105 ULONG spc;
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;
117 UWORD *cmdcheck;
119 D(bug("[install-i386] nsdCheck(%x)\n", volume));
121 if (
123 (volume->startblock+volume->countblock)* /* last block */
124 ((volume->SizeBlock<<2)/512) /* 1 portion (block) equals 512 (bytes) */
125 )>8388608)
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");
136 else
138 if (
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");
146 else
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;
157 if (
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;
170 LONG error=0;
172 D(bug("[install-i386] initVolume(%s:%d)\n", device, unit));
174 volume = AllocVec(sizeof(struct Volume), MEMF_PUBLIC | MEMF_CLEAR);
175 if (volume)
177 volume->mp = CreateMsgPort();
178 if (volume->mp)
180 volume->iotd = (struct IOExtTD *)CreateIORequest(volume->mp, sizeof(struct IOExtTD));
181 if (volume->iotd)
183 volume->blockbuffer = AllocVec(de->de_SizeBlock<<2, MEMF_PUBLIC | MEMF_CLEAR);
184 if (volume->blockbuffer)
186 if (
187 OpenDevice
189 device,
190 unit,
191 (struct IORequest *)volume->iotd,
192 flags
193 ) == 0
196 if (strcmp(device, "trackdisk.device")==0)
197 volume->flags |= VF_IS_TRACKDISK;
198 else
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);
204 nsdCheck(volume);
205 return volume;
207 else
208 error = ERROR_NO_FREE_STORE;
209 FreeVec(volume->blockbuffer);
211 else
212 error = ERROR_NO_FREE_STORE;
213 DeleteIORequest((struct IORequest *)volume->iotd);
215 else
216 error = ERROR_NO_FREE_STORE;
217 DeleteMsgPort(volume->mp);
219 else
220 error = ERROR_NO_FREE_STORE;
221 FreeVec(volume);
223 else
224 error = ERROR_NO_FREE_STORE;
225 PrintFault(error, NULL);
226 return 0;
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);
238 FreeVec(volume);
241 ULONG readwriteBlock
243 struct Volume *volume,
244 ULONG block, APTR buffer, ULONG length,
245 ULONG command
248 UQUAD offset;
249 ULONG retval=0;
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);
266 return retval;
269 BOOL isvalidFileSystem(struct Volume *volume, STRPTR device, ULONG unit) {
270 BOOL retval = FALSE;
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");
279 return FALSE;
281 if (
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");
291 return FALSE;
293 if (
294 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)!=0x444F5300) ||
295 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFF) == 0)
297 return FALSE;
299 volume->partnum = -1;
300 PartitionBase = (struct PartitionBase *)OpenLibrary("partition.library", 1);
301 if (PartitionBase)
303 ph = OpenRootPartition(device, unit);
304 if (ph)
306 if (OpenPartitionTable(ph) == 0)
308 struct TagItem tags[2];
309 ULONG type;
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;
318 struct DosEnvec de;
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)
325 ULONG scp;
327 GetPartitionAttrs(pn, tags);
328 scp = de.de_Surfaces*de.de_BlocksPerTrack;
329 if (
330 (volume->startblock>=(de.de_LowCyl*scp)) &&
331 (volume->startblock<=(((de.de_HighCyl+1)*scp)-1))
333 break;
334 pn = (struct PartitionHandle *)pn->ln.ln_Succ;
336 if (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;
342 retval = TRUE;
345 else
347 if (type == PHPTT_RDB)
349 /* just use whole hard disk */
350 retval = TRUE;
352 else
353 printf("only MBR and RDB partition tables are supported\n");
355 ClosePartitionTable(ph);
357 else
359 /* just use whole hard disk */
360 retval = TRUE;
362 CloseRootPartition(ph);
364 else
365 printf("Error OpenRootPartition(%s,%ld)\n", device, unit);
366 CloseLibrary((struct Library *)PartitionBase);
368 else
369 printf("Couldn't open partition.library\n");
370 return retval;
373 struct Volume *getGrubStageVolume
375 STRPTR device,
376 ULONG unit,
377 ULONG flags,
378 struct DosEnvec *de
381 struct Volume *volume;
383 volume = initVolume(device, unit, flags, de);
385 D(bug("[install-i386] getGrubStageVolume(): volume=%x\n", volume));
387 if (volume)
389 if (isvalidFileSystem(volume, device, unit))
390 return volume;
391 else
393 printf("stage2 is on an unsupported file system\n");
394 PrintFault(ERROR_OBJECT_WRONG_TYPE, NULL);
396 uninitVolume(volume);
398 return 0;
401 BOOL isvalidPartition
403 STRPTR device,
404 ULONG unit,
405 LONG *pnum,
406 struct DosEnvec *de
409 struct PartitionBase *PartitionBase;
410 struct PartitionHandle *ph;
411 ULONG type;
412 BOOL retval=FALSE;
414 D(bug("[install-i386] isvalidPartition(%s:%d, part:%d)\n", device, unit, pnum));
416 PartitionBase = (struct PartitionBase *)OpenLibrary("partition.library", 1);
417 if (PartitionBase)
419 ph = OpenRootPartition(device, unit);
420 if (ph)
422 struct TagItem tags[2];
424 tags[1].ti_Tag = TAG_DONE;
425 /* is there a partition table? */
426 if (OpenPartitionTable(ph) == 0)
428 if (pnum)
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);
445 if (type == *pnum)
446 break;
447 pn = (struct PartitionHandle *)pn->ln.ln_Succ;
449 if (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);
462 retval = TRUE;
464 else
465 printf("partition is not of type AROS (0x30)\n");
467 else
469 printf
471 "partition %ld not found on device %s unit %ld\n",
472 *pnum, device, unit
476 else
477 printf("you can only install in partitions which are MBR partitioned\n");
479 else
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);
490 retval = TRUE;
492 else
493 printf("partition table type must be either MBR or RDB\n");
495 ClosePartitionTable(ph);
497 else
499 #warning "FIXME: GetPartitionAttr() should always work for root partition"
500 CopyMem(&ph->de, de, sizeof(struct DosEnvec));
501 retval = TRUE;
503 CloseRootPartition(ph);
505 else
506 printf("Error OpenRootPartition(%s,%ld)\n", device, unit);
507 CloseLibrary((struct Library *)PartitionBase);
509 else
510 printf("Couldn't open partition.library\n");
511 return retval;
514 struct Volume *getBBVolume(STRPTR device, ULONG unit, LONG *partnum) {
515 struct Volume *volume;
516 struct DosEnvec de;
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! */
528 return volume;
530 else
531 printf("no space for bootblock (RDB is on block 0)\n");
533 return NULL;
536 ULONG collectBlockList
538 struct Volume *volume,
539 ULONG block,
540 struct BlockNode *blocklist
543 ULONG retval, first_block;
544 WORD blk_count,count;
545 UWORD i;
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,
568 volume->readcmd
570 if (retval)
572 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld\n", retval));
573 printf("ReadError %ld\n", retval);
574 return 0;
577 i = volume->SizeBlock - 52;
578 first_block = AROS_BE2LONG(volume->blockbuffer[volume->SizeBlock-51]);
579 blk_count=0;
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,
589 volume->readcmd
591 if (retval)
593 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld)\n", retval));
594 printf("ReadError %ld\n", retval);
595 return 0;
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
605 if (
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));
614 else
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");
622 return 0;
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;
628 i--;
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));
633 } while (block);
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));
640 i = 0;
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));
649 return first_block;
652 void copyRootPath(char *dst, char *rpdos, BOOL isRDB) {
654 D(bug("[install-i386] copyRootPath()\n"));
656 if (isRDB)
658 /* we have an RDB so use devicename */
659 *dst++ = '/';
660 while ((*rpdos) && (*rpdos!=':'))
661 *dst++ = *rpdos++;
663 else
665 while ((*rpdos) && (*rpdos!=':'))
666 rpdos++;
668 rpdos++; /* skip colon */
669 *dst++ = '/';
670 /* append path */
671 while (*rpdos)
672 *dst++ = *rpdos++;
673 if (dst[-1] == '/')
674 dst[-1] = 0;
675 else
676 *dst = 0;
679 UBYTE *memstr(UBYTE *mem, UBYTE *str, LONG len) {
680 UBYTE *next;
681 UBYTE *search;
682 LONG left;
684 while (len)
686 len--;
687 if (*mem++ == *str)
689 next = mem;
690 search = str+1;
691 left = len;
692 while ((*search) && (left) && (*next++ == *search++))
693 left--;
694 if (*search == 0)
695 return mem-1;
698 return 0;
701 BOOL setUpMenu(BPTR fh, struct Volume *volume)
703 LONG length = 0;
704 LONG config_length = 0;
705 LONG read = 0;
706 UBYTE *buffer = NULL;
707 UBYTE *start = NULL;
708 UBYTE *stop = NULL;
709 UBYTE *position = NULL;
710 STRPTR line =
711 "timeout 0\n"
712 "default 0\n"
713 "\n"
714 "title AROS HD\n"
715 "root (hd%ld,%ld)\n"
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);
730 if (read < length)
732 printf("ERROR: Could not read entire file.\n");
733 goto error;
736 /* Find begin marker */
737 start = memstr(buffer, "# [B] (DO NOT REMOVE THIS LINE!)", length);
738 if (start == NULL)
740 printf("ERROR: Could not find start marker!?\n");
741 goto error;
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);
747 if (stop == NULL)
749 printf("ERROR: Could not find stop marker!?\n");
750 goto error;
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");
761 goto error;
764 /* Blank the rest */
765 for (position = start + config_length; position < stop; position++)
767 *position = '\n';
770 /* Write the new file out */
771 Seek(fh, 0, OFFSET_BEGINNING);
772 Write(fh, buffer, length);
774 FreeVec(buffer);
776 return TRUE;
778 error:
779 if (buffer != NULL) FreeVec(buffer);
781 return FALSE;
784 BOOL writeStage2
786 BPTR fh,
787 UBYTE *buffer,
788 STRPTR kernelpath,
789 struct Volume *volume
792 BOOL retval = FALSE;
793 UBYTE menupath[256];
794 char *menuname;
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 */
807 buffer[8] = 0xFF;
808 buffer[9] = 0xFF;
809 buffer[10] = volume->partnum;
810 buffer[11] = 0;
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);
822 retval = TRUE;
824 else
825 printf("%s: Write Error\n", menuname);
827 else
828 printf("%s: Seek Error\n", menuname);
830 else
831 printf("Read Error\n");
833 else
834 printf("Write Error\n");
836 else
837 PrintFault(IoErr(), NULL);
838 return retval;
841 ULONG changeStage2
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 */
849 ULONG block = 0;
850 struct FileInfoBlock fib;
851 BPTR fh;
853 D(bug("[install-i386] changeStage2(%x)\n", volume));
855 fh = Open(stage2path, MODE_OLDFILE);
856 if (fh)
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]);
869 if (block)
871 if (!writeStage2(fh, (UBYTE *)buffer, kernelpath, volume))
872 block = 0;
875 else
876 printf("%s: Read Error\n", stage2path);
878 else
879 PrintFault(IoErr(), stage2path);
880 Close(fh);
882 else
883 PrintFault(IoErr(), stage2path);
884 return block;
887 BOOL writeStage1
889 STRPTR stage1path,
890 struct Volume *volume,
891 struct Volume *s2vol,
892 ULONG block, /* first block of stage2 file */
893 ULONG unit
896 BOOL retval = FALSE;
897 LONG error = 0;
898 BPTR fh;
900 D(bug("[install-i386] writeStage1(%x)\n", volume));
902 fh = Open(stage1path, MODE_OLDFILE);
903 if (fh)
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"));
911 // read old MBR
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)
918 CopyMem
920 (APTR)((char *)s2vol->blockbuffer + 0x04),
921 (APTR)((char *)volume->blockbuffer + 0x04),
922 (MBR_BPBEND - 4)
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));
926 CopyMem
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]));
942 if (myargs[5]!=0)
944 D(bug("[install-i386] writeStage1: Forcing LBA\n"));
945 ((char *)volume->blockbuffer)[GRUB_FORCE_LBA] = 1;
947 else
949 D(bug("[install-i386] writeStage1: NOT Forcing LBA\n"));
950 ((char *)volume->blockbuffer)[GRUB_FORCE_LBA] = 0;
953 else
955 D(bug("[install-i386] writeStage1: Install to FLOPPY\n"));
958 if (error == 0)
960 error = readwriteBlock
961 (volume, 0, volume->blockbuffer, 512, volume->writecmd);
962 if (error)
963 printf("WriteError %ld\n", error);
964 else
965 retval = TRUE;
967 else
968 printf("WriteError %ld\n", error);
970 else
971 printf("%s: Read Error\n", stage1path);
972 Close(fh);
974 else
975 PrintFault(IoErr(), stage1path);
976 return retval;
979 /* Flushes the cache on the volume containing the specified path. */
980 VOID flushFS(CONST TEXT *path)
982 char devname[256];
983 UWORD i;
985 for (i = 0; path[i] != ':'; i++)
986 devname[i] = path[i];
987 devname[i++] = ':';
988 devname[i] = '\0';
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];
1004 ULONG block;
1006 D(bug("[install-i386] installStageFiles(%x)\n", s1vol));
1008 /* Flush GRUB and kernel volumes' caches */
1009 flushFS(stagepath);
1010 flushFS(kernelpath);
1012 AddPart(stagename, stagepath, 256);
1013 AddPart(stagename, "stage2", 256);
1014 block = changeStage2(stagename, kernelpath, s2vol, s1vol->blockbuffer);
1015 if (block)
1017 AddPart(stagename, stagepath, 256);
1018 AddPart(stagename, "stage1", 256);
1019 if (writeStage1(stagename, s1vol, s2vol, block, unit))
1020 retval = TRUE;
1022 return retval;
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);
1035 if (rdargs)
1037 D(bug("[install-i386] FORCELBA = %d\n",myargs[5]));
1039 fssm = getDiskFSSM((STRPTR)myargs[3]);
1040 if ((fssm) && (getDiskFSSM((STRPTR)myargs[4])))
1042 if (
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),
1050 fssm->fssm_Unit,
1051 fssm->fssm_Flags,
1052 (struct DosEnvec *)BADDR(fssm->fssm_Environ)
1054 if (grubvol)
1056 bbvol=getBBVolume
1058 (STRPTR)myargs[0],
1059 *((LONG *)myargs[1]),
1060 (LONG *)myargs[2]
1062 if (bbvol)
1064 ULONG retval=0;
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
1071 if (
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);
1080 if (retval == 0)
1082 installStageFiles
1084 grubvol,
1085 (STRPTR)myargs[3], /* grub path (stage1/2) */
1086 (STRPTR)myargs[4], /* kernel path */
1087 fssm->fssm_Unit,
1088 bbvol
1091 else
1092 printf("Read Error: %ld\n", retval);
1093 uninitVolume(bbvol);
1095 uninitVolume(grubvol);
1098 else
1100 printf
1102 "%s is not on device %s unit %ld\n",
1103 (STRPTR)myargs[3], (STRPTR)myargs[0], *((LONG *)myargs[1])
1107 else
1108 if (fssm)
1109 printf("kernel path must begin with a device name\n");
1110 FreeArgs(rdargs);
1112 else
1113 PrintFault(IoErr(), argv[0]);
1114 return 0;