Subversion Repositories SvarDOS

Rev

Rev 1943 | Rev 1946 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1943 Rev 1944
Line 538... Line 538...
538
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
538
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
539
  return(res);
539
  return(res);
540
}
540
}
541
 
541
 
542
 
542
 
543
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
-
 
544
static unsigned char get_cur_drive(void);
-
 
545
#pragma aux get_cur_drive = \
-
 
546
"mov ah, 0x19" /* DOS 1+ GET CURRENT DEFAULT DRIVE */ \
-
 
547
"int 0x21" \
-
 
548
modify [ah] \
-
 
549
value [al]
-
 
550
 
-
 
551
 
-
 
552
/* replace all occurences of char a by char b in s */
543
/* replace all occurences of char a by char b in s */
553
static void strtr(char *s, char a, char b) {
544
static void strtr(char *s, char a, char b) {
554
  for (;*s != 0; s++) {
545
  for (;*s != 0; s++) {
555
    if (*s == a) *s = b;
546
    if (*s == a) *s = b;
556
  }
547
  }
Line 601... Line 592...
601
  }
592
  }
602
  return(result);
593
  return(result);
603
}
594
}
604
 
595
 
605
 
596
 
-
 
597
#define MBR_WRITE 3
-
 
598
#define MBR_READ 2
606
/* read MBR of driveid (0x80, 0x81..) into buff */
599
/* read (action=2) or write (action=3) MBR of driveid (0x80, 0x81..) into buff */
607
static int READMBR(char *buff, unsigned char driveid);
600
static int READ_OR_WRITE_MBR(unsigned char action, char *buff, unsigned char driveid);
608
#pragma aux READMBR = \
601
#pragma aux READ_OR_WRITE_MBR = \
609
"push es" \
602
"push es" \
610
"mov ax, 0x0201"  /* read 1 sector into memory */ \
603
"mov al, 1"       /* read 1 sector into memory */ \
611
"mov cx, 0x0001"  /* cylinder 0, sector 1 */ \
604
"mov cx, 0x0001"  /* cylinder 0, sector 1 */ \
612
"xor dh, dh"      /* head 0 */ \
605
"xor dh, dh"      /* head 0 */ \
613
"push ds" \
606
"push ds" \
614
"pop es" \
607
"pop es" \
615
"int 0x13" \
608
"int 0x13" \
616
"mov ax, 0" /* do not do "xor ax, ax", CF needs to be preserved */ \
609
"mov ax, 0" /* do not do "xor ax, ax", CF needs to be preserved */ \
617
"jnc DONE" \
610
"jnc DONE" \
618
"inc ax" \
611
"inc ax" \
619
"DONE:" \
612
"DONE:" \
620
"pop es" \
613
"pop es" \
621
parm [bx] [dl] \
614
parm [ah] [bx] [dl] \
622
modify [cx dx] \
615
modify [cx dx] \
623
value [ax]
616
value [ax]
624
 
617
 
625
 
618
 
-
 
619
 
626
/*
620
/*
627
 * MBR structure:
621
 * MBR structure:
628
 *
622
 *
629
 * Boot signature (word 0xAA55) is at 0x01FE
623
 * Boot signature (word 0xAA55) is at 0x01FE
630
 *
624
 *
Line 650... Line 644...
650
 
644
 
651
struct drivelist {
645
struct drivelist {
652
  unsigned long start_lba;
646
  unsigned long start_lba;
653
  unsigned long tot_sect;  /* size (of partition), in sectors */
647
  unsigned long tot_sect;  /* size (of partition), in sectors */
654
  unsigned short tot_size; /* size in MiB */
648
  unsigned short tot_size; /* size in MiB */
655
  unsigned char active;
-
 
656
  unsigned char partid;    /* position of the partition in the MBR (0,1,2,3) */
649
  unsigned char partid;    /* position of the partition in the MBR (0,1,2,3) */
657
  unsigned char hd;        /* 0x80, 0x81... */
650
  unsigned char hd;        /* 0-3 */
