kern

diff src/part.c @ 88:a398bf73fe93

- added the partition table parsing code - starting with the filesystem
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 08 Dec 2011 13:34:47 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/part.c	Thu Dec 08 13:34:47 2011 +0200
     1.3 @@ -0,0 +1,149 @@
     1.4 +#include <stdio.h>
     1.5 +#include <stdlib.h>
     1.6 +#include <assert.h>
     1.7 +#include "part.h"
     1.8 +#include "ata.h"
     1.9 +
    1.10 +#define PTYPE_EXT		0x5
    1.11 +#define PTYPE_EXT_LBA	0xf
    1.12 +
    1.13 +#define PATTR_ACT_BIT	(1 << 9)
    1.14 +#define PATTR_PRIM_BIT	(1 << 10)
    1.15 +
    1.16 +#define PTYPE(attr)		((attr) & 0xff)
    1.17 +#define IS_ACT(attr)	((attr) & PATTR_ACT_BIT)
    1.18 +#define IS_PRIM(attr)	((attr) & PATTR_PRIM_BIT)
    1.19 +
    1.20 +#define BOOTSIG_OFFS	510
    1.21 +#define PTABLE_OFFS		0x1be
    1.22 +
    1.23 +#define BOOTSIG			0xaa55
    1.24 +
    1.25 +#define IS_MBR			(sidx == 0)
    1.26 +#define IS_FIRST_EBR	(!IS_MBR && (first_ebr_offs == 0))
    1.27 +
    1.28 +struct part_record {
    1.29 +	uint8_t stat;
    1.30 +	uint8_t first_head, first_cyl, first_sect;
    1.31 +	uint8_t type;
    1.32 +	uint8_t last_head, last_cyl, last_sect;
    1.33 +	uint32_t first_lba;
    1.34 +	uint32_t nsect_lba;
    1.35 +} __attribute__((packed));
    1.36 +
    1.37 +
    1.38 +static uint16_t bootsig(const char *sect);
    1.39 +
    1.40 +
    1.41 +struct partition *get_part_list(int devno)
    1.42 +{
    1.43 +	char *sect;
    1.44 +	struct partition *phead = 0, *ptail = 0;
    1.45 +	uint32_t sidx = 0;
    1.46 +	uint32_t first_ebr_offs = 0;
    1.47 +	int i, num_bootrec = 0;
    1.48 +
    1.49 +	sect = malloc(512);
    1.50 +	assert(sect);
    1.51 +
    1.52 +	do {
    1.53 +		int num_rec;
    1.54 +		struct part_record *prec;
    1.55 +
    1.56 +		if(IS_FIRST_EBR) {
    1.57 +			first_ebr_offs = sidx;
    1.58 +		}
    1.59 +
    1.60 +		if(ata_read_pio(devno, sidx, sect) == -1) {
    1.61 +			goto err;
    1.62 +		}
    1.63 +		if(bootsig(sect) != BOOTSIG) {
    1.64 +			printf("invalid/corrupted partition table, sector %lu has no magic\n", (unsigned long)sidx);
    1.65 +			goto err;
    1.66 +		}
    1.67 +		prec = (struct part_record*)(sect + PTABLE_OFFS);
    1.68 +
    1.69 +		/* MBR has 4 records, EBRs have 2 */
    1.70 +		num_rec = IS_MBR ? 4 : 2;
    1.71 +
    1.72 +		for(i=0; i<num_rec; i++) {
    1.73 +			struct partition *pnode;
    1.74 +
    1.75 +			/* ignore empty partitions in the MBR, stop if encountered in an EBR */
    1.76 +			if(prec[i].type == 0) {
    1.77 +				if(num_bootrec > 0) {
    1.78 +					sidx = 0;
    1.79 +					break;
    1.80 +				}
    1.81 +				continue;
    1.82 +			}
    1.83 +
    1.84 +			/* ignore extended partitions and setup sector index to read
    1.85 +			 * the next logical partition afterwards.
    1.86 +			 */
    1.87 +			if(prec[i].type == PTYPE_EXT || prec[i].type == PTYPE_EXT_LBA) {
    1.88 +				/* all EBR start fields are relative to the first EBR offset */
    1.89 +				sidx = first_ebr_offs + prec[i].first_lba;
    1.90 +				continue;
    1.91 +			}
    1.92 +
    1.93 +			pnode = malloc(sizeof *pnode);
    1.94 +			assert(pnode);
    1.95 +
    1.96 +			pnode->attr = prec[i].type;
    1.97 +
    1.98 +			if(prec[i].stat & 0x80) {
    1.99 +				pnode->attr |= PATTR_ACT_BIT;
   1.100 +			}
   1.101 +			if(IS_MBR) {
   1.102 +				pnode->attr |= PATTR_PRIM_BIT;
   1.103 +			}
   1.104 +			pnode->start_sect = prec[i].first_lba + first_ebr_offs;
   1.105 +			pnode->size_sect = prec[i].nsect_lba;
   1.106 +			pnode->next = 0;
   1.107 +
   1.108 +			/* append to the list */
   1.109 +			if(!phead) {
   1.110 +				phead = ptail = pnode;
   1.111 +			} else {
   1.112 +				ptail->next = pnode;
   1.113 +				ptail = pnode;
   1.114 +			}
   1.115 +		}
   1.116 +
   1.117 +		num_bootrec++;
   1.118 +	} while(sidx > 0);
   1.119 +
   1.120 +	free(sect);
   1.121 +	return phead;
   1.122 +
   1.123 +err:
   1.124 +	free(sect);
   1.125 +	while(phead) {
   1.126 +		void *tmp = phead;
   1.127 +		phead = phead->next;
   1.128 +		free(tmp);
   1.129 +	}
   1.130 +	return 0;
   1.131 +}
   1.132 +
   1.133 +void free_part_list(struct partition *plist)
   1.134 +{
   1.135 +	while(plist) {
   1.136 +		struct partition *tmp = plist;
   1.137 +		plist = plist->next;
   1.138 +		free(tmp);
   1.139 +	}
   1.140 +}
   1.141 +
   1.142 +int get_part_type(struct partition *p)
   1.143 +{
   1.144 +	return PTYPE(p->attr);
   1.145 +}
   1.146 +
   1.147 +
   1.148 +static uint16_t bootsig(const char *sect)
   1.149 +{
   1.150 +	return *(uint16_t*)(sect + BOOTSIG_OFFS);
   1.151 +}
   1.152 +