Subversion Repositories SvarDOS

Rev

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

Rev 1942 Rev 1943
Line 648... Line 648...
648
 * 0x0C  number of sectors in partition (4 bytes)
648
 * 0x0C  number of sectors in partition (4 bytes)
649
 */
649
 */
650
 
650
 
651
struct drivelist {
651
struct drivelist {
652
  unsigned long start_lba;
652
  unsigned long start_lba;
653
  unsigned long tot_sect; /* size (of partition), in sectors */
653
  unsigned long tot_sect;  /* size (of partition), in sectors */
654
  unsigned short tot_size; /* size in MiB */
654
  unsigned short tot_size; /* size in MiB */
655
  unsigned char active;
655
  unsigned char active;
-
 
656
  unsigned char partid;    /* position of the partition in the MBR (0,1,2,3) */
656
  unsigned char hd; /* 0x80, 0x81... */
657
  unsigned char hd;        /* 0x80, 0x81... */
657
  unsigned char dosid;   /* DOS drive id (A=1, B=2...)*/
658
  unsigned char dosid;     /* DOS drive id (A=1, B=2...)*/
658
};
659
};
659
 
660
 
660
 
661
 
661
/* a (very partial) struct mimicking what EDR-DOS uses in int 2Fh,AX=0803h */
662
/* a (very partial) struct mimicking what EDR-DOS uses in int 2Fh,AX=0803h */
662
#pragma pack (push)
663
#pragma pack (push)
Line 693... Line 694...
693
  return(MK_FP(udsc_seg, udsc_off));
694
  return(MK_FP(udsc_seg, udsc_off));
694
}
695
}
695
 
696
 
696
 
697
 
697
/* reads the MBR and matches its entries to DOS drives
698
/* reads the MBR and matches its entries to DOS drives
-
 
699
 * fills the drives array with up to 16 drives (4 partitions * 4 disks)
698
 * see https://github.com/SvarDOS/bugz/issues/89 */
700
 * see https://github.com/SvarDOS/bugz/issues/89 */
699
int get_drives_list(char *buff, struct drivelist *drives) {
701
static int get_drives_list(char *buff, struct drivelist *drives) {
700
  int i;
702
  int i;
-
 
703
  int listlen = 0;
-
 
704
  int drv;
701
  struct dos_udsc far *udsc_root = get_dos_udsc();
705
  struct dos_udsc far *udsc_root = get_dos_udsc();
702
  struct dos_udsc far *udsc_node;
706
  struct dos_udsc far *udsc_node;
703
 
707
 
704
  if (READMBR(buff, 0x80) != 0) return(1);
708
  for (drv = 0x80; drv < 0x84; drv++) {
705
 
709
 
706
  /* check boot signature at 0x01fe */
-
 
707
  if (*(unsigned short *)(buff + 0x01fe) != 0xAA55) return(2);
710
    if (READMBR(buff, drv) != 0) continue;
708
 
711
 
-
 
712
    /* check boot signature at 0x01fe */
-
 
713
    if (*(unsigned short *)(buff + 0x01fe) != 0xAA55) continue;
-
 
714
 
709
  /* iterate over the 4 partitions in the MBR */
715
    /* iterate over the 4 partitions in the MBR */
710
  for (i = 0; i < 4; i++) {
716
    for (i = 0; i < 4; i++) {
711
    unsigned char *entry;
717
      unsigned char *entry;
712
    bzero(&(drives[i]), sizeof(struct drivelist));
-
 
713
 
718
 
714
    entry = buff + 0x01BE + (i * 16);
719
      entry = buff + 0x01BE + (i * 16);
715
 
720
 
716
    /* ignore partition if fs is unknown (non-FAT) */
721
      /* ignore partition if fs is unknown (non-FAT) */
717
    if ((entry[4] != 0x0E) && (entry[4] != 0x0C)  /* LBA FAT */
722
      if ((entry[4] != 0x0E) && (entry[4] != 0x0C)  /* LBA FAT */
718
     && (entry[4] != 0x01) && (entry[4] != 0x06) && (entry[4] != 0x08)) { /* CHS FAT */
723
       && (entry[4] != 0x01) && (entry[4] != 0x06) && (entry[4] != 0x08)) { /* CHS FAT */
719
      continue;
724
        continue;
720
    }
-
 
721
    drives[i].hd = 0x80;
-
 
722
    drives[i].active = entry[0] >> 7;
-
 
723
    drives[i].start_lba = ((unsigned long *)entry)[2];
-
 
724
    drives[i].tot_sect = ((unsigned long *)entry)[3];
-
 
725
 
-
 
726
    /* now iterate over DOS drives and try to match ont to this MBR entry */
-
 
727
    udsc_node = udsc_root;
-
 
728
    while (udsc_node != NULL) {
-
 
729
      if (udsc_node->hd != 0x80) goto NEXT;
-
 
730
      if (udsc_node->start_lba != drives[i].start_lba) goto NEXT;
-
 
731
 
-
 
732
      /* FOUND! */
-
 
733
      drives[i].dosid = udsc_node->letter + 1;
-
 
734
      {
-
 
735
        unsigned long sz = (drives[i].tot_sect * udsc_node->sectsize) >> 20;
-
 
736
        drives[i].tot_size = (unsigned short)sz;
-
 
737
      }
725
      }
-
 
726
      bzero(&(drives[listlen]), sizeof(struct drivelist));
-
 
727
      drives[listlen].hd = drv;
-
 
728
      drives[listlen].partid = i;
-
 
729
      drives[listlen].active = entry[0] >> 7;
-
 
730
      drives[listlen].start_lba = ((unsigned long *)entry)[2];
-
 
731
      drives[listlen].tot_sect = ((unsigned long *)entry)[3];
-
 
732
 
-
 
733
      /* now iterate over DOS drives and try to match ont to this MBR entry */
-
 
734
      udsc_node = udsc_root;
-
 
735
      while (udsc_node != NULL) {
-
 
736
        if (udsc_node->hd != drv) goto NEXT;
-
 
737
        if (udsc_node->start_lba != drives[listlen].start_lba) goto NEXT;
-
 
738
 
-
 
739
        /* FOUND! */
-
 
740
        drives[listlen].dosid = udsc_node->letter + 1;
-
 
741
        {
-
 
742
          unsigned long sz = (drives[listlen].tot_sect * udsc_node->sectsize) >> 20;
-
 
743
          drives[listlen].tot_size = (unsigned short)sz;
-
 
744
        }
-
 
745
        listlen++;
738
      break;
746
        break;
739
 
747
 
740
      NEXT:
748
        NEXT:
741
      if (udsc_node->next_off == 0xffff) break;
749
        if (udsc_node->next_off == 0xffff) break;
742
      udsc_node = MK_FP(udsc_node->next_seg, udsc_node->next_off);
750
        udsc_node = MK_FP(udsc_node->next_seg, udsc_node->next_off);
743
    }
751
      } /* iterate over UDSC nodes */
744
  }
-
 
-
 
752
    } /* iterate over partition entries of the MBR */
-
 
753
  } /* iterate over BIOS disks (0x80, 0x81, ...) */
745
 
754
 
746
  return(0);
755
  return(listlen);
747
}
756
}
748
 