658
  unsigned char dosid;     /* DOS drive id (A=1, B=2...)*/
651
  unsigned char dosid;     /* DOS drive id (A=0, B=1...)*/
659
};
652
};
660
 
653
 
661
 
654
 
662
/* a (very partial) struct mimicking what EDR-DOS uses in int 2Fh,AX=0803h */
655
/* a (very partial) struct mimicking what EDR-DOS uses in int 2Fh,AX=0803h */
663
#pragma pack (push)
656
#pragma pack (push)
664
#pragma pack (0) /* disable the automatic alignment of struct members */
657
#pragma pack (0) /* disable the automatic alignment of struct members */
665
struct dos_udsc {
658
struct dos_udsc {
666
  unsigned short next_off;   /* offset FFFFh if last */
659
  unsigned short next_off; /* offset FFFFh if last */
667
  unsigned short next_seg;
660
  unsigned short next_seg;
668
  unsigned char hd;     /* physical unit, as used by int 13h */
661
  unsigned char hd;        /* physical unit (as in int 13h) */
669
  unsigned char letter; /* DOS letter drive (A=0, B=1, C=2, ...) */
662
  unsigned char letter;    /* DOS letter drive (A=0, B=1, C=2, ...) */
670
  unsigned short sectsize; /* bytes per sector */
663
  unsigned short sectsize; /* bytes per sector */
671
  unsigned char unknown[15];
664
  unsigned char unknown[15];
672
  unsigned long start_lba; /* LBA address of the partition (only for primary partitions) */
665
  unsigned long start_lba; /* LBA address of the partition (only for primary partitions) */
673
};
666
};
674
#pragma pack (pop)
667
#pragma pack (pop)
Line 705... Line 698...
705
  struct dos_udsc far *udsc_root = get_dos_udsc();
698
  struct dos_udsc far *udsc_root = get_dos_udsc();
706
  struct dos_udsc far *udsc_node;
699
  struct dos_udsc far *udsc_node;
707
 
700
 
