kern

view 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 source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include "part.h"
5 #include "ata.h"
7 #define PTYPE_EXT 0x5
8 #define PTYPE_EXT_LBA 0xf
10 #define PATTR_ACT_BIT (1 << 9)
11 #define PATTR_PRIM_BIT (1 << 10)
13 #define PTYPE(attr) ((attr) & 0xff)
14 #define IS_ACT(attr) ((attr) & PATTR_ACT_BIT)
15 #define IS_PRIM(attr) ((attr) & PATTR_PRIM_BIT)
17 #define BOOTSIG_OFFS 510
18 #define PTABLE_OFFS 0x1be
20 #define BOOTSIG 0xaa55
22 #define IS_MBR (sidx == 0)
23 #define IS_FIRST_EBR (!IS_MBR && (first_ebr_offs == 0))
25 struct part_record {
26 uint8_t stat;
27 uint8_t first_head, first_cyl, first_sect;
28 uint8_t type;
29 uint8_t last_head, last_cyl, last_sect;
30 uint32_t first_lba;
31 uint32_t nsect_lba;
32 } __attribute__((packed));
35 static uint16_t bootsig(const char *sect);
38 struct partition *get_part_list(int devno)
39 {
40 char *sect;
41 struct partition *phead = 0, *ptail = 0;
42 uint32_t sidx = 0;
43 uint32_t first_ebr_offs = 0;
44 int i, num_bootrec = 0;
46 sect = malloc(512);
47 assert(sect);
49 do {
50 int num_rec;
51 struct part_record *prec;
53 if(IS_FIRST_EBR) {
54 first_ebr_offs = sidx;
55 }
57 if(ata_read_pio(devno, sidx, sect) == -1) {
58 goto err;
59 }
60 if(bootsig(sect) != BOOTSIG) {
61 printf("invalid/corrupted partition table, sector %lu has no magic\n", (unsigned long)sidx);
62 goto err;
63 }
64 prec = (struct part_record*)(sect + PTABLE_OFFS);
66 /* MBR has 4 records, EBRs have 2 */
67 num_rec = IS_MBR ? 4 : 2;
69 for(i=0; i<num_rec; i++) {
70 struct partition *pnode;
72 /* ignore empty partitions in the MBR, stop if encountered in an EBR */
73 if(prec[i].type == 0) {
74 if(num_bootrec > 0) {
75 sidx = 0;
76 break;
77 }
78 continue;
79 }
81 /* ignore extended partitions and setup sector index to read
82 * the next logical partition afterwards.
83 */
84 if(prec[i].type == PTYPE_EXT || prec[i].type == PTYPE_EXT_LBA) {
85 /* all EBR start fields are relative to the first EBR offset */
86 sidx = first_ebr_offs + prec[i].first_lba;
87 continue;
88 }
90 pnode = malloc(sizeof *pnode);
91 assert(pnode);
93 pnode->attr = prec[i].type;
95 if(prec[i].stat & 0x80) {
96 pnode->attr |= PATTR_ACT_BIT;
97 }
98 if(IS_MBR) {
99 pnode->attr |= PATTR_PRIM_BIT;
100 }
101 pnode->start_sect = prec[i].first_lba + first_ebr_offs;
102 pnode->size_sect = prec[i].nsect_lba;
103 pnode->next = 0;
105 /* append to the list */
106 if(!phead) {
107 phead = ptail = pnode;
108 } else {
109 ptail->next = pnode;
110 ptail = pnode;
111 }
112 }
114 num_bootrec++;
115 } while(sidx > 0);
117 free(sect);
118 return phead;
120 err:
121 free(sect);
122 while(phead) {
123 void *tmp = phead;
124 phead = phead->next;
125 free(tmp);
126 }
127 return 0;
128 }
130 void free_part_list(struct partition *plist)
131 {
132 while(plist) {
133 struct partition *tmp = plist;
134 plist = plist->next;
135 free(tmp);
136 }
137 }
139 int get_part_type(struct partition *p)
140 {
141 return PTYPE(p->attr);
142 }
145 static uint16_t bootsig(const char *sect)
146 {
147 return *(uint16_t*)(sect + BOOTSIG_OFFS);
148 }