Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.os.msdos.programmer > #93

Partitions

From Single Stage to Orbit <alex.buell@munted.org.uk>
Newsgroups comp.os.msdos.programmer
Subject Partitions
Date 2011-06-02 01:03 +0100
Organization One very high maintenance cat
Message-ID <5k0jb8-d4h1.ln1@nntp.local.net> (permalink)

Show all headers | View raw


I hereby release these sources into the public domain, provided
acknowledgements as myself as the author is kept for posterity.

The following program simply gets the partition table from all the hard
disks available on the system and prints them out in human readable
form. I originally wrote this program whilst hunting down an obscure bug
in an IDE hard disk driver. This program can be compiled with Watcom C
or with Turbo C 2.01. BEWARE: this program makes direct accesses to the
hard disk through the hardware, so be careful. 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <dos.h>
#include <conio.h>

#ifdef __TURBOC__
#define outportb outportb
#define inportb inportb
#define inportw inport
#endif

#ifdef __WATCOMC__
#define outportb outp
#define inportb inp
#define inportw inpw
#endif

#define IDE_DATA        0x01f0
#define IDE_ERROR       0x01f1 /* read */
#define IDE_SECTORS     0x01f2
#define IDE_SECTOR      0x01f3
#define IDE_CYL_LOW     0x01f4
#define IDE_CYL_HIGH    0x01f5
#define IDE_DRIVEHEAD   0x01f6
#define IDE_STATUS      0x01f7 /* read */
#define IDE_COMMAND     0x01f7 /* write */

#define IDE_CMD_READ    0x20

#define SECTOR_SIZE     512

typedef struct
{
	unsigned char bootable;
	unsigned char first_chs_head;
	unsigned char first_chs_sector_cylinder;
	unsigned char first_chs_cylinder;
	unsigned char partition_type;
	unsigned char last_chs_head;
	unsigned char last_chs_sector_cylinder;
	unsigned char last_chs_cylinder;
	unsigned long first_lba_sector;
	unsigned long lba_sectors;
} partition_t;

typedef struct 
{
	unsigned char code[440]; /* bootloader */
	unsigned long disk_signature;  /* optional */
	unsigned short int null;

	partition_t partitions[4];
	unsigned short int mbr_signature; /* usually 0xAA55 */  
} mbr_t;        

int main(int argc, char *argv[])
{
	char far *bios_drives = MK_FP(0x0, 0x475);
	int drives = (char)*bios_drives;
	unsigned char *buffer = malloc(SECTOR_SIZE); 
	mbr_t *mbr = (mbr_t *)buffer;
	int i, j, dump = 0;

	if (!buffer)
	{
		printf("Unable to allocate memory for disk buffer.\n");
		return 1;
	}

	if ((argc == 2) && (strcmp(argv[1], "-d") == 0))
		dump = 1;

	for (i = 0; i < drives; i++)
	{
		outportb(IDE_DRIVEHEAD, i == 0 ? 0xA0 : 0xA8);
		outportb(IDE_SECTORS, 1);
		outportb(IDE_SECTOR, 1);
		outportb(IDE_CYL_LOW, 0);
		outportb(IDE_CYL_HIGH, 0);
		outportb(IDE_COMMAND, IDE_CMD_READ);

		while ((inportb(IDE_COMMAND) & 8) == 0);

		for (j = 0; j < SECTOR_SIZE / 2; j++)
		{
			unsigned int data = inportw(IDE_DATA);
			memcpy(&buffer[j * 2], &data, sizeof(unsigned int));
		}

		printf("Drive %d, disk signature: %ld, MBR signature: %04hX\n\n",
			i, mbr->disk_signature, mbr->mbr_signature);

		if (dump)
		{
			for (j = 0; j < SECTOR_SIZE; j += 16)
			{
				int l;
	
				for (l = 0; l < 16; l++)
					printf("%02X ", buffer[j + l]);

				printf("\n");
			}
			printf("\n");
		}

		for (j = 0; j < 4; j++)
		{
			int cylinder, head, sector;
			unsigned long disksize;
			partition_t *p = &mbr->partitions[j];

			printf("%d. ", j);
			cylinder = p->first_chs_cylinder + ((p->first_chs_sector_cylinder >> 6) << 8);
			head = p->first_chs_head;
			sector = p->first_chs_sector_cylinder & 0x3F;
			if (cylinder > 0 || head > 0 || sector > 0)
				printf("C=%d,H=%d,S=%d", 
					cylinder, head, sector);

			cylinder = p->last_chs_cylinder + ((p->last_chs_sector_cylinder >> 6) << 8);
			head = p->last_chs_head;
			sector = p->last_chs_sector_cylinder & 0x3F;
			if (cylinder > 0 || head > 0 || sector > 0)
			{
				printf(" .. C=%d,H=%d,S=%d", 
					cylinder, head, sector);

				/* bug in Turbo C 2.01 makes this necessary */
				disksize = (cylinder + 1);
				disksize *= (head + 1);
				disksize *= sector;
				disksize *= SECTOR_SIZE;

				printf(" (%ld bytes) ", disksize);
	
				if (p->bootable & 0x80)
					printf("Bootable");
			}
			else
				printf("None.");

			printf("\n");
		}

		if (i < drives - 1)
			printf("\n");
	}

	free(buffer);
	return 0;
}


-- 
Tactical Nuclear Kittens

Back to comp.os.msdos.programmer | Previous | NextNext in thread | Find similar


Thread

Partitions Single Stage to Orbit <alex.buell@munted.org.uk> - 2011-06-02 01:03 +0100
  Re: Partitions Single Stage to Orbit <alex.buell@munted.org.uk> - 2011-06-02 15:20 +0100

csiph-web