708
  for (drv = 0x80; drv < 0x84; drv++) {
701
  for (drv = 0x80; drv < 0x84; drv++) {
709
 
702
 
710
    if (READMBR(buff, drv) != 0) continue;
703
    if (READ_OR_WRITE_MBR(MBR_READ, buff, drv) != 0) continue;
711
 
704
 
712
    /* check boot signature at 0x01fe */
705
    /* check boot signature at 0x01fe */
713
    if (*(unsigned short *)(buff + 0x01fe) != 0xAA55) continue;
706
    if (*(unsigned short *)(buff + 0x01fe) != 0xAA55) continue;
714
 
707
 
715
    /* iterate over the 4 partitions in the MBR */
708
    /* iterate over the 4 partitions in the MBR */
Line 722... Line 715...
722
      if ((entry[4] != 0x0E) && (entry[4] != 0x0C)  /* LBA FAT */
715
      if ((entry[4] != 0x0E) && (entry[4] != 0x0C)  /* LBA FAT */
723
       && (entry[4] != 0x01) && (entry[4] != 0x06) && (entry[4] != 0x08)) { /* CHS FAT */
716
       && (entry[4] != 0x01) && (entry[4] != 0x06) && (entry[4] != 0x08)) { /* CHS FAT */
724
        continue;
717
        continue;
725
      }
718
      }
726
      bzero(&(drives[listlen]), sizeof(struct drivelist));
719
      bzero(&(drives[listlen]), sizeof(struct drivelist));
727
      drives[listlen].hd = drv;
720
      drives[listlen].hd = drv & 3;
728
      drives[listlen].partid = i;
721
      drives[listlen].partid = i;
729
      drives[listlen].active = entry[0] >> 7;
-
 
730
      drives[listlen].start_lba = ((unsigned long *)entry)[2];
722
      drives[listlen].start_lba = ((unsigned long *)entry)[2];
731
      drives[listlen].tot_sect = ((unsigned long *)entry)[3];
723
      drives[listlen].tot_sect = ((unsigned long *)entry)[3];
732
 
724
 
733
      /* now iterate over DOS drives and try to match ont to this MBR entry */
725
      /* now iterate over DOS drives and try to match ont to this MBR entry */
734
      udsc_node = udsc_root;
726
      udsc_node = udsc_root;
735
      while (udsc_node != NULL) {
727
      while (udsc_node != NULL) {
736
        if (udsc_node->hd != drv) goto NEXT;
728
        if (udsc_node->hd != drv) goto NEXT;
737
        if (udsc_node->start_lba != drives[listlen].start_lba) goto NEXT;
729
        if (udsc_node->start_lba != drives[listlen].start_lba) goto NEXT;
738
 
730
 
739
        /* FOUND! */
731
        /* FOUND! */
740
        drives[listlen].dosid = udsc_node->letter + 1;
732
        drives[listlen].dosid = udsc_node->letter;
741
        {
733
        {
742
          unsigned long sz = (drives[listlen].tot_sect * udsc_node->sectsize) >> 20;
734
          unsigned long sz = (drives[listlen].tot_sect * udsc_node->sectsize) >> 20;
743
          drives[listlen].tot_size = (unsigned short)sz;
735
          drives[listlen].tot_size = (unsigned short)sz;
744
        }
736
        }
745
        listlen++;
737
        listlen++;
Line 755... Line 747...
755
  return(listlen);
747
  return(listlen);
756
}
748
}
757
 
749
 
758
 
750
 
759
/* displays a list of drives and asks user to choose one for installation
751
/* displays a list of drives and asks user to choose one for installation
760
 * returns a word with DOS drive value in lowest 8 bits (A=1, B=2, etc) and
752
 * returns a word with bits HHPPLLLLLLLL where:
-
 
753
 * HH = hard drive id (0..3)
-
 
754
 * PP = position of the partition in MBR (0..3)
761
 * the BIOS drive id in highest 8 bits (1, 2...) */
755
 * LL... = drive's DOS id (A=0, B=1, C=2, ...) */
762
static int selectdrive(void) {
756
static int selectdrive(void) {
763
  char buff[512];
757
  char buff[512];
764
  struct drivelist drives[16];
758
  struct drivelist drives[16];
765
  char drvlist[16][32]; /* up to 16 drives (4 partitions on 4 disks) */
759
  char drvlist[16][32]; /* up to 16 drives (4 partitions on 4 disks) */
766
  int i, drvlistlen;
760
  int i, drvlistlen;
Line 807... Line 801...
807
    return(MENUQUIT);
801
    return(MENUQUIT);
808
  }
802
  }
809
 
803
 
810
  /* build a menu with all drives */
804
  /* build a menu with all drives */
811
  for (i = 0; i < drvlistlen; i++) {
805
  for (i = 0; i < drvlistlen; i++) {
812
    snprintf(drvlist[i], sizeof(drvlist[0]), "%c: [%u MiB, hd%c%u, act=%u]", '@' + drives[i].dosid, drives[i].tot_size, 'a' + (drives[i].hd & 127), drives[i].partid, drives[i].active);
806
    snprintf(drvlist[i], sizeof(drvlist[0]), "%c: [%u MiB, hd%c%u]", 'A' + drives[i].dosid, drives[i].tot_size, 'a' + drives[i].hd, drives[i].partid);
813
    menulist[i] = drvlist[i];
807
    menulist[i] = drvlist[i];
814
  }
808
  }
815
  menulist[i++] = svarlang_str(0, 2); /* Quit to DOS */
809
  menulist[i++] = svarlang_str(0, 2); /* Quit to DOS */
816
  menulist[i] = NULL;
810
  menulist[i] = NULL;
817
 
811
 
818
  newscreen(0);
812
  newscreen(0);
819
  i = menuselect(6 /*ypos*/, i /*height*/, menulist, -1);
813
  i = menuselect(6 /*ypos*/, i /*height*/, menulist, -1);
820
  if (i < 0) {
814
  if (i < 0) {
821
    return(MENUPREV);
815
    return(MENUPREV);
822
  } else if (i < drvlistlen) {
816
  } else if (i < drvlistlen) {
-
 
817
    /* return a bitfield HHPPLLLLLLLL
-
 
818
     * HH = hard drive id (0..3)
-
 
819
     * PP = position of the partition in MBR (0..3)
-
 
820
     * LL... = drive's DOS id (A=0, B=1, C=2, ...) */
823
    return(((drives[i].hd & 127) << 8) | drives[i].dosid);
821
    return((drives[i].partid << 8) | (drives[i].hd << 10) | drives[i].dosid);
824
  }
822
  }
825
 
823
 
826
  return(MENUQUIT);
824
  return(MENUQUIT);
827
}
825
}
828
 
