Subversion Repositories SvarDOS

Rev

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

Rev 1935 Rev 1939
Line 601... Line 601...
601
  }
601
  }
602
  return(result);
602
  return(result);
603
}
603
}
604
 
604
 
605
 
605
 
-
 
606
/* computes a BSD sum of a block of 512 bytes */
-
 
607
static unsigned short bootsum(void *buff) {
-
 
608
  unsigned short b, sum = 0;
-
 
609
  for (b = 0; b < 256; b++) { /* 256 because I read 16 bits at a time */
-
 
610
    sum <<= 1;
-
 
611
    sum += ((unsigned short *)buff)[b];
-
 
612
  }
-
 
613
  return(sum);
-
 
614
}
-
 
615
 
-
 
616
 
-
 
617
/* read one sector from driveid (0x80, 0x81..) at C,H,S into buff */
-
 
618
static int READSEC_CHS(char *buff, unsigned char driveid, unsigned short cyl, unsigned char head, unsigned char sec);
-
 
619
#pragma aux READSEC_CHS = \
-
 
620
"push es" \
-
 
621
"mov ch, al" \
-
 
622
"shl ah, 1" \
-
 
623
"shl ah, 1" \
-
 
624
"shl ah, 1" \
-
 
625
"shl ah, 1" \
-
 
626
"shl ah, 1" \
-
 
627
"shl ah, 1" \
-
 
628
"or cl, ah" \
-
 
629
"mov ax, 0x0201"  /* read 1 sector into memory */ \
-
 
630
"push ds" \
-
 
631
"pop es" \
-
 
632
"int 0x13" \
-
 
633
"mov ax, 0" /* do not do "xor ax, ax", CF needs to be preserved */ \
-
 
634
"jnc DONE" \
-
 
635
"inc ax" \
-
 
636
"DONE:" \
-
 
637
"pop es" \
-
 
638
parm [bx] [dl] [ax] [dh] [cl] \
-
 
639
modify [cx] \
-
 
640
value [ax]
-
 
641
 
-
 
642
 
-
 
643
/*
-
 
644
 * MBR structure:
-
 
645
 *
-
 
646
 * Boot signature (word 0xAA55) is at 0x01FE
-
 
647
 *
-
 
648
 * partition entry 1 is at 0x01BE
-
 
649
 *                 2    at 0x01CE
-
 
650
 *                 3    at 0x01DE
-
 
651
 *                 4    at 0x01EE
-
 
652
 *
-
 
653
 * a partition entry is:
-
 
654
 * 0x00  status byte (active is bit 0x80 set)
-
 
655
 * 0x01  CHS addr of first sector (here: HEAD)
-
 
656
 * 0x02  CHS addr of first sector (CCSSSSSS) sector in 6 low bits, cylinder high bits in CC
-
 
657
 * 0x03  CHS addr of furst sector (here: low 8 bits of cylinder)
-
 
658
 * 0x04  Partition type:
-
 
659
        0x06/0x08 for CHS FAT16/32
-
 
660
        0x0E/0x0C for LBA FAT16/32
-
 
661
 * 0x05  CHS addr of last sector (same format as for 1st sector)
-
 
662
 * 0x06  CHS addr of last sector (same format as for 1st sector)
-
 
663
 * 0x07  CHS addr of last sector (same format as for 1st sector)
-
 
664
 * 0x08  LBA addr of first sector (4 bytes) - used sometimes instead of CHS
-
 
665
 * 0x0C  number of sectors in partition (4 bytes)
-
 
666
 */
-
 
667
 
-
 
668
struct drivelist {
-
 
669
  union {
-
 
670
    unsigned long lbasector;
-
 
671
    struct {
-
 
672
      unsigned short c;
-
 
673
      unsigned char h;
-
 
674
      unsigned char s;
-
 
675
    } chs;
-
 
676
  } start;
-
 
677
  unsigned char active;
-
 
678
  unsigned char fstype; /* fat16 chs, fat16 lba, fat32 chs, fat32 lba... */
-
 
679
  unsigned char hd; /* 0x80, 0x81... */
-
 
680
  unsigned char dos_id;  /* A=1, B=2, C=3, etc... 0 = unknown */
-
 
681
  unsigned short dos_size; /* size, as provided by DOS (in MiB) */
-
 
682
  unsigned short bootsum; /* hash-like sum of the bootcode area */
-
 
683
};
-
 
