kern

changeset 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 178d5a95e6de
children 2f555c81ae67
files .hgignore src/ata.c src/ata.h src/fs.c src/fs.h src/main.c src/part.c src/part.h
diffstat 8 files changed, 237 insertions(+), 7 deletions(-) [+]
line diff
     1.1 --- a/.hgignore	Wed Dec 07 17:10:37 2011 +0200
     1.2 +++ b/.hgignore	Thu Dec 08 13:34:47 2011 +0200
     1.3 @@ -3,3 +3,4 @@
     1.4  \.swp$
     1.5  ^kernel.elf$
     1.6  ^link.map$
     1.7 +^disk.img$
     2.1 --- a/src/ata.c	Wed Dec 07 17:10:37 2011 +0200
     2.2 +++ b/src/ata.c	Thu Dec 08 13:34:47 2011 +0200
     2.3 @@ -78,8 +78,7 @@
     2.4  #define MAX_IFACES		2
     2.5  #define MAX_DEV			(MAX_IFACES * 2)
     2.6  static struct device devices[MAX_DEV];
     2.7 -
     2.8 -static int use_irq;
     2.9 +static int ndev;
    2.10  
    2.11  /* This serves as a sync point for I/O. While the mutex is held,
    2.12   * some process is doing I/O and all the others must wait.
    2.13 @@ -93,28 +92,32 @@
    2.14  
    2.15  	interrupt(IRQ_TO_INTR(15), ata_intr);
    2.16  
    2.17 +	ndev = 0;
    2.18  	for(i=0; i<MAX_DEV; i++) {
    2.19  		int iface = i / MAX_IFACES;
    2.20  		int id = i % MAX_IFACES;
    2.21  
    2.22 -		if(identify(devices + i, iface, id) == -1) {
    2.23 -			devices[i].id = -1;
    2.24 +		if(identify(devices + ndev, iface, id) == 0) {
    2.25 +			ndev++;
    2.26  		}
    2.27  	}
    2.28 +}
    2.29  
    2.30 -	/* init code done, from now on use the irq sleep/wakeup mechanism */
    2.31 -	use_irq = 1;
    2.32 +int ata_num_devices(void)
    2.33 +{
    2.34 +	return ndev;
    2.35  }
    2.36  
    2.37  int ata_read_pio(int devno, uint64_t sect, void *buf)
    2.38  {
    2.39 -	int cmd, st, res = -1;
    2.40 +	int use_irq, cmd, st, res = -1;
    2.41  	uint32_t sect_low, sect_high;
    2.42  	struct device *dev = devices + devno;
    2.43  
    2.44  	if(dev->id == -1) {
    2.45  		return -1;
    2.46  	}
    2.47 +	use_irq = get_current_proc() != 0;
    2.48  
    2.49  	if(use_irq) {
    2.50  		/* wait for the interface to become available */
     3.1 --- a/src/ata.h	Wed Dec 07 17:10:37 2011 +0200
     3.2 +++ b/src/ata.h	Thu Dec 08 13:34:47 2011 +0200
     3.3 @@ -3,6 +3,8 @@
     3.4  
     3.5  void init_ata(void);
     3.6  
     3.7 +int ata_num_devices(void);
     3.8 +
     3.9  int ata_read_pio(int devno, uint64_t sect, void *buf);
    3.10  int ata_write_pio(int devno, uint64_t sect, void *buf);
    3.11  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/fs.c	Thu Dec 08 13:34:47 2011 +0200
     4.3 @@ -0,0 +1,46 @@
     4.4 +#include <stdio.h>
     4.5 +#include "fs.h"
     4.6 +#include "ata.h"
     4.7 +#include "part.h"
     4.8 +#include "panic.h"
     4.9 +
    4.10 +#define PART_TYPE	0xcc
    4.11 +
    4.12 +static int find_rootfs(int *dev, struct partition *part);
    4.13 +
    4.14 +/* root device & partition */
    4.15 +static int rdev;
    4.16 +static struct partition rpart;
    4.17 +
    4.18 +void init_fs(void)
    4.19 +{
    4.20 +	if(find_rootfs(&rdev, &rpart) == -1) {
    4.21 +		panic("can't find root filesystem\n");
    4.22 +	}
    4.23 +}
    4.24 +
    4.25 +static int find_rootfs(int *dev, struct partition *part)
    4.26 +{
    4.27 +	int i, num_dev, partid;
    4.28 +	struct partition *plist, *p;
    4.29 +
    4.30 +	num_dev = ata_num_devices();
    4.31 +	for(i=0; i<num_dev; i++) {
    4.32 +		plist = p = get_part_list(i);
    4.33 +
    4.34 +		partid = 0;
    4.35 +		while(p) {
    4.36 +			if(get_part_type(p) == PART_TYPE) {
    4.37 +				/* found it! */
    4.38 +				printf("using ata%dp%d\n", i, partid);
    4.39 +				*dev = i;
    4.40 +				*part = *p;
    4.41 +				return 0;
    4.42 +			}
    4.43 +			p = p->next;
    4.44 +			partid++;
    4.45 +		}
    4.46 +		free_part_list(plist);
    4.47 +	}
    4.48 +	return -1;
    4.49 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/fs.h	Thu Dec 08 13:34:47 2011 +0200
     5.3 @@ -0,0 +1,6 @@
     5.4 +#ifndef FS_H_
     5.5 +#define FS_H_
     5.6 +
     5.7 +void init_fs(void);
     5.8 +
     5.9 +#endif	/* FS_H_ */
     6.1 --- a/src/main.c	Wed Dec 07 17:10:37 2011 +0200
     6.2 +++ b/src/main.c	Thu Dec 08 13:34:47 2011 +0200
     6.3 @@ -6,6 +6,7 @@
     6.4  #include "segm.h"
     6.5  #include "intr.h"
     6.6  #include "ata.h"
     6.7 +#include "fs.h"
     6.8  #include "rtc.h"
     6.9  #include "timer.h"
    6.10  #include "mem.h"
    6.11 @@ -38,6 +39,8 @@
    6.12  
    6.13  	/* initialize ATA disks */
    6.14  	init_ata();
    6.15 +	/* initialize the filesystem */
    6.16 +	init_fs();
    6.17  
    6.18  	/* initialize the timer and RTC */
    6.19  	init_timer();
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/part.c	Thu Dec 08 13:34:47 2011 +0200
     7.3 @@ -0,0 +1,149 @@
     7.4 +#include <stdio.h>
     7.5 +#include <stdlib.h>
     7.6 +#include <assert.h>
     7.7 +#include "part.h"
     7.8 +#include "ata.h"
     7.9 +
    7.10 +#define PTYPE_EXT		0x5
    7.11 +#define PTYPE_EXT_LBA	0xf
    7.12 +
    7.13 +#define PATTR_ACT_BIT	(1 << 9)
    7.14 +#define PATTR_PRIM_BIT	(1 << 10)
    7.15 +
    7.16 +#define PTYPE(attr)		((attr) & 0xff)
    7.17 +#define IS_ACT(attr)	((attr) & PATTR_ACT_BIT)
    7.18 +#define IS_PRIM(attr)	((attr) & PATTR_PRIM_BIT)
    7.19 +
    7.20 +#define BOOTSIG_OFFS	510
    7.21 +#define PTABLE_OFFS		0x1be
    7.22 +
    7.23 +#define BOOTSIG			0xaa55
    7.24 +
    7.25 +#define IS_MBR			(sidx == 0)
    7.26 +#define IS_FIRST_EBR	(!IS_MBR && (first_ebr_offs == 0))
    7.27 +
    7.28 +struct part_record {
    7.29 +	uint8_t stat;
    7.30 +	uint8_t first_head, first_cyl, first_sect;
    7.31 +	uint8_t type;
    7.32 +	uint8_t last_head, last_cyl, last_sect;
    7.33 +	uint32_t first_lba;
    7.34 +	uint32_t nsect_lba;
    7.35 +} __attribute__((packed));
    7.36 +
    7.37 +
    7.38 +static uint16_t bootsig(const char *sect);
    7.39 +
    7.40 +
    7.41 +struct partition *get_part_list(int devno)
    7.42 +{
    7.43 +	char *sect;
    7.44 +	struct partition *phead = 0, *ptail = 0;
    7.45 +	uint32_t sidx = 0;
    7.46 +	uint32_t first_ebr_offs = 0;
    7.47 +	int i, num_bootrec = 0;
    7.48 +
    7.49 +	sect = malloc(512);
    7.50 +	assert(sect);
    7.51 +
    7.52 +	do {
    7.53 +		int num_rec;
    7.54 +		struct part_record *prec;
    7.55 +
    7.56 +		if(IS_FIRST_EBR) {
    7.57 +			first_ebr_offs = sidx;
    7.58 +		}
    7.59 +
    7.60 +		if(ata_read_pio(devno, sidx, sect) == -1) {
    7.61 +			goto err;
    7.62 +		}
    7.63 +		if(bootsig(sect) != BOOTSIG) {
    7.64 +			printf("invalid/corrupted partition table, sector %lu has no magic\n", (unsigned long)sidx);
    7.65 +			goto err;
    7.66 +		}
    7.67 +		prec = (struct part_record*)(sect + PTABLE_OFFS);
    7.68 +
    7.69 +		/* MBR has 4 records, EBRs have 2 */
    7.70 +		num_rec = IS_MBR ? 4 : 2;
    7.71 +
    7.72 +		for(i=0; i<num_rec; i++) {
    7.73 +			struct partition *pnode;
    7.74 +
    7.75 +			/* ignore empty partitions in the MBR, stop if encountered in an EBR */
    7.76 +			if(prec[i].type == 0) {
    7.77 +				if(num_bootrec > 0) {
    7.78 +					sidx = 0;
    7.79 +					break;
    7.80 +				}
    7.81 +				continue;
    7.82 +			}
    7.83 +
    7.84 +			/* ignore extended partitions and setup sector index to read
    7.85 +			 * the next logical partition afterwards.
    7.86 +			 */
    7.87 +			if(prec[i].type == PTYPE_EXT || prec[i].type == PTYPE_EXT_LBA) {
    7.88 +				/* all EBR start fields are relative to the first EBR offset */
    7.89 +				sidx = first_ebr_offs + prec[i].first_lba;
    7.90 +				continue;
    7.91 +			}
    7.92 +
    7.93 +			pnode = malloc(sizeof *pnode);
    7.94 +			assert(pnode);
    7.95 +
    7.96 +			pnode->attr = prec[i].type;
    7.97 +
    7.98 +			if(prec[i].stat & 0x80) {
    7.99 +				pnode->attr |= PATTR_ACT_BIT;
   7.100 +			}
   7.101 +			if(IS_MBR) {
   7.102 +				pnode->attr |= PATTR_PRIM_BIT;
   7.103 +			}
   7.104 +			pnode->start_sect = prec[i].first_lba + first_ebr_offs;
   7.105 +			pnode->size_sect = prec[i].nsect_lba;
   7.106 +			pnode->next = 0;
   7.107 +
   7.108 +			/* append to the list */
   7.109 +			if(!phead) {
   7.110 +				phead = ptail = pnode;
   7.111 +			} else {
   7.112 +				ptail->next = pnode;
   7.113 +				ptail = pnode;
   7.114 +			}
   7.115 +		}
   7.116 +
   7.117 +		num_bootrec++;
   7.118 +	} while(sidx > 0);
   7.119 +
   7.120 +	free(sect);
   7.121 +	return phead;
   7.122 +
   7.123 +err:
   7.124 +	free(sect);
   7.125 +	while(phead) {
   7.126 +		void *tmp = phead;
   7.127 +		phead = phead->next;
   7.128 +		free(tmp);
   7.129 +	}
   7.130 +	return 0;
   7.131 +}
   7.132 +
   7.133 +void free_part_list(struct partition *plist)
   7.134 +{
   7.135 +	while(plist) {
   7.136 +		struct partition *tmp = plist;
   7.137 +		plist = plist->next;
   7.138 +		free(tmp);
   7.139 +	}
   7.140 +}
   7.141 +
   7.142 +int get_part_type(struct partition *p)
   7.143 +{
   7.144 +	return PTYPE(p->attr);
   7.145 +}
   7.146 +
   7.147 +
   7.148 +static uint16_t bootsig(const char *sect)
   7.149 +{
   7.150 +	return *(uint16_t*)(sect + BOOTSIG_OFFS);
   7.151 +}
   7.152 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/part.h	Thu Dec 08 13:34:47 2011 +0200
     8.3 @@ -0,0 +1,20 @@
     8.4 +#ifndef PART_H_
     8.5 +#define PART_H_
     8.6 +
     8.7 +#include <inttypes.h>
     8.8 +
     8.9 +struct partition {
    8.10 +	uint32_t start_sect;
    8.11 +	size_t size_sect;
    8.12 +
    8.13 +	unsigned int attr;
    8.14 +
    8.15 +	struct partition *next;
    8.16 +};
    8.17 +
    8.18 +struct partition *get_part_list(int devno);
    8.19 +void free_part_list(struct partition *plist);
    8.20 +
    8.21 +int get_part_type(struct partition *p);
    8.22 +
    8.23 +#endif	/* PART_H_ */