New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / workbench / c / install-i386-pc.c
bloba03081d653333817d6a9bd41ca757bde618e317c
1 /*
2 Copyright © 1995-2006, 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 UWORD SizeBlock;
43 UBYTE flags;
44 BYTE partnum;
45 ULONG *blockbuffer;
48 #define VF_IS_TRACKDISK (1<<0)
49 #define VF_IS_RDB (1<<1)
51 struct BlockNode {
52 ULONG sector;
53 UWORD count;
54 UWORD seg_adr;
57 char *template =
58 "DEVICE/A,"
59 "UNIT/N/K/A,"
60 "PARTITIONNUMBER=PN/K/N,"
61 "GRUB/K/A,"
62 "KERNEL/K/A,"
63 "FORCELBA/S";
64 IPTR myargs[7] = {0,0,0,0,0,0};
66 struct FileSysStartupMsg *getDiskFSSM(STRPTR path) {
67 struct DosList *dl;
68 struct DeviceNode *dn;
69 char dname[32];
70 UBYTE i;
72 D(bug("[install-i386] getDiskFSSM('%s')\n", path));
74 for (i=0;(path[i]) && (path[i]!=':');i++)
75 dname[i] = path[i];
76 if (path[i] == ':')
78 dname[i] = 0;
79 dl = LockDosList(LDF_READ);
80 if (dl)
82 dn = (struct DeviceNode *)FindDosEntry(dl, dname, LDF_DEVICES);
83 UnLockDosList(LDF_READ);
84 if (dn)
86 if (IsFileSystem(dname))
88 return (struct FileSysStartupMsg *)BADDR(dn->dn_Startup);
90 else
91 printf("device '%s' doesn't contain a file system\n", dname);
93 else
94 PrintFault(ERROR_OBJECT_NOT_FOUND, dname);
97 else
98 printf("'%s' doesn't contain a device name\n",path);
99 return 0;
102 void nsdCheck(struct Volume *volume) {
103 struct NSDeviceQueryResult nsdq;
104 UWORD *cmdcheck;
106 D(bug("[install-i386] nsdCheck(%x)\n", volume));
108 if (
110 (volume->startblock+volume->countblock)* /* last block */
111 ((volume->SizeBlock<<2)/512) /* 1 portion (block) equals 512 (bytes) */
112 )>8388608)
114 nsdq.SizeAvailable=0;
115 nsdq.DevQueryFormat=0;
116 volume->iotd->iotd_Req.io_Command=NSCMD_DEVICEQUERY;
117 volume->iotd->iotd_Req.io_Data=&nsdq;
118 volume->iotd->iotd_Req.io_Length=sizeof(struct NSDeviceQueryResult);
119 if (DoIO((struct IORequest *)&volume->iotd->iotd_Req)==IOERR_NOCMD)
121 printf("Device doesn't understand NSD-Query\n");
123 else
125 if (
126 (volume->iotd->iotd_Req.io_Actual>sizeof(struct NSDeviceQueryResult)) ||
127 (volume->iotd->iotd_Req.io_Actual==0) ||
128 (volume->iotd->iotd_Req.io_Actual!=nsdq.SizeAvailable)
131 printf("WARNING wrong io_Actual using NSD\n");
133 else
135 if (nsdq.DeviceType != NSDEVTYPE_TRACKDISK)
136 printf("WARNING no trackdisk type\n");
137 for (cmdcheck=nsdq.SupportedCommands;*cmdcheck;cmdcheck++)
139 if (*cmdcheck == NSCMD_TD_READ64)
140 volume->readcmd = NSCMD_TD_READ64;
141 if (*cmdcheck == NSCMD_TD_WRITE64);
142 volume->writecmd = NSCMD_TD_WRITE64;
144 if (
145 (volume->readcmd!=NSCMD_TD_READ64) ||
146 (volume->writecmd!=NSCMD_TD_WRITE64)
148 printf("WARNING no READ64/WRITE64\n");
155 struct Volume *initVolume(STRPTR device, ULONG unit, ULONG flags, ULONG size) {
156 struct Volume *volume;
157 LONG error=0;
159 D(bug("[install-i386] initVolume(%s:%d)\n", device, unit));
161 volume = AllocVec(sizeof(struct Volume), MEMF_PUBLIC | MEMF_CLEAR);
162 if (volume)
164 volume->mp = CreateMsgPort();
165 if (volume->mp)
167 volume->iotd = (struct IOExtTD *)CreateIORequest(volume->mp, sizeof(struct IOExtTD));
168 if (volume->iotd)
170 volume->blockbuffer = AllocVec(size<<2, MEMF_PUBLIC | MEMF_CLEAR);
171 if (volume->blockbuffer)
173 if (
174 OpenDevice
176 device,
177 unit,
178 (struct IORequest *)volume->iotd,
179 flags
180 ) == 0
183 if (strcmp(device, "trackdisk.device")==0)
184 volume->flags |= VF_IS_TRACKDISK;
185 else
186 volume->flags |= VF_IS_RDB; /* just assume we have RDB */
187 volume->readcmd = CMD_READ;
188 volume->writecmd = CMD_WRITE;
189 nsdCheck(volume);
190 return volume;
192 else
193 error = ERROR_NO_FREE_STORE;
194 FreeVec(volume->blockbuffer);
196 else
197 error = ERROR_NO_FREE_STORE;
198 DeleteIORequest((struct IORequest *)volume->iotd);
200 else
201 error = ERROR_NO_FREE_STORE;
202 DeleteMsgPort(volume->mp);
204 else
205 error = ERROR_NO_FREE_STORE;
206 FreeVec(volume);
208 else
209 error = ERROR_NO_FREE_STORE;
210 PrintFault(error, NULL);
211 return 0;
214 void uninitVolume(struct Volume *volume)
217 D(bug("[install-i386] uninitVolume(%x)\n", volume));
219 CloseDevice((struct IORequest *)volume->iotd);
220 FreeVec(volume->blockbuffer);
221 DeleteIORequest((struct IORequest *)volume->iotd);
222 DeleteMsgPort(volume->mp);
223 FreeVec(volume);
226 ULONG readwriteBlock
228 struct Volume *volume,
229 ULONG block, APTR buffer, ULONG length,
230 ULONG command
233 UQUAD offset;
234 ULONG retval=0;
236 D(bug("[install-i386] readwriteBlock(vol:%x, block:%d, %d bytes)\n", volume, block, length));
238 volume->iotd->iotd_Req.io_Command = command;
239 volume->iotd->iotd_Req.io_Length = length;
240 volume->iotd->iotd_Req.io_Data = buffer;
241 offset = (UQUAD)(volume->startblock+block)*(volume->SizeBlock<<2);
242 volume->iotd->iotd_Req.io_Offset = offset & 0xFFFFFFFF;
243 volume->iotd->iotd_Req.io_Actual = offset>>32;
244 retval = DoIO((struct IORequest *)&volume->iotd->iotd_Req);
245 if (volume->flags & VF_IS_TRACKDISK)
247 volume->iotd->iotd_Req.io_Command = TD_MOTOR;
248 volume->iotd->iotd_Req.io_Length = 0;
249 DoIO((struct IORequest *)&volume->iotd->iotd_Req);
251 return retval;
254 BOOL isvalidFileSystem(struct Volume *volume, STRPTR device, ULONG unit) {
255 BOOL retval = FALSE;
256 struct PartitionBase *PartitionBase;
257 struct PartitionHandle *ph;
259 D(bug("[install-i386] isvalidFileSystem(%x, %s, %d)\n", volume, device, unit));
261 if (readwriteBlock(volume, 0, volume->blockbuffer, 512, volume->readcmd))
263 printf("Read Error\n");
264 return FALSE;
266 if (
267 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)!=0x444F5300) ||
268 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFF) == 0)
271 /* first block has no DOS\x so we don't have RDB for sure */
272 volume->flags &= ~VF_IS_RDB;
273 if (readwriteBlock(volume, 1, volume->blockbuffer, 512, volume->readcmd))
275 printf("Read Error\n");
276 return FALSE;
278 if (
279 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)!=0x444F5300) ||
280 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFF) == 0)
282 return FALSE;
284 volume->partnum = -1;
285 PartitionBase = (struct PartitionBase *)OpenLibrary("partition.library", 1);
286 if (PartitionBase)
288 ph = OpenRootPartition(device, unit);
289 if (ph)
291 if (OpenPartitionTable(ph) == 0)
293 struct TagItem tags[2];
294 ULONG type;
296 tags[1].ti_Tag = TAG_DONE;
297 tags[0].ti_Tag = PTT_TYPE;
298 tags[0].ti_Data = (STACKIPTR)&type;
299 GetPartitionTableAttrs(ph, tags);
300 if (type == PHPTT_MBR)
302 struct PartitionHandle *pn;
303 struct DosEnvec de;
305 tags[0].ti_Tag = PT_DOSENVEC;
306 tags[0].ti_Data = (STACKIPTR)&de;
307 pn = (struct PartitionHandle *)ph->table->list.lh_Head;
308 while (pn->ln.ln_Succ)
310 ULONG scp;
312 GetPartitionAttrs(pn, tags);
313 scp = de.de_Surfaces*de.de_BlocksPerTrack;
314 if (
315 (volume->startblock>=(de.de_LowCyl*scp)) &&
316 (volume->startblock<=(((de.de_HighCyl+1)*scp)-1))
318 break;
319 pn = (struct PartitionHandle *)pn->ln.ln_Succ;
321 if (pn->ln.ln_Succ)
323 tags[0].ti_Tag = PT_POSITION;
324 tags[0].ti_Data = (STACKIPTR)&type;
325 GetPartitionAttrs(pn, tags);
326 volume->partnum = (UBYTE)type;
327 retval = TRUE;
330 else
332 if (type == PHPTT_RDB)
334 /* just use whole hard disk */
335 retval = TRUE;
337 else
338 printf("only MBR and RDB partition tables are supported\n");
340 ClosePartitionTable(ph);
342 else
344 /* just use whole hard disk */
345 retval = TRUE;
347 CloseRootPartition(ph);
349 else
350 printf("Error OpenRootPartition(%s,%ld)\n", device, unit);
351 CloseLibrary((struct Library *)PartitionBase);
353 else
354 printf("Couldn't open partition.library\n");
355 return retval;
358 void fillGeometry(struct Volume *volume, struct DosEnvec *de) {
359 ULONG spc;
361 D(bug("[install-i386] fillGeometry(%x)\n", volume));
363 spc = de->de_Surfaces*de->de_BlocksPerTrack;
364 volume->SizeBlock = de->de_SizeBlock;
365 volume->startblock = de->de_LowCyl*spc;
366 volume->countblock =((de->de_HighCyl-de->de_LowCyl+1)*spc)-1+de->de_Reserved;
369 struct Volume *getGrubStageVolume
371 STRPTR device,
372 ULONG unit,
373 ULONG flags,
374 struct DosEnvec *de
377 struct Volume *volume;
379 volume = initVolume(device, unit, flags, de->de_SizeBlock);
381 D(bug("[install-i386] getGrubStageVolume(): volume=%x\n", volume));
383 if (volume)
385 fillGeometry(volume, de);
386 if (isvalidFileSystem(volume, device, unit))
387 return volume;
388 else
390 printf("stage2 is on an unsupported file system\n");
391 PrintFault(ERROR_OBJECT_WRONG_TYPE, NULL);
393 uninitVolume(volume);
395 return 0;
398 BOOL isvalidPartition
400 STRPTR device,
401 ULONG unit,
402 LONG *pnum,
403 struct DosEnvec *de
406 struct PartitionBase *PartitionBase;
407 struct PartitionHandle *ph;
408 ULONG type;
409 BOOL retval=FALSE;
411 D(bug("[install-i386] isvalidPartition(%s:%d, part:%d)\n", device, unit, pnum));
413 PartitionBase = (struct PartitionBase *)OpenLibrary("partition.library", 1);
414 if (PartitionBase)
416 ph = OpenRootPartition(device, unit);
417 if (ph)
419 struct TagItem tags[2];
421 tags[1].ti_Tag = TAG_DONE;
422 /* is there a partition table? */
423 if (OpenPartitionTable(ph) == 0)
425 if (pnum)
427 /* install into partition bootblock */
428 tags[0].ti_Tag = PTT_TYPE;
429 tags[0].ti_Data = (STACKIPTR)&type;
430 GetPartitionTableAttrs(ph, tags);
431 if (type == PHPTT_MBR)
433 struct PartitionHandle *pn;
435 /* search for partition */
436 tags[0].ti_Tag = PT_POSITION;
437 tags[0].ti_Data = (STACKIPTR)&type;
438 pn = (struct PartitionHandle *)ph->table->list.lh_Head;
439 while (pn->ln.ln_Succ)
441 GetPartitionAttrs(pn, tags);
442 if (type == *pnum)
443 break;
444 pn = (struct PartitionHandle *)pn->ln.ln_Succ;
446 if (pn->ln.ln_Succ)
448 struct PartitionType ptype;
450 /* is it an AROS partition? */
451 tags[0].ti_Tag = PT_TYPE;
452 tags[0].ti_Data = (STACKIPTR)&ptype;
453 GetPartitionAttrs(pn, tags);
454 if (ptype.id[0] == 0x30)
456 tags[0].ti_Tag = PT_DOSENVEC;
457 tags[0].ti_Data = (STACKIPTR)de;
458 GetPartitionAttrs(pn, tags);
459 retval = TRUE;
461 else
462 printf("partition is not of type AROS (0x30)\n");
464 else
466 printf
468 "partition %ld not found on device %s unit %ld\n",
469 *pnum, device, unit
473 else
474 printf("you can only install in partitions which are MBR partitioned\n");
476 else
478 /* install into MBR */
479 tags[0].ti_Tag = PTT_TYPE;
480 tags[0].ti_Data = (STACKIPTR)&type;
481 GetPartitionTableAttrs(ph, tags);
482 if ((type == PHPTT_MBR) || (type == PHPTT_RDB))
484 tags[0].ti_Tag = PT_DOSENVEC;
485 tags[0].ti_Data = (STACKIPTR)de;
486 GetPartitionAttrs(ph, tags);
487 retval = TRUE;
489 else
490 printf("partition table type must be either MBR or RDB\n");
492 ClosePartitionTable(ph);
494 else
496 #warning "FIXME: GetPartitionAttr() should always work for root partition"
497 CopyMem(&ph->de, de, sizeof(struct DosEnvec));
498 retval = TRUE;
500 CloseRootPartition(ph);
502 else
503 printf("Error OpenRootPartition(%s,%ld)\n", device, unit);
504 CloseLibrary((struct Library *)PartitionBase);
506 else
507 printf("Couldn't open partition.library\n");
508 return retval;
511 struct Volume *getBBVolume(STRPTR device, ULONG unit, LONG *partnum) {
512 struct Volume *volume;
513 struct DosEnvec de;
515 D(bug("[install-i386] getBBVolume(%s:%d, %d)\n", device, unit, partnum));
517 if (isvalidPartition(device, unit, partnum, &de))
519 volume = initVolume(device, unit, 0, de.de_SizeBlock);
520 volume->partnum = partnum ? *partnum : -1;
521 fillGeometry(volume, &de);
522 readwriteBlock(volume, 0, volume->blockbuffer, 512, volume->readcmd);
523 if (AROS_BE2LONG(volume->blockbuffer[0]) != IDNAME_RIGIDDISK)
525 memset(volume->blockbuffer,0x00, 446); /* Clear the boot sector region! */
526 return volume;
528 else
529 printf("no space for bootblock (RDB is on block 0)\n");
531 return 0;
534 ULONG collectBlockList
536 struct Volume *volume,
537 ULONG block,
538 struct BlockNode *blocklist
541 ULONG retval, first_block;
542 WORD blk_count,count;
543 UWORD i;
545 D(bug("[install-i386] collectBlockList(%x, %d, %x)\n", volume, block, blocklist));
547 #warning "TODO: logical/physical blocks"
549 initialze stage2-blocklist
550 (it is NULL-terminated)
552 // for (blk_count=-1;blocklist[blk_count].sector!=0;blk_count--)
553 // blocklist[blk_count].sector = 0;
555 memset((char *)&blocklist[-20],0x00, 20*sizeof(struct BlockNode)); /* Clear the stage2 sector pointers region! */
556 D(bug("[install-i386] collectBlockList: Cleared sector list (20 entries) [start: %x, end %x]\n", &blocklist[-20], &blocklist[-1]));
559 the first block of stage2 will be stored in stage1
560 so skip the first filekey in the first loop
562 #warning "Block read twice"
563 retval=readwriteBlock
565 volume, block, volume->blockbuffer, volume->SizeBlock<<2,
566 volume->readcmd
568 if (retval)
570 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld\n", retval));
571 printf("ReadError %ld\n", retval);
572 return 0;
575 i = volume->SizeBlock - 52;
576 first_block = AROS_BE2LONG(volume->blockbuffer[volume->SizeBlock-51]);
577 blk_count=0;
579 D(bug("[install-i386] collectBlockList: First block @ %x, i:%d\n", first_block, i));
584 retval=readwriteBlock
586 volume, block, volume->blockbuffer, volume->SizeBlock<<2,
587 volume->readcmd
589 if (retval)
591 D(bug("[install-i386] collectBlockList: ERROR reading block (error: %ld)\n", retval));
592 printf("ReadError %ld\n", retval);
593 return 0;
595 D(bug("[install-i386] collectBlockList: read block %lx, i = %d\n", block, i));
596 while ((i>=6) && (volume->blockbuffer[i]))
598 D(bug("[install-i386] collectBlockList: i = %d\n", i));
600 if current sector follows right after last sector
601 then we don't need a new element
603 if (
604 (blocklist[blk_count].sector) &&
605 ((blocklist[blk_count].sector+blocklist[blk_count].count)==
606 AROS_BE2LONG(volume->blockbuffer[i]))
609 blocklist[blk_count].count += 1;
610 D(bug("[install-i386] collectBlockList: sector %d follows previous - increasing count of block %d to %d\n", i, blk_count, blocklist[blk_count].count));
612 else
614 blk_count--; /* decrement first */
615 D(bug("[install-i386] collectBlockList: store new block (%d)\n", blk_count));
616 if (blocklist[blk_count-1].sector != 0)
618 D(bug("[install-i386] collectBlockList: ERROR: out of block space at sector %d, block %d\n", i, blk_count));
619 printf("There is no more space to save blocklist in stage2\n");
620 return 0;
622 D(bug("[install-i386] collectBlockList: storing sector pointer for %d in block %d\n", i, blk_count));
623 blocklist[blk_count].sector = AROS_BE2LONG(volume->blockbuffer[i]);
624 blocklist[blk_count].count = 1;
626 i--;
628 i = volume->SizeBlock - 51;
629 block = AROS_BE2LONG(volume->blockbuffer[volume->SizeBlock - 2]);
630 D(bug("[install-i386] collectBlockList: next block %d, i = %d\n", block, i));
631 } while (block);
633 blocks in blocklist are relative to the first
634 sector of the HD (not partition)
636 D(bug("[install-i386] collectBlockList: successfully updated pointers for %d blocks\n", blk_count));
638 i = 0;
639 for (count=-1;count>=blk_count;count--)
641 blocklist[count].sector += volume->startblock;
642 blocklist[count].seg_adr = 0x820 + (i*32);
643 i += blocklist[count].count;
644 D(bug("[install-i386] collectBlockList: correcting block %d for partition start\n", count));
645 D(bug("[install-i386] collectBlockList: sector : %x seg_adr : %x\n", blocklist[count].sector, blocklist[count].seg_adr));
647 return first_block;
650 void copyRootPath(char *dst, char *rpdos, BOOL isRDB) {
652 D(bug("[install-i386] copyRootPath()\n"));
654 if (isRDB)
656 /* we have an RDB so use devicename */
657 *dst++ = '/';
658 while ((*rpdos) && (*rpdos!=':'))
659 *dst++ = *rpdos++;
661 else
663 while ((*rpdos) && (*rpdos!=':'))
664 rpdos++;
666 rpdos++; /* skip colon */
667 *dst++ = '/';
668 /* append path */
669 while (*rpdos)
670 *dst++ = *rpdos++;
671 if (dst[-1] == '/')
672 dst[-1] = 0;
673 else
674 *dst = 0;
677 UBYTE *memstr(UBYTE *mem, UBYTE *str, LONG len) {
678 UBYTE *next;
679 UBYTE *search;
680 LONG left;
682 while (len)
684 len--;
685 if (*mem++ == *str)
687 next = mem;
688 search = str+1;
689 left = len;
690 while ((*search) && (left) && (*next++ == *search++))
691 left--;
692 if (*search == 0)
693 return mem-1;
696 return 0;
699 BOOL setupMenu(BPTR fh)
701 LONG length = 0;
702 LONG read = 0;
703 UBYTE *buffer = NULL;
704 UBYTE *start = NULL;
705 UBYTE *stop = NULL;
706 UBYTE *position = NULL;
707 STRPTR line =
708 "timeout 0\n"
709 "default 0\n"
710 "\n"
711 "title AROS HD\n"
712 "root (hd0,0)\n"
713 "configfile /dh0/boot/grub/menu.lst\n";
715 D(bug("[install-i386] setupMenu(%x)\n", fh));
717 /* Get the filesize and reset the position */
718 Seek(fh, 0, OFFSET_END);
719 length = Seek(fh, 0, OFFSET_BEGINNING);
721 /* Allocate memory for file data */
722 buffer = AllocVec(length, MEMF_ANY);
723 if (buffer == NULL) goto error;
725 /* Read in the entire file */
726 read = Read(fh, buffer, length);
727 if (read < length)
729 printf("ERROR: Could not read entire file.\n");
730 goto error;
733 /* Find begin marker */
734 start = memstr(buffer, "# [B] (DO NOT REMOVE THIS LINE!)", length);
735 if (start == NULL)
737 printf("ERROR: Could not find start marker!?\n");
738 goto error;
740 start += strlen("# [B] (DO NOT REMOVE THIS LINE!)") + 2;
742 /* Find end marker */
743 stop = memstr(buffer, "# [E] (DO NOT REMOVE THIS LINE!)", length);
744 if (stop == NULL)
746 printf("ERROR: Could not find stop marker!?\n");
747 goto error;
750 /* Check if there is enough space */
751 if ((stop - start) < strlen(line))
753 printf("ERROR: Not enough space to setup menu.\n");
754 goto error;
757 /* Write the new menu config */
758 strlcpy(start, line, stop - start - 1);
760 /* Blank the rest */
761 for (position = start + strlen(line); position < stop; position++)
763 *position = '\n';
766 /* Write the new file out */
767 Seek(fh, 0, OFFSET_BEGINNING);
768 Write(fh, buffer, length);
770 FreeVec(buffer);
772 return TRUE;
774 error:
775 if (buffer != NULL) FreeVec(buffer);
777 return FALSE;
780 BOOL writeStage2
782 BPTR fh,
783 UBYTE *buffer,
784 STRPTR kernelpath,
785 struct Volume *volume
788 BOOL retval = FALSE;
789 UBYTE menupath[256];
790 char *menuname;
792 D(bug("[install-i386] writeStage2(%x)\n", volume));
794 if (Seek(fh, 0, OFFSET_BEGINNING) != -1)
796 /* write back first block */
797 if (Write(fh, buffer, 512)==512)
799 /* read second stage2 block */
800 if (Read(fh, buffer, 512) == 512)
802 /* set partition number where stage2 is on */
803 buffer[8] = 0xFF;
804 buffer[9] = 0xFF;
805 buffer[10] = volume->partnum;
806 buffer[11] = 0;
807 /* get ptr to version string */
808 menuname = buffer+18;
809 while (*menuname++); /* skip version string */
810 copyRootPath(menuname, menupath, volume->flags & VF_IS_RDB);
811 strcat(menuname, "/menu.lst");
812 /* write second stage2 block back */
813 if (Seek(fh, -512, OFFSET_CURRENT) != -1)
815 if (Write(fh, buffer, 512) == 512)
817 setupMenu(fh);
818 retval = TRUE;
820 else
821 printf("%s: Write Error\n", menuname);
823 else
824 printf("%s: Seek Error\n", menuname);
826 else
827 printf("Read Error\n");
829 else
830 printf("Write Error\n");
832 else
833 PrintFault(IoErr(), NULL);
834 return retval;
837 ULONG changeStage2
839 STRPTR stage2path, /* path of stage2 file */
840 STRPTR kernelpath, /* path of the kernel image */
841 struct Volume *volume, /* volume stage2 is on */
842 ULONG *buffer /* a buffer of at least 512 bytes */
845 ULONG block = 0;
846 struct FileInfoBlock fib;
847 BPTR fh;
849 D(bug("[install-i386] changeStage2(%x)\n", volume));
851 fh = Open(stage2path, MODE_OLDFILE);
852 if (fh)
854 if (Examine(fh, &fib))
856 if (Read(fh, buffer, 512) == 512)
859 get and store all blocks of stage2 in first block of stage2
860 first block of stage2 will be returned
862 block = collectBlockList
863 (volume, fib.fib_DiskKey, (struct BlockNode *)&buffer[128]);
865 if (block)
867 if (!writeStage2(fh, (UBYTE *)buffer, kernelpath, volume))
868 block = 0;
871 else
872 printf("%s: Read Error\n", stage2path);
874 else
875 PrintFault(IoErr(), stage2path);
876 Close(fh);
878 else
879 PrintFault(IoErr(), stage2path);
880 return block;
883 BOOL writeStage1
885 STRPTR stage1path,
886 struct Volume *volume,
887 struct Volume *s2vol,
888 ULONG block, /* first block of stage2 file */
889 ULONG unit
892 BOOL retval = FALSE;
893 LONG error = 0;
894 BPTR fh;
896 D(bug("[install-i386] writeStage1(%x)\n", volume));
898 fh = Open(stage1path, MODE_OLDFILE);
899 if (fh)
901 if (Read(fh, volume->blockbuffer, 512) == 512)
903 /* install into MBR ? */
904 if ((volume->startblock == 0) && (!(volume->flags & VF_IS_TRACKDISK)))
906 D(bug("[install-i386] writeStage1: Install to HARDDISK\n"));
907 // read old MBR
908 error = readwriteBlock
909 (volume, 0, s2vol->blockbuffer, 512, volume->readcmd);
911 D(bug("[install-i386] writeStage1: MBR Buffer @ %x\n", volume->blockbuffer));
912 D(bug("[install-i386] writeStage1: Copying MBR BPB to %x\n", (char *)volume->blockbuffer + 0x04));
913 // copy BPB (BIOS Parameter Block)
914 CopyMem
916 (APTR)((char *)s2vol->blockbuffer + 0x04),
917 (APTR)((char *)volume->blockbuffer + 0x04),
918 (MBR_BPBEND - 4)
920 // copy partition table - [Overwrites Floppy boot code]
921 D(bug("[install-i386] writeStage1: Copying MBR Partitions to %x\n", (char *)volume->blockbuffer + MBR_PARTSTART));
922 CopyMem
924 (APTR)((char *)s2vol->blockbuffer + MBR_PARTSTART),
925 (APTR)((char *)volume->blockbuffer + MBR_PARTSTART),
926 (MBR_PARTEND - MBR_PARTSTART)
928 // store the drive num stage2 is stored on
929 ((char *)volume->blockbuffer)[GRUB_BOOT_DRIVE] = unit + BIOS_HDISK_FLAG;
930 // Store the stage 2 pointer ..
931 ULONG * stage2_sector_start = (ULONG *)((char *)volume->blockbuffer + GRUB_STAGE2_SECTOR);
932 D(bug("[install-i386] writeStage1: writing stage2 pointer @ %x\n", stage2_sector_start));
933 stage2_sector_start[0] = block;
934 D(bug("[install-i386] writeStage1: stage2 pointer = %x\n", stage2_sector_start[0]));
935 stage2_sector_start[0] += s2vol->startblock;
936 D(bug("[install-i386] writeStage1: + offset [%d] = %x\n", s2vol->startblock, stage2_sector_start[0]));
938 if (myargs[5]!=0)
940 D(bug("[install-i386] writeStage1: Forcing LBA\n"));
941 ((char *)volume->blockbuffer)[GRUB_FORCE_LBA] = 1;
943 else
945 D(bug("[install-i386] writeStage1: NOT Forcing LBA\n"));
946 ((char *)volume->blockbuffer)[GRUB_FORCE_LBA] = 0;
949 else
951 D(bug("[install-i386] writeStage1: Install to FLOPPY\n"));
954 if (error == 0)
956 error = readwriteBlock
957 (volume, 0, volume->blockbuffer, 512, volume->writecmd);
958 if (error)
959 printf("WriteError %ld\n", error);
960 else
961 retval = TRUE;
963 else
964 printf("WriteError %ld\n", error);
966 else
967 printf("%s: Read Error\n", stage1path);
968 Close(fh);
970 else
971 PrintFault(IoErr(), stage1path);
972 return retval;
975 /* Flushes the cache on the volume containing the specified path. */
976 VOID flushFS(CONST TEXT *path)
978 char devname[256];
979 UWORD i;
981 for (i = 0; path[i] != ':'; i++)
982 devname[i] = path[i];
983 devname[i++] = ':';
984 devname[i] = '\0';
985 if (Inhibit(devname, DOSTRUE))
986 Inhibit(devname, DOSFALSE);
989 BOOL installStageFiles
991 struct Volume *s2vol, /* stage2 volume */
992 STRPTR stagepath, /* path to stage* files */
993 STRPTR kernelpath, /* path to kernel image */
994 ULONG unit, /* unit stage2 is on */
995 struct Volume *s1vol /* device on which stage1 will be stored */
998 BOOL retval = FALSE;
999 char stagename[256];
1000 ULONG block;
1002 D(bug("[install-i386] installStageFiles(%x)\n", s1vol));
1004 /* Flush GRUB and kernel volumes' caches */
1005 flushFS(stagepath);
1006 flushFS(kernelpath);
1008 AddPart(stagename, stagepath, 256);
1009 AddPart(stagename, "stage2", 256);
1010 block = changeStage2(stagename, kernelpath, s2vol, s1vol->blockbuffer);
1011 if (block)
1013 AddPart(stagename, stagepath, 256);
1014 AddPart(stagename, "stage1", 256);
1015 if (writeStage1(stagename, s1vol, s2vol, block, unit))
1016 retval = TRUE;
1018 return retval;
1021 int main(int argc, char **argv) {
1023 struct RDArgs *rdargs;
1024 struct Volume *grubvol;
1025 struct Volume *bbvol;
1026 struct FileSysStartupMsg *fssm;
1028 D(bug("[install-i386] main()\n"));
1030 rdargs = ReadArgs(template, myargs, NULL);
1031 if (rdargs)
1033 D(bug("[install-i386] FORCELBA = %d\n",myargs[5]));
1035 fssm = getDiskFSSM((STRPTR)myargs[3]);
1036 if ((fssm) && (getDiskFSSM((STRPTR)myargs[4])))
1038 if (
1039 (strcmp(AROS_BSTR_ADDR(fssm->fssm_Device),(char*)myargs[0])==0)
1040 // && (fssm->fssm_Unit == *((LONG *)myargs[1]))
1043 grubvol = getGrubStageVolume
1045 AROS_BSTR_ADDR(fssm->fssm_Device),
1046 fssm->fssm_Unit,
1047 fssm->fssm_Flags,
1048 (struct DosEnvec *)BADDR(fssm->fssm_Environ)
1050 if (grubvol)
1052 bbvol=getBBVolume
1054 (STRPTR)myargs[0],
1055 *((LONG *)myargs[1]),
1056 (LONG *)myargs[2]
1058 if (bbvol)
1060 ULONG retval=0;
1062 getBBVolume() read block 0
1063 if the partition directly contains a filesystem
1064 (currently only DOS\x is supported) we have
1065 to move block 0 to block 1 to make space for stage1
1067 if (
1068 (grubvol->startblock == bbvol->startblock) &&
1069 ((AROS_BE2LONG(bbvol->blockbuffer[0]) & 0xFFFFFF00)==0x444F5300)
1072 grubvol->flags &= ~VF_IS_RDB;
1073 retval = readwriteBlock
1074 (bbvol, 0, bbvol->blockbuffer, 512, bbvol->readcmd);
1076 if (retval == 0)
1078 installStageFiles
1080 grubvol,
1081 (STRPTR)myargs[3], /* grub path (stage1/2) */
1082 (STRPTR)myargs[4], /* kernel path */
1083 fssm->fssm_Unit,
1084 bbvol
1087 else
1088 printf("Read Error: %ld\n", retval);
1089 uninitVolume(bbvol);
1091 uninitVolume(grubvol);
1094 else
1096 printf
1098 "%s is not on device %s unit %ld\n",
1099 (STRPTR)myargs[3], (STRPTR)myargs[0], *((LONG *)myargs[1])
1103 else
1104 if (fssm)
1105 printf("kernel path must begin with a device name\n");
1106 FreeArgs(rdargs);
1108 else
1109 PrintFault(IoErr(), argv[0]);
1110 return 0;