6 /******************* START OF SPECIFICATIONS *******************/
8 /* SOURCE FILE NAME: FDISK */
10 /* DESCRIPTIVE NAME: FIXED DISK PARTITIONING UTILITY */
13 /* Allows creation and deletion of DOS related partitions */
14 /* on fixed disk devices 80-81h (int 13h BIOS defined, */
15 /* DOS). Also allows display of all partitions, and will */
16 /* allow a partition to be marked active (bootable). The */
17 /* user will be prompted for action thru a full screen */
18 /* interface. The user can also create, delete and display */
19 /* logical DOS drives within a EXTENDED DOS Partition. If a*/
20 /* regular DOS partition is created, the beginning of the */
21 /* partition will be scanned to insure a contiguous area of*/
22 /* good sectors on the disk large enough to satisfy the */
23 /* DOS system requirements. If a bad spot is found, the */
24 /* start of the partition will be moved out until a good */
27 /* NOTES: The program will work by setting up a logical image */
28 /* of all relevant disk information at initilization */
29 /* time. All operations will be performed on this */
30 /* logical image, thus reducing disk accesses to only */
31 /* those required to initially set up the logical image,*/
32 /* and to write the changed information at the end. The */
33 /* user will be informed if there is a problem writing */
34 /* the logical image back to the disk. */
36 /* FDISK will interface with the partition table in the */
37 /* master boot record as defined in the PC-DOS technical*/
38 /* reference manual. It will also create and manage the */
39 /* EXTENDED DOS partition architecture as defined in the*/
40 /* PC-DOS 3.30 functional spec (CP/DOS spec dcr pending)*/
42 /* ENTRY POINTS: MAIN */
43 /* LINKAGE: [d:] [path] FDISK */
45 /* EXTERNAL REFERENCES: */
46 /* Fixed Disk Master Boot Record */
47 /* EXTENDED Partition Volume Boot Records */
48 /* Note: Both of the above are physical data structures on */
49 /* the surface of the disk */
51 /* P.S. - To whoever winds up maintaining this, I will */
52 /* apoligize in advance. I had just learned 'C' when */
53 /* writing this, so out of ignorance of the finer points*/
54 /* of the langauge I did a lot of things by brute force.*/
55 /* Hope this doesn't mess you up too much - MT 5/20/86 */
56 /******************** END OF SPECIFICATIONS ********************/
64 #include <string.h> /* AN000 */
65 #include <fdiskmsg.h> /* AN000 */
66 #include <msgret.h> /* AN000 */
67 #include <process.h> /* AN000 */
68 #include <stdio.h> /* AN000 */
71 /**************************************************************************/
73 /* UTILITY NAME: FDISK.com */
74 /* SOURCE FILE NAME: FDISK.c */
75 /* STATUS: FDISK utility, DOS 3.3 */
76 /* CHANGE HISTORY: UPDATED 5-29-87 DOS4.0 DRM */
77 /* SYNTAX (Command line) */
83 /* [d:][path]FDISK d [/PRI:m | /EXT:n | /LOG:o ...] */
85 /* d: Drive to load FDISK utility from */
87 /* path path to the directory on specified drive to */
90 /* d Drive (1 or 2) that FDISK should operate on */
92 /* /PRI:m Size of Primary DOS partition to create in K */
94 /* /EXT:n Size of Extended DOS partition to create in K */
96 /* /LOG:o Size of Logical drive to create in K in the */
97 /* extended partition */
99 /* UTILITY FUNCTION: */
100 /* Allows you to create, set up, display, and delete the */
101 /* DOS partitions on a fixed disk. */
103 /**************************************************************************/
106 /******************* START OF SPECIFICATIONS *******************/
108 /* SUBROUTINE NAME: CHANGE_ACTIVE_PARTITION */
110 /* DESCRIPTIVE NAME: Change bootable partition */
112 /* FUNCTION: Will allow user to select the partition that will */
113 /* recieve control when system is IPL'd. This is */
114 /* only for the first hardfile as far as booting is */
115 /* concerned, although partitions can be set active */
116 /* the second. There are reserved partitions that may*/
117 /* not be set active and this routine will enforce */
120 /* NOTES: If no valid partition is specified, then the active */
121 /* partition setting is left unchanged. Screen can be */
122 /* exited via the ESC command before active partition */
123 /* is changed and no action will take place */
125 /* The following screen is managed */
127 /* ³0000000000111111111122222222223333333333³ */
128 /* ³0123456789012345678901234567890123456789³ */
129 /* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */
134 /* 04³Change Active Partition ³ */
136 /* 06³Current Fixed Disk Drive: # ³ */
138 /* 08³Partition Status Type Start End Size³ */
139 /* 09³ # # ####### #### #### ####³ */
144 /* 14³Total disk space is #### cylinders. ³ */
148 /* 18³Enter the number of the partition you ³ */
149 /* 19³want to make active...............: [#] ³ */
153 /* 23³Press ESC to return to FDISK Options ³ */
154 /* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
156 /* ENTRY POINTS: Change_Active_Partition */
157 /* LINKAGE: change_active_partition () */
162 /* EXIT-NORMAL: ERROR=FALSE */
164 /* EXIT-ERROR: ERROR=TRUE */
165 /* GOTO internal_program_error if invalid num */
166 /* input is returned to this level */
168 /* EFFECTS: Display prompts needed to guide user input, and */
169 /* gets input from user. */
172 /* INTERNAL REFERENCES: */
179 /* internal_program_error */
181 /* EXTERNAL REFERENCES: */
184 /******************** END OF SPECIFICATIONS ********************/
187 void change_active_partition()
197 char valid_partitions;
198 char num_of_bootable_partitions;
206 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
211 /* Setup and print current disk */
212 insert[0] = cur_disk+1+'0';
215 /* print ESC prompt */
218 /* Only allow active partitions on the first (and bootable) disk */
219 if (cur_disk == c(0)) /* AC000 */
222 /* Display partition info and see if any partitions exist*/
226 /* See if active partition is bootable */
227 for (i=u(0); i < u(4); i++) /* AC000 */
229 if (part_table[0][i].sys_id != uc(0) &&
230 part_table[0][i].boot_ind == uc(0x80)) /* AC000 */
232 if ((part_table[0][i].sys_id == uc(BAD_BLOCK)) ||
233 (part_table[0][i].sys_id==uc(EXTENDED))) /* AC000 */
235 /* The active partition is not bootable, so warn user */
241 /* Check to see if only one partition */
242 num_partitions = c(0) ; /* AC000 */
243 num_of_bootable_partitions = c(0); /* AC000 */
244 for (i=u(0); i < u(4); i++) /* AC000 */
247 if (part_table[0][i].sys_id != uc(0)) /* AC000 */
249 /* Get a count of partitions */
252 /* Get a count of the number of defined partitions but don't*/
253 /* count those we know aren't bootable */
254 if ((part_table[0][i].sys_id != uc(BAD_BLOCK)) &&
255 (part_table[0][i].sys_id != uc(EXTENDED))) /* AC000 */
257 num_of_bootable_partitions++;
261 /* If only one partition found, see if it is active already */
262 if (num_of_bootable_partitions == c(1)) /* AC000 */
265 /* Find the partition and see if it is already active */
266 for (i=u(0); i < u(4); i++) /* AC000 */
269 if (part_table[0][i].sys_id !=uc(0) &&
270 part_table[0][i].boot_ind == uc(0x80)) /* AC000 */
273 /* Make sure it is not unbootable partition again*/
274 if ((part_table[0][i].sys_id != uc(BAD_BLOCK)) &&
275 (part_table[0][i].sys_id!=uc(EXTENDED))) /* AC000 */
278 /* Once it is found, put out the message */
281 /* Wait for ESC, then get out */
284 /* clear the screen before going back to main menu*/
285 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
291 /* See if any bootable partitions exist */
292 if (num_of_bootable_partitions == c(0)) /* AC000 */
294 /* At this point, we know at least one partition does exist due to*/
295 /* getting past the table_display call, so the only ones around */
296 /* must be unbootable */
298 /* Display this fact then get out of here */
303 /* All is okay to go and set one, do display prompts */
304 number_in_msg((XFLOAT)total_mbytes[cur_disk],u(0)); /* AC000 */
307 /* Put up input prompt*/
310 /* Assume bad input until proven otherwise */
312 valid_partitions = num_partitions;
313 input_default = c(NUL); /* AC000 */
317 /* Go get partition to make active */
318 input = get_num_input(input_default,num_partitions,input_row,input_col);
320 /* Save the input for next time in case CR pressed */
321 input_default = input-'0';
323 clear_screen(u(18),u(0),u(23),u(79)); /* AC000 */
325 if (input != c(ESC)) /* AC000 */
327 /* See if known unbootable partition */
328 /* Set the new one */
329 valid_partitions = c(0); /* AC000 */
331 /* Make sure the partitions are in physical order*/
332 sort_part_table(c(4)); /* AC000 */
334 /* Go find existing partitiona */
335 for (i=u(0);i < u(4); i++) /* AC000 */
337 /* First we have to find it */
338 if (part_table[0][sort[i]].sys_id != uc(0)) /* AC000 */
340 /* If this is the 'input'th one, then we got it */
341 if (valid_partitions == (input-'1'))
343 /* See if it is an unbootable partition */
344 if ((part_table[0][sort[i]].sys_id != uc(BAD_BLOCK)) &&
345 (part_table[0][sort[i]].sys_id != uc(EXTENDED))) /* AC000 */
348 /* Its bootable, so we have good input */
349 valid_input = c(TRUE); /* AC000 */
351 /* Remove the active indicator from the old partition */
352 for (x=u(0); x < u(4); x++) /* AC000 */
355 if (part_table[0][x].boot_ind == uc(0x80)) /* AC000 */
357 part_table[0][x].changed = TRUE;
358 part_table[0][x].boot_ind = uc(0); /* AC000 */
362 /* Put in new active indicator */
363 part_table[0][sort[i]].boot_ind = uc(0x80); /* AC000 */
365 /* Indicate that it is changed */
366 part_table[0][sort[i]].changed = TRUE;
368 /* Update the partition info display */
371 /* Clear off the old prompts */
372 clear_screen(u(16),u(0),u(21),u(79)); /* AC000 */
381 /* It is, so setup message and tell user */
389 /* Indicate we found one but keep going */
397 /* Mark ESC as ok input so we can get out of here */
398 valid_input = c(TRUE); /* AC000 */
402 END /* table display test endif */
405 /* No partitions to make active */
413 /* clear the screen before going back to main menu */
414 if (input != c(ESC)) /* AC000 */
418 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
424 /******************* START OF SPECIFICATIONS *******************/
426 /* SUBROUTINE NAME: DISPLAY_PARTITION_INFORMATION */
428 /* DESCRIPTIVE NAME: Display partition information */
430 /* FUNCTION: Displays defined partition information and prompt */
431 /* user to display disk volumes if they exist */
435 /* The following screen is managed */
437 /* ³0000000000111111111122222222223333333333³ */
438 /* ³0123456789012345678901234567890123456789³ */
439 /* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */
444 /* 04³Display Partition Information ³ */
446 /* 06³Current Fixed Disk Drive: # ³ */
448 /* 08³Partition Status Type Start End Size³ */
449 /* 09³ # # ####### #### #### ####³ */
454 /* 14³Total disk space is #### cylinders. ³ */
458 /* 18³The EXTENDED DOS partition contains DOS ³ */
459 /* 19³disk volumes. Do you want to display ³ */
460 /* 20³the volume information............? [Y] ³ */
463 /* 23³Press ESC to return to FDISK Options ³ */
464 /* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
466 /* ENTRY POINTS: Display_Partition_Information */
467 /* LINKAGE: display_partition_information () */
472 /* EXIT-NORMAL: ERROR=FALSE */
474 /* EXIT-ERROR: ERROR=TRUE */
475 /* GOTO internal_program_error if invalid input */
476 /* returned to this routine */
478 /* EFFECTS: No data directly modified by this routine, but */
479 /* child routines will modify data. */
481 /* INTERNAL REFERENCES: */
488 /* find_partition_type */
489 /* display_volume_information */
490 /* internal_program_error */
492 /* EXTERNAL REFERENCES: */
495 /******************** END OF SPECIFICATIONS ********************/
498 void display_partition_information()
505 input = c(NUL); /* AC000 */
507 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
512 /* Setup and print current disk */
513 insert[0] = cur_disk+1+'0';
516 /* print ESC prompt */
519 /* Display information */
523 /* Setup and print disk space msg */
524 number_in_msg((XFLOAT)total_mbytes[cur_disk],u(0)); /* AC000 */
527 /* See if any logical drive stuff to display */
528 if (find_partition_type(uc(EXTENDED))) /* AC000 */
530 /* See if any logical drives exist */
531 if (find_logical_drive())
534 /* Prompt to see if they want to see EXTENDED info */
537 /* Get Y/N input, default is YES */
538 input = get_yn_input(c(Yes),input_row,input_col); /* AC000 AC011 */
542 case 1: display_volume_information(); /* AC000 */
545 case 0: break; /* AC000 */
549 default: internal_program_error();
554 input = wait_for_ESC();
557 input = wait_for_ESC();
560 input = wait_for_ESC();
561 /* clear the screen before going back to main menu */
562 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
569 /******************* START OF SPECIFICATIONS *******************/
571 /* SUBROUTINE NAME: DISPLAY_VOLUME_INFORMATION */
573 /* DESCRIPTIVE NAME: Display DOS disk Volume Information */
575 /* FUNCTION: Displays disk volume size and existence */
579 /* The following screen is managed */
581 /* ³0000000000111111111122222222223333333333³ */
582 /* ³0123456789012345678901234567890123456789³ */
583 /* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */
584 /* 01³Display DOS Disk Volume Information ³ */
586 /* 03³Vol Start End Size Vol Start End Size³ */
587 /* 04³ # #### #### #### # #### #### ####³ */
606 /* 23³Press ESC to return to FDISK Options ³ */
607 /* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
609 /* ENTRY POINTS: Display_Volume_Information */
610 /* LINKAGE: display_volume_information () */
615 /* EXIT-NORMAL: ERROR=FALSE */
617 /* EXIT-ERROR: ERROR=TRUE */
619 /* EFFECTS: No data directly modified by this routine, but */
620 /* child routines will modify data. */
622 /* INTERNAL REFERENCES: */
629 /* EXTERNAL REFERENCES: */
632 /******************** END OF SPECIFICATIONS ********************/
635 void display_volume_information()
642 input = c(NUL); /* AC000 */
643 /* clear the screen */
644 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
649 /* Display information */
650 temp = volume_display();
652 /* Set up partition size message */
653 sprintf(insert,"%4.0d",get_partition_size( uc(EXTENDED) ) );
656 /* print ESC prompt */
660 input = wait_for_ESC();
665 char check_valid_environment()
668 /* See if the net is there */
669 regs.x.ax = u(INSTALLATION_CHECK); /* AC000 */
670 int86((int)NETWORK,®s,®s); /* AC000 */
672 #ifdef DEBUG /* AN006 */
673 regs.h.al = uc(0); /* AN006 */
677 if (regs.h.al != uc(0)) /* AC000 */
680 /* See if server is loaded, otherwise okay */
681 if ((regs.x.bx & SERVER_CHECK) != u(0)) /* AC000 */
683 no_fatal_error = FALSE;
684 display_msg((int)4,(int)DosStdEr,(int)nosubcnt,(int)nosubptr,c(noinput),c(Utility_Msg_Class)); /* AN000 AC014*/
694 void init_partition_tables()
701 unsigned partition_location;
703 char more_drives_exist;
704 char num_logical_drives;
708 /* initialize first drive found to "C" */
709 next_letter = c(SEA); /* AC000 */
711 /* Look at both disks */
712 for (j = uc(0); j < number_of_drives; j++) /* AC000 */
715 /* Initialize the cur_disk field to the drive in question so */
716 /* that the calls to the partition information routines will work */
717 cur_disk = ((char)(j));
719 /* Read in the master boot record and see if it was okay */
720 if (read_boot_record(u(0),j,uc(0),uc(1))) /* AC000 */
723 /* See if there was a valid boot record there */
724 if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA))) /* AC000 */
727 /* What was on the disk is a valid boot record, so save it */
728 for (i=u(0);i < u(BYTES_PER_SECTOR); i++) /* AC000 */
730 master_boot_record[j][i] = boot_record[i];
733 /* We've now got a copy of the master boot record saved. Now we need */
734 /* to translate what in the boot record to the area that it's going */
735 /* to be worked on (part_table) */
737 /* Read in the data from the master boot record partition entries*/
738 for (i=u(0); i < u(4); i++) /* AC000 */
743 part_table[j][i].boot_ind = master_boot_record[j][0x1BE+index];
746 part_table[j][i].start_head = master_boot_record[j][0x1BF+index];
748 /* Start sector - unscramble it from INT 13 format*/
749 part_table[j][i].start_sector= (master_boot_record[j][0x1C0+index] & 0x3F);
751 /* Start cyl - unscramble it from INT 13 format*/
752 part_table[j][i].start_cyl= ((((unsigned)master_boot_record[j][0x1C0+index]) & 0x00C0) << 2)
753 + ((unsigned)master_boot_record[j][0x1C1+index]);
756 part_table[j][i].sys_id = master_boot_record[j][0x1C2+index];
759 part_table[j][i].end_head = master_boot_record[j][0x1C3+index];
761 /* End sector - unscramble it from INT 13 format*/
762 part_table[j][i].end_sector= (master_boot_record[j][0x1C4+index] & 0x3F);
764 /* End cyl - unscramble it from INT 13 format*/
765 part_table[j][i].end_cyl= ((((unsigned)master_boot_record[j][0x1C4+index]) & 0x00C0) << 2)
766 + ((unsigned)master_boot_record[j][0x1C5+index]);
768 /* Relative sectors */
770 part_table[j][i].rel_sec =
771 ((unsigned long)master_boot_record[j][0x1C9+index]) << 24;
773 part_table[j][i].rel_sec = part_table[j][i].rel_sec +
774 (((unsigned long)master_boot_record[j][0x1C8+index]) << 16);
776 part_table[j][i].rel_sec = part_table[j][i].rel_sec +
777 (((unsigned long)master_boot_record[j][0x1C7+index]) << 8);
779 part_table[j][i].rel_sec = part_table[j][i].rel_sec +
780 ((unsigned long)master_boot_record[j][0x1C6+index]);
782 /* Number of sectors */
783 part_table[j][i].num_sec =
784 ((unsigned long)master_boot_record[j][0x1CD+index]) << 24;
786 part_table[j][i].num_sec = part_table[j][i].num_sec +
787 (((unsigned long)master_boot_record[j][0x1CC+index]) << 16);
789 part_table[j][i].num_sec = part_table[j][i].num_sec +
790 (((unsigned long)master_boot_record[j][0x1CB+index]) << 8);
792 part_table[j][i].num_sec = part_table[j][i].num_sec +
793 ((unsigned long)master_boot_record[j][0x1CA+index]);
795 part_table[j][i].mbytes_used =
796 cylinders_to_mbytes(((part_table[j][i].end_cyl-part_table[j][i].start_cyl)+1),
797 cur_disk); /* AN004 */
799 part_table[j][i].percent_used =
800 cylinders_to_percent(((part_table[j][i].end_cyl-part_table[j][i].start_cyl)+1),
801 total_disk[cur_disk]); /* AN000 */
803 /* Set drive letter */
804 if ( (part_table[j][i].sys_id == DOS12) || /* AN000 */
805 (part_table[j][i].sys_id == DOS16) || /* AN000 */
806 (part_table[j][i].sys_id == DOSNEW) ) /* AN000 */
807 part_table[j][i].drive_letter = next_letter++; /* AN000 */
809 /* Set changed flag */
810 part_table[j][i].changed = FALSE;
819 /* Look at both disks */
820 for (j = uc(0); j < number_of_drives; j++) /* AC000 */
823 /* Initialize the cur_disk field to the drive in question so */
824 /* that the calls to the partition information routines will work */
825 cur_disk = ((char)(j));
827 /* Read in the master boot record and see if it was okay */
828 if (read_boot_record(u(0),j,uc(0),uc(1))) /* AC000 */
830 /* Now, go read in extended partition info */
831 if (find_partition_type(uc(EXTENDED))) /* AC000 */
833 /* Initialize the array to zero's - include one dummy entry */
834 for (i=u(0); i < u(24); i++) /* AC000 */
836 ext_table[j][i].boot_ind = uc(0); /* AC000 */
837 ext_table[j][i].start_head = uc(0); /* AC000 */
838 ext_table[j][i].start_sector = uc(0); /* AC000 */
839 ext_table[j][i].start_cyl = u(0); /* AC000 */
840 ext_table[j][i].sys_id = uc(0); /* AC000 */
841 ext_table[j][i].end_head = uc(0); /* AC000 */
842 ext_table[j][i].end_sector = uc(0); /* AC000 */
843 ext_table[j][i].end_cyl = u(0); /* AC000 */
844 ext_table[j][i].rel_sec = ul(0); /* AC000 */
845 ext_table[j][i].num_sec = ul(0); /* AC000 */
846 ext_table[j][i].mbytes_used = f(0); /* AN000 */
847 ext_table[j][i].percent_used = u(0); /* AN000 */
848 ext_table[j][i].changed = FALSE;
849 ext_table[j][i].drive_letter = NUL; /* AN000 */
851 strcpy(ext_table[cur_disk][i].system,NUL); /* AN000 */
852 strcpy(ext_table[cur_disk][i].vol_label,NUL); /* AN000 */
856 /* Find where the first extended boot record is */
857 temp = find_partition_location(uc(EXTENDED)); /* AC000 */
858 partition_location = part_table[j][temp].start_cyl;
860 /* Go find extended boot records as long as there are more of them */
861 more_drives_exist = TRUE;
863 /* Init the number of logical drives, for a array index */
864 num_logical_drives = c(0); /* AC000 */
866 while (more_drives_exist)
868 /* Assume we won't find another logical drive */
869 more_drives_exist = FALSE;
871 /*Read in the extended boot record */
872 if (read_boot_record(partition_location,
877 load_logical_drive(num_logical_drives,j);
880 /* find the next logical drive */
881 for (i = u(0); i < u(4); i++) /* AC000 */
884 /* See if a sys id byte of exteneded exists */
885 if (boot_record[0x1C2+index] == uc(EXTENDED)) /* AC000 */
887 /* Found another drive, now get its location */
888 partition_location= (((((unsigned)(boot_record[0x1C0 + index])) & 0x00C0) << 2));
889 partition_location = partition_location + ((unsigned)(boot_record[0x1C1+index]));
891 /* Indicate we found another one */
892 more_drives_exist = TRUE;
894 /* Up the count of found ones */
895 num_logical_drives++;
909 void load_logical_drive(point,drive)
916 char volume_label[13]; /* AC000 *//*Used be 11*/
917 unsigned ext_part_num; /* AN000 */
919 unsigned j; /* AN000 */
920 unsigned k; /* AN000 */
921 unsigned length; /* AN000 */
923 unsigned dx_pointer; /* AN000 */
924 unsigned partition_location; /* AN000 */
926 /* Check to see if anything is there */
927 if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA))) /* AC000 */
929 /* The boot record is there - read in the logical drive if it is there */
930 for (i = u(0); i < u(4); i++) /* AC000 */
934 /* See if it is a defined extended drive*/
935 if ((boot_record[0x1C2 + index] != uc(0)) && (boot_record[0x1C2 + index] != uc(EXTENDED))) /* AC000 */
938 ext_table[drive][point].boot_ind = boot_record[0x1BE + index];
941 ext_table[drive][point].start_head = boot_record[0x1BF + index];
943 /* Start sector - unscramble it from INT 13 format*/
944 ext_table[drive][point].start_sector= (boot_record[0x1C0 + index] & 0x3F);
946 /* Start cyl - unscramble it from INT 13 format*/
947 ext_table[drive][point].start_cyl= ((((unsigned)boot_record[0x1C0+index]) & 0x00C0) << 2)
948 + ((unsigned)boot_record[0x1C1+index]);
952 ext_table[drive][point].sys_id = boot_record[0x1C2+index];
955 ext_table[drive][point].end_head = boot_record[0x1C3+index];
957 /* End sector - unscramble it from INT 13 format*/
958 ext_table[drive][point].end_sector= (boot_record[0x1C4+index] & 0x3F);
961 /* End cyl - unscramble it from INT 13 format*/
962 ext_table[drive][point].end_cyl= ((((unsigned)boot_record[0x1C4+index]) & 0x00C0) << 2)
963 + ((unsigned)boot_record[0x1C5+index]);
965 /* Relative sectors */
966 ext_table[drive][point].rel_sec =
967 ((unsigned long)boot_record[0x1C9+index]) << 24;
969 ext_table[drive][point].rel_sec =
970 ext_table[drive][point].rel_sec+(((unsigned long)boot_record[0x1C8+index]) << 16);
972 ext_table[drive][point].rel_sec =
973 ext_table[drive][point].rel_sec + (((unsigned long)boot_record[0x1C7+index]) << 8);
975 ext_table[drive][point].rel_sec =
976 ext_table[drive][point].rel_sec + ((unsigned long)boot_record[0x1C6+index]);
978 /* Number of sectors */
980 ext_table[drive][point].num_sec =
981 ((unsigned long)boot_record[0x1CD+index]) << 24;
983 ext_table[drive][point].num_sec =
984 ext_table[drive][point].num_sec+(((unsigned long)boot_record[0x1CC+index]) << 16);
986 ext_table[drive][point].num_sec =
987 ext_table[drive][point].num_sec + (((unsigned long)boot_record[0x1CB+index]) << 8);
989 ext_table[drive][point].num_sec =
990 ext_table[drive][point].num_sec + ((unsigned long)boot_record[0x1CA+index]);
992 ext_table[drive][point].mbytes_used =
993 cylinders_to_mbytes(((ext_table[drive][point].end_cyl - ext_table[drive][point].start_cyl)+1),
994 cur_disk); /* AN004 */
996 ext_part_num = find_partition_location(uc(EXTENDED));
998 ext_table[drive][point].percent_used =
999 cylinders_to_percent(((ext_table[drive][point].end_cyl-ext_table[drive][point].start_cyl)+1),
1000 ((part_table[drive][ext_part_num].end_cyl-part_table[drive][ext_part_num].start_cyl)+1)); /* AN000 */
1002 ext_table[drive][point].drive_letter = next_letter++; /* AN000 */
1004 partition_location = ext_table[drive][point].start_cyl;
1006 if (read_boot_record(ext_table[drive][point].start_cyl,
1008 ext_table[drive][point].start_head,
1009 ext_table[drive][point].start_sector));
1011 /* See if the disk has already been formated */
1012 if (check_format(ext_table[drive][point].drive_letter) == TRUE ) /* AN002 */
1014 /* get volume and system info */
1016 /* AC000 Just for cleaning up purposes */
1018 for (k = u(0); k < u(12); k++) /* AC000 */
1020 ext_table[drive][point].vol_label[k]=u(0); /* AC000 */
1023 for (k = u(0); k < u(9); k++) /* AC000 */
1025 ext_table[drive][point].system[k]=u(0); /* AC000 */
1028 get_volume_string(ext_table[drive][point].drive_letter,&volume_label[0]); /* AN000 AC015 */
1030 for (k = u(0); k < strlen(volume_label); k++) /* AC000 AC015 */
1031 BEGIN /* AC000 AC015 */
1032 ext_table[drive][point].vol_label[k]=volume_label[k]; /* AC000 AC015 */
1033 END /* AC000 AC015 */
1035 /* Now try to get it using GET MEDIA ID function */
1036 if (get_fs_and_vol(ext_table[drive][point].drive_letter)) /* AN000 */
1039 /* AC000 Just use more conceptually simple logic */
1040 for (k=u(0); k < u(8); k++) /* AC000 */
1043 if (dx_buff.file_system[k] != ' ') /* AC000 */
1044 length = k+1; /* AC000 */
1047 strncpy(ext_table[drive][point].system,&dx_buff.file_system[0],u(length)); /* AN000 */
1053 if (ext_table[drive][point].num_sec > (unsigned long)FAT16_SIZE) /* AN000 */
1054 strcpy(ext_table[drive][point].system,FAT16); /* AN000 */
1056 strcpy(ext_table[drive][point].system,FAT12); /* AN000 */
1061 /* set up array to say no file system or volume label */
1062 strcpy(ext_table[drive][point].vol_label,NOVOLUME); /* AN000 */
1063 strcpy(ext_table[drive][point].system,NOFORMAT); /* AN000 */
1067 regs.x.ax = NETWORK_IOCTL;
1068 regs.h.bl = ((ext_table[drive][point].drive_letter - 'A') + 1);
1069 intdos(®s,®s);
1070 if (regs.x.dx & 0x1000) strcpy(ext_table[drive][point].vol_label,"* Remote * ");
1072 read_boot_record(ext_table[drive][point].start_cyl,
1087 void reboot_system()
1091 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
1092 if (quiet_flag == FALSE)
1100 cur_disk = c(0); /* AN001 */
1101 reset_video_information(); /* AN006 */
1102 if ( (find_partition_type(uc(DOS12))) ||
1103 (find_partition_type(uc(DOS16))) ||
1104 (find_partition_type(uc(DOSNEW))) ) /* AN001 */
1105 exit(ERR_LEVEL_0); /* AN001 */
1107 exit(ERR_LEVEL_1); /* AN001 */
1113 void internal_program_error()
1116 display(internal_error);
1117 DOSEXIT(u(0),u(0)); /* AC000 */