kern

annotate src/part.c @ 97:8717eb590727

ok stopping with the filesystem to manage to write the article in time
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 17 Dec 2011 14:09:17 +0200
parents
children
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