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 +