684
 
-
 
685
int get_drives_list(char *buff, struct drivelist *drives) {
-
 
686
  int i;
-
 
687
  if (READSEC_CHS(buff, 0x80, 0, 0, 1) != 0) return(1);
-
 
688
 
-
 
689
  /* check boot signature at 0x01fe */
-
 
690
  if (*(unsigned short *)(buff + 0x01fe) != 0xAA55) return(2);
-
 
691
 
-
 
692
  /* iterate over the 4 partitions */
-
 
693
  for (i = 0; i < 4; i++) {
-
 
694
    unsigned char *entry;
-
 
695
    bzero(&(drives[i]), sizeof(struct drivelist));
-
 
696
 
-
 
697
    entry = buff + 0x01BE + (i * 16);
-
 
698
 
-
 
699
    if ((entry[4] == 0x0E) || (entry[4] == 0x0C)) { /* LBA FAT */
-
 
700
      drives[i].start.lbasector = ((unsigned long *)entry)[2];
-
 
701
    } else if ((entry[4] == 0x01) || (entry[4] == 0x06) || (entry[4] == 0x08)) { /* CHS FAT */
-
 
702
      drives[i].start.chs.c = entry[0x02] & 0xC0;
-
 
703
      drives[i].start.chs.c <<= 2;
-
 
704
      drives[i].start.chs.c |= entry[0x03];
-
 
705
      drives[i].start.chs.h = entry[0x01];
-
 
706
      drives[i].start.chs.s = entry[0x02] & 63;
-
 
707
    } else { /* unknown filesystem (non-FAT) */
-
 
708
      continue;
-
 
709
    }
-
 
710
    drives[i].hd = 0x80;
-
 
711
    drives[i].active = entry[0] >> 7;
-
 
712
    drives[i].fstype = entry[4];
-
 
713
  }
-
 
714
 
-
 
715
  /* load the boot sector of each (valid) partition and compute its sum */
-
 
716
  for (i = 0; i < 4; i++) {
-
 
717
    if (drives[i].hd == 0) continue;
-
 
718
    if ((drives[i].fstype == 0x0E) || (drives[i].fstype == 0x0C)) { /* LBA */
-
 
719
      printf("LBA!\n");
-
 
720
    } else { /* CHS */
-
 
721
      if (READSEC_CHS(buff, 0x80, drives[i].start.chs.c, drives[i].start.chs.h, drives[i].start.chs.s) == 0) {
-
 
722
        drives[i].bootsum = bootsum(buff);
-
 
723
      }
-
 
724
    }
-
 
725
  }
-
 
726
 
-
 
727
  /* now iterate over DOS drives and try to match them to an entry in drives[] */
-
 
728
  for (i = 3; i < 8; i++) {
-
 
729
    unsigned short err = 0, sum, b;
-
 
730
    if (isdriveremovable(i) <= 0) {
-
 
731
      printf("SKIPPED = %u\n", i);
-
 
732
      continue;
-
 
733
    }
-
 
734
    _asm {
-
 
735
      push ax
-
 
736
      push bx
-
 
737
      push cx
-
 
738
      push dx
-
 
739
      push di
-
 
740
      push si
-
 
741
      pushf
-
 
742
 
-
 
743
      mov ax, i
-
 
744
      dec ax     /* int 25h takes zero-based drive id (A=0, B=1, C=3, ...) */
-
 
745
      mov cx, 1
-
 
746
      mov dx, 0
-
 
747
      mov bx, buff
-
 
748
      int 0x25
-
 
749
      jnc GOOD
-
 
750
      mov err, 1
-
 
751
      GOOD:
-
 
752
      pop dx     /* int 25h leaves a word on stack, needs to be POPed */
-
 
753
 
-
 
754
      /* extensive push/pop saving of registers because according to RBIL
-
 
755
       * int25h may destroy all registers except segment registers */
-
 
756
 
-
 
757
      popf
-
 
758
      pop si
-
 
759
      pop di
-
 
760
      pop dx
-
 
761
      pop cx
-
 
762
      pop bx
-
 
763
      pop ax
-
 
764
    }
-
 
765
 
-
 
766
    if (err != 0) {
-
 
767
      printf("INT25 ERR FOR DRV %u!\n", i);
-
 
768
      continue;
-
 
769
    }
-
 
770
 
-
 
771
    /* compute the sum of this sector */
-
 
772
    sum = bootsum(buff);
-
 
773
 
-
 
774
    /* try to match the sum to something in drives[] */
-
 
775
    for (b = 0; b < 4; b++) {
-
 
776
      if (drives[b].hd == 0) continue;
-
 
777
      printf("%c: sum = %04X  /  drive[%u].sum = %04X\n", '@' + i, sum, b, drives[b].bootsum);
-
 
778
      if (drives[b].bootsum == sum) {
-
 
779
        drives[b].dos_id = i;
-
 
780
        drives[b].dos_size = disksize(i);
-
 
781
        break;
-
 
782
      }
-
 
783
    }
-
 
784
  }
-
 
785
 
-
 
786
  return(0);
-
 
787
}
-
 
