# HG changeset patch # User John Tsiombikas # Date 1323344087 -7200 # Node ID a398bf73fe93d2ba9e8d6de8e1992294cc159b0c # Parent 178d5a95e6de1afe1d61f28bc79c545b3f8d8523 - added the partition table parsing code - starting with the filesystem diff -r 178d5a95e6de -r a398bf73fe93 .hgignore --- a/.hgignore Wed Dec 07 17:10:37 2011 +0200 +++ b/.hgignore Thu Dec 08 13:34:47 2011 +0200 @@ -3,3 +3,4 @@ \.swp$ ^kernel.elf$ ^link.map$ +^disk.img$ diff -r 178d5a95e6de -r a398bf73fe93 src/ata.c --- a/src/ata.c Wed Dec 07 17:10:37 2011 +0200 +++ b/src/ata.c Thu Dec 08 13:34:47 2011 +0200 @@ -78,8 +78,7 @@ #define MAX_IFACES 2 #define MAX_DEV (MAX_IFACES * 2) static struct device devices[MAX_DEV]; - -static int use_irq; +static int ndev; /* This serves as a sync point for I/O. While the mutex is held, * some process is doing I/O and all the others must wait. @@ -93,28 +92,32 @@ interrupt(IRQ_TO_INTR(15), ata_intr); + ndev = 0; for(i=0; iid == -1) { return -1; } + use_irq = get_current_proc() != 0; if(use_irq) { /* wait for the interface to become available */ diff -r 178d5a95e6de -r a398bf73fe93 src/ata.h --- a/src/ata.h Wed Dec 07 17:10:37 2011 +0200 +++ b/src/ata.h Thu Dec 08 13:34:47 2011 +0200 @@ -3,6 +3,8 @@ void init_ata(void); +int ata_num_devices(void); + int ata_read_pio(int devno, uint64_t sect, void *buf); int ata_write_pio(int devno, uint64_t sect, void *buf); diff -r 178d5a95e6de -r a398bf73fe93 src/fs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fs.c Thu Dec 08 13:34:47 2011 +0200 @@ -0,0 +1,46 @@ +#include +#include "fs.h" +#include "ata.h" +#include "part.h" +#include "panic.h" + +#define PART_TYPE 0xcc + +static int find_rootfs(int *dev, struct partition *part); + +/* root device & partition */ +static int rdev; +static struct partition rpart; + +void init_fs(void) +{ + if(find_rootfs(&rdev, &rpart) == -1) { + panic("can't find root filesystem\n"); + } +} + +static int find_rootfs(int *dev, struct partition *part) +{ + int i, num_dev, partid; + struct partition *plist, *p; + + num_dev = ata_num_devices(); + for(i=0; inext; + partid++; + } + free_part_list(plist); + } + return -1; +} diff -r 178d5a95e6de -r a398bf73fe93 src/fs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fs.h Thu Dec 08 13:34:47 2011 +0200 @@ -0,0 +1,6 @@ +#ifndef FS_H_ +#define FS_H_ + +void init_fs(void); + +#endif /* FS_H_ */ diff -r 178d5a95e6de -r a398bf73fe93 src/main.c --- a/src/main.c Wed Dec 07 17:10:37 2011 +0200 +++ b/src/main.c Thu Dec 08 13:34:47 2011 +0200 @@ -6,6 +6,7 @@ #include "segm.h" #include "intr.h" #include "ata.h" +#include "fs.h" #include "rtc.h" #include "timer.h" #include "mem.h" @@ -38,6 +39,8 @@ /* initialize ATA disks */ init_ata(); + /* initialize the filesystem */ + init_fs(); /* initialize the timer and RTC */ init_timer(); diff -r 178d5a95e6de -r a398bf73fe93 src/part.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/part.c Thu Dec 08 13:34:47 2011 +0200 @@ -0,0 +1,149 @@ +#include +#include +#include +#include "part.h" +#include "ata.h" + +#define PTYPE_EXT 0x5 +#define PTYPE_EXT_LBA 0xf + +#define PATTR_ACT_BIT (1 << 9) +#define PATTR_PRIM_BIT (1 << 10) + +#define PTYPE(attr) ((attr) & 0xff) +#define IS_ACT(attr) ((attr) & PATTR_ACT_BIT) +#define IS_PRIM(attr) ((attr) & PATTR_PRIM_BIT) + +#define BOOTSIG_OFFS 510 +#define PTABLE_OFFS 0x1be + +#define BOOTSIG 0xaa55 + +#define IS_MBR (sidx == 0) +#define IS_FIRST_EBR (!IS_MBR && (first_ebr_offs == 0)) + +struct part_record { + uint8_t stat; + uint8_t first_head, first_cyl, first_sect; + uint8_t type; + uint8_t last_head, last_cyl, last_sect; + uint32_t first_lba; + uint32_t nsect_lba; +} __attribute__((packed)); + + +static uint16_t bootsig(const char *sect); + + +struct partition *get_part_list(int devno) +{ + char *sect; + struct partition *phead = 0, *ptail = 0; + uint32_t sidx = 0; + uint32_t first_ebr_offs = 0; + int i, num_bootrec = 0; + + sect = malloc(512); + assert(sect); + + do { + int num_rec; + struct part_record *prec; + + if(IS_FIRST_EBR) { + first_ebr_offs = sidx; + } + + if(ata_read_pio(devno, sidx, sect) == -1) { + goto err; + } + if(bootsig(sect) != BOOTSIG) { + printf("invalid/corrupted partition table, sector %lu has no magic\n", (unsigned long)sidx); + goto err; + } + prec = (struct part_record*)(sect + PTABLE_OFFS); + + /* MBR has 4 records, EBRs have 2 */ + num_rec = IS_MBR ? 4 : 2; + + for(i=0; i 0) { + sidx = 0; + break; + } + continue; + } + + /* ignore extended partitions and setup sector index to read + * the next logical partition afterwards. + */ + if(prec[i].type == PTYPE_EXT || prec[i].type == PTYPE_EXT_LBA) { + /* all EBR start fields are relative to the first EBR offset */ + sidx = first_ebr_offs + prec[i].first_lba; + continue; + } + + pnode = malloc(sizeof *pnode); + assert(pnode); + + pnode->attr = prec[i].type; + + if(prec[i].stat & 0x80) { + pnode->attr |= PATTR_ACT_BIT; + } + if(IS_MBR) { + pnode->attr |= PATTR_PRIM_BIT; + } + pnode->start_sect = prec[i].first_lba + first_ebr_offs; + pnode->size_sect = prec[i].nsect_lba; + pnode->next = 0; + + /* append to the list */ + if(!phead) { + phead = ptail = pnode; + } else { + ptail->next = pnode; + ptail = pnode; + } + } + + num_bootrec++; + } while(sidx > 0); + + free(sect); + return phead; + +err: + free(sect); + while(phead) { + void *tmp = phead; + phead = phead->next; + free(tmp); + } + return 0; +} + +void free_part_list(struct partition *plist) +{ + while(plist) { + struct partition *tmp = plist; + plist = plist->next; + free(tmp); + } +} + +int get_part_type(struct partition *p) +{ + return PTYPE(p->attr); +} + + +static uint16_t bootsig(const char *sect) +{ + return *(uint16_t*)(sect + BOOTSIG_OFFS); +} + diff -r 178d5a95e6de -r a398bf73fe93 src/part.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/part.h Thu Dec 08 13:34:47 2011 +0200 @@ -0,0 +1,20 @@ +#ifndef PART_H_ +#define PART_H_ + +#include + +struct partition { + uint32_t start_sect; + size_t size_sect; + + unsigned int attr; + + struct partition *next; +}; + +struct partition *get_part_list(int devno); +void free_part_list(struct partition *plist); + +int get_part_type(struct partition *p); + +#endif /* PART_H_ */