757
 
749
 
758
 
750
/* displays a list of drives and asks user to choose one for installation
759
/* displays a list of drives and asks user to choose one for installation
751
 * returns a word with DOS drive value in lowest 8 bits (A=1, B=2, etc) and
760
 * returns a word with DOS drive value in lowest 8 bits (A=1, B=2, etc) and
752
 * the BIOS drive id in highest 8 bits (1, 2...) */
761
 * the BIOS drive id in highest 8 bits (1, 2...) */
753
static int selectdrive(void) {
762
static int selectdrive(void) {
754
  char buff[512];
763
  char buff[512];
755
  struct drivelist drives[4];
764
  struct drivelist drives[16];
756
  char drvlist[4][32]; /* C: [2048 MB] */
765
  char drvlist[16][32]; /* up to 16 drives (4 partitions on 4 disks) */
757
  int i, drvlistlen = 0;
766
  int i, drvlistlen;
758
  const char *menulist[16];
767
  const char *menulist[16];
759
  unsigned char driveid = 1; /* fdisk runs on first drive (unless USB boot) */
768
  unsigned char driveid = 1; /* fdisk runs on first drive (unless USB boot) */
760
 
769
 
761
  /* read MBR of first HDD */
770
  /* read MBR of first HDD */
762
  i = get_drives_list(buff, drives);
771
  drvlistlen = get_drives_list(buff, drives);
763
  if (i) {
-
 
764
    printf("get_drives_list() error = %d", i);
-
 
765
    /* TODO build a proper menu with an explanation about drive not partitioned */
-
 
766
  }
-
 
767
 
-
 
768
  /* build a menu with all drives */
-
 
769
  for (i = 0; i < 4; i++) {
-
 
770
    if (drives[i].hd == 0) continue;
-
 
771
    snprintf(drvlist[drvlistlen], sizeof(drvlist[0]), "%c: [%u MiB, hd%c%u, act=%u]", '@' + drives[i].dosid, drives[i].tot_size, 'a' + (drives[i].hd & 127), i, drives[i].active);
-
 
772
    drvlistlen++;
-
 
773
  }
-
 
774
 
772
 
775
  /* if no drive found - disk not partitioned? */
773
  /* if no drive found - disk not partitioned? */
776
  if (drvlistlen == 0) {
774
  if (drvlistlen == 0) {
777
    const char *list[4];
775
    const char *list[4];
778
    newscreen(0);
776
    newscreen(0);
Line 807... Line 805...
807
    mdr_dos_getkey();
805
    mdr_dos_getkey();
808
    reboot();
806
    reboot();
809
    return(MENUQUIT);
807
    return(MENUQUIT);
810
  }
808
  }
811
 
809
 
812
  /* select the drive from list */
810
  /* build a menu with all drives */
813
  for (i = 0; i < drvlistlen; i++) menulist[i] = drvlist[i];
811
  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);
-
 
813
    menulist[i] = drvlist[i];
-
 
814
  }
814
  menulist[i++] = svarlang_str(0, 2); /* Quit to DOS */
815
  menulist[i++] = svarlang_str(0, 2); /* Quit to DOS */
815
  menulist[i] = NULL;
816
  menulist[i] = NULL;
816
  newscreen(0);
-
 
817
 
817
 
-
 
818
  newscreen(0);
818
  i = menuselect(6 /*ypos*/, i /*height*/, menulist, -1);
819
  i = menuselect(6 /*ypos*/, i /*height*/, menulist, -1);
819
  if (i < 0) {
820
  if (i < 0) {
820
    return(MENUPREV);
821
    return(MENUPREV);
821
  } else if (i < drvlistlen) {
822
  } else if (i < drvlistlen) {
822
    return((driveid << 8) | (menulist[i][0] - '@'));
823
    return(((drives[i].hd & 127) << 8) | drives[i].dosid);
823
  }
824
  }
824
 
825
 
825
  return(MENUQUIT);
826
  return(MENUQUIT);
826
}
827
}
827
 
828