826
 
829
 
-
 
-
 
827
/* hd_drv is a bitfield HHPPLLLLLLLL
-
 
828
 * HH = hard drive id (0..3)
-
 
829
 * PP = position of the partition in MBR (0..3)
-
 
830
 * LL... = drive's DOS id (A=0, B=1, C=2, ...) */
830
static int preparedrive(int hd_drv) {
831
static int preparedrive(int hd_drv) {
831
  unsigned char selecteddrive;
832
  unsigned char selecteddrive;
832
  unsigned char driveid;
833
  unsigned char driveid, partid;
833
  char cselecteddrive;
834
  char cselecteddrive;
834
  int choice;
835
  int choice;
835
  char buff[512];
836
  char buff[512];
836
 
837
 
837
  /* decode hd and drive id from hd_drv */
838
  /* decode hd and drive id from hd_drv */
838
  selecteddrive = hd_drv & 0xff;
839
  selecteddrive = hd_drv & 0xff; /* DOS drive letter (A=0. B=1, C=2 etc) */
-
 
840
  partid = (hd_drv >> 8) & 3;    /* position of partition in MBR (0..3) */
839
  driveid = hd_drv >> 8;
841
  driveid = (hd_drv >> 10);      /* HDD identifier (0..3) */
840
 
842
 
841
  cselecteddrive = '@' + selecteddrive;
843
  cselecteddrive = 'A' + selecteddrive;
842
 
844
 
843
  TRY_AGAIN:
845
  TRY_AGAIN:
844
 
846
 
845
  /* if not formatted, propose to format it right away (try to create a directory) */
847
  /* if not formatted, propose to format it right away (try to create a directory) */
846
  if (test_drive_write(cselecteddrive) != 0) {
848
  if (test_drive_write(cselecteddrive) != 0) {
Line 863... Line 865...
863
    exec(buff);
865
    exec(buff);
864
    goto TRY_AGAIN;
866
    goto TRY_AGAIN;
865
  }
867
  }
866
 
868
 
867
  /* check total disk space */
869
  /* check total disk space */
868
  if (disksize(selecteddrive) < SVARDOS_DISK_REQ) {
870
  if (disksize(selecteddrive+1) < SVARDOS_DISK_REQ) {
869
    int y = 9;
871
    int y = 9;
870
    newscreen(2);
872
    newscreen(2);
871
    snprintf(buff, sizeof(buff), svarlang_strid(0x0304), cselecteddrive, SVARDOS_DISK_REQ); /* "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB." */
873
    snprintf(buff, sizeof(buff), svarlang_strid(0x0304), cselecteddrive, SVARDOS_DISK_REQ); /* "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB." */
872
    y += putstringwrap(y, 1, COLOR_BODY, buff);
874
    y += putstringwrap(y, 1, COLOR_BODY, buff);
873
    putstringnls(++y, 1, COLOR_BODY, 0, 5); /* "Press any key..." */
875
    putstringnls(++y, 1, COLOR_BODY, 0, 5); /* "Press any key..." */
Line 905... Line 907...
905
    snprintf(buff, sizeof(buff), svarlang_strid(0x0306), cselecteddrive); /* "The installation of SvarDOS to %c: is about to begin." */
907
    snprintf(buff, sizeof(buff), svarlang_strid(0x0306), cselecteddrive); /* "The installation of SvarDOS to %c: is about to begin." */
906
    mdr_cout_str(7, 40 - (strlen(buff) / 2), buff, COLOR_BODY, 80);
908
    mdr_cout_str(7, 40 - (strlen(buff) / 2), buff, COLOR_BODY, 80);
907
    choice = menuselect(10, 2, list, -1);
909
    choice = menuselect(10, 2, list, -1);
908
    if (choice < 0) return(MENUPREV);
910
    if (choice < 0) return(MENUPREV);
909
    if (choice == 1) return(MENUQUIT);
911
    if (choice == 1) return(MENUQUIT);
-
 
912
 
-
 
913
    /* update the disk's MBR, transfer the boot system, make sure the partition
-
 
914
     * is ACTIVE and create a TEMP directory to copy SVP files over */
910
    snprintf(buff, sizeof(buff), "SYS %c: > NUL", cselecteddrive);
915
    snprintf(buff, sizeof(buff), "SYS %c: > NUL", cselecteddrive);
911
    exec(buff);
916
    exec(buff);
912
    sprintf(buff, "FDISK /MBR %d", driveid);
917
    sprintf(buff, "FDISK /MBR %u", driveid + 1);
913
    exec(buff);
918
    exec(buff);
-
 
919
 
-
 
920
    if (READ_OR_WRITE_MBR(MBR_READ, buff, driveid | 0x80) == 0) {
-
 
921
      /* active flags for part 0,1,2,3 are at offsets 0x01BE, 0x01CE, 0x01DE, 0x01EE */
-
 
922
      unsigned char i, flag_before, changed = 0;
-
 
923
      unsigned short memoffset = 0x01BE; /* first partition flag is here */
-
 
924
      for (i = 0; i < 4; i++) {
-
 
925
        flag_before = buff[memoffset];
-
 
926
        buff[memoffset] &= 127;
-
 
927
        if (i == partid) buff[memoffset] |= 0x80;
914
    snprintf(buff, sizeof(buff), "%c:\\SVARDOS", cselecteddrive);
928
        if (flag_before != buff[memoffset]) changed++;
-
 
929
        memoffset += 16; /* jump to next partition entry */
915
    mkdir(buff);
930
      }
-
 
931
      /* do I need to update the MBR? */
-
 
932
      if (changed != 0) READ_OR_WRITE_MBR(MBR_WRITE, buff, driveid | 0x80);
-
 
933
    }
-
 
934
 
916
    snprintf(buff + 3, sizeof(buff), "TEMP");
935
    snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
917
    mkdir(buff);
936
    mkdir(buff);
918
    return(0);
937
    return(0);
919
  }
938
  }
920
}
939
}
921
 
