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