788
 
-
 
789
 
606
static int preparedrive(void) {
790
static int preparedrive(void) {
607
  int selecteddrive;
791
  int selecteddrive;
608
  char cselecteddrive;
792
  char cselecteddrive;
609
  int ds;
793
  int ds;
610
  int choice;
794
  int choice;
611
  char buff[512];
795
  char buff[512];
612
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
796
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
-
 
797
  struct drivelist drives[4];
613
 
798
 
614
  for (;;) {
799
  for (;;) {
615
    char drvlist[4][16]; /* C: [2048 MB] */
800
    char drvlist[4][32]; /* C: [2048 MB] */
616
    int i, drvlistlen = 0;
801
    int i, drvlistlen = 0;
617
 
802
 
-
 
803
    /* read MBR of first HDD */
-
 
804
    i = get_drives_list(buff, drives);
-
 
805
    if (i) {
-
 
806
      printf("get_drives_list() error = %d", i);
-
 
807
    }
-
 
808
 
-
 
809
    sleep(5);
-
 
810
 
618
    /* build a menu with all non-removable drives from C to F */
811
    /* build a menu with all non-removable drives from C to F */
619
    for (i = 3; i < 7; i++) {
812
    for (i = 3; i < 7; i++) {
620
      if (isdriveremovable(i) > 0) {
813
      if (isdriveremovable(i) >= 0) {
621
        unsigned short sz = disksize(i);
814
        unsigned char drvid;
-
 
815
        /* is it in drives? */
622
        if (sz == 0xffff) { /* size not avail (probably unformatted disk) */
816
        for (drvid = 0; drvid < 4; drvid++) if (drives[drvid].dos_id == i) break;
-
 
817
        if (drvid < 4) {
-
 
818
          snprintf(drvlist[drvlistlen], sizeof(drvlist[0]), "%c: [%u MiB, #%u, act=%u]", '@' + i, drives[drvid].dos_size, drvid, drives[drvid].active);
-
 
819
        } else if (disksize(i) == 0xffff) {
623
          snprintf(drvlist[drvlistlen], sizeof(drvlist[0]), "%c:", '@' + i, disksize(i));
820
          snprintf(drvlist[drvlistlen], sizeof(drvlist[0]), "%c: (unformatted)", '@' + i);
624
        } else {
821
        } else {
625
          snprintf(drvlist[drvlistlen], sizeof(drvlist[0]), "%c: [%u MiB]", '@' + i, disksize(i));
822
          continue;
626
        }
823
        }
627
        drvlistlen++;
824
        drvlistlen++;
628
      }
825
      }
629
    }
826
    }
630
 
827