940
 
Line 1343... Line 1362...
1343
  if (targetdrv == MENUPREV) goto WelcomeScreen;
1362
  if (targetdrv == MENUPREV) goto WelcomeScreen;
1344
 
1363
 
1345
  action = preparedrive(targetdrv); /* what drive should we install to? check avail. space */
1364
  action = preparedrive(targetdrv); /* what drive should we install to? check avail. space */
1346
  if (action == MENUQUIT) goto QUIT;
1365
  if (action == MENUQUIT) goto QUIT;
1347
  if (action == MENUPREV) goto SelDriveScreen;
1366
  if (action == MENUPREV) goto SelDriveScreen;
1348
  targetdrv = (targetdrv & 0xff) + '@'; /* convert the hd+drv into a DOS letter */
1367
  targetdrv = (targetdrv & 0xff) + 'A'; /* convert the part+hd+drv value to a DOS letter */
1349
 
1368
 
1350
  /* copy packages to dst drive */
1369
  /* copy packages to dst drive */
1351
  if (copypackages(targetdrv, locales) != 0) goto QUIT;
1370
  if (copypackages(targetdrv, locales) != 0) goto QUIT;
1352
  finalreboot(); /* remove the install medium and reboot */
1371
  finalreboot(); /* remove the install medium and reboot */
1353
 
1372