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_ */