nuclear@88: #include nuclear@88: #include nuclear@88: #include nuclear@88: #include "part.h" nuclear@88: #include "ata.h" nuclear@88: nuclear@88: #define PTYPE_EXT 0x5 nuclear@88: #define PTYPE_EXT_LBA 0xf nuclear@88: nuclear@88: #define PATTR_ACT_BIT (1 << 9) nuclear@88: #define PATTR_PRIM_BIT (1 << 10) nuclear@88: nuclear@88: #define PTYPE(attr) ((attr) & 0xff) nuclear@88: #define IS_ACT(attr) ((attr) & PATTR_ACT_BIT) nuclear@88: #define IS_PRIM(attr) ((attr) & PATTR_PRIM_BIT) nuclear@88: nuclear@88: #define BOOTSIG_OFFS 510 nuclear@88: #define PTABLE_OFFS 0x1be nuclear@88: nuclear@88: #define BOOTSIG 0xaa55 nuclear@88: nuclear@88: #define IS_MBR (sidx == 0) nuclear@88: #define IS_FIRST_EBR (!IS_MBR && (first_ebr_offs == 0)) nuclear@88: nuclear@88: struct part_record { nuclear@88: uint8_t stat; nuclear@88: uint8_t first_head, first_cyl, first_sect; nuclear@88: uint8_t type; nuclear@88: uint8_t last_head, last_cyl, last_sect; nuclear@88: uint32_t first_lba; nuclear@88: uint32_t nsect_lba; nuclear@88: } __attribute__((packed)); nuclear@88: nuclear@88: nuclear@88: static uint16_t bootsig(const char *sect); nuclear@88: nuclear@88: nuclear@88: struct partition *get_part_list(int devno) nuclear@88: { nuclear@88: char *sect; nuclear@88: struct partition *phead = 0, *ptail = 0; nuclear@88: uint32_t sidx = 0; nuclear@88: uint32_t first_ebr_offs = 0; nuclear@88: int i, num_bootrec = 0; nuclear@88: nuclear@88: sect = malloc(512); nuclear@88: assert(sect); nuclear@88: nuclear@88: do { nuclear@88: int num_rec; nuclear@88: struct part_record *prec; nuclear@88: nuclear@88: if(IS_FIRST_EBR) { nuclear@88: first_ebr_offs = sidx; nuclear@88: } nuclear@88: nuclear@88: if(ata_read_pio(devno, sidx, sect) == -1) { nuclear@88: goto err; nuclear@88: } nuclear@88: if(bootsig(sect) != BOOTSIG) { nuclear@88: printf("invalid/corrupted partition table, sector %lu has no magic\n", (unsigned long)sidx); nuclear@88: goto err; nuclear@88: } nuclear@88: prec = (struct part_record*)(sect + PTABLE_OFFS); nuclear@88: nuclear@88: /* MBR has 4 records, EBRs have 2 */ nuclear@88: num_rec = IS_MBR ? 4 : 2; nuclear@88: nuclear@88: for(i=0; i 0) { nuclear@88: sidx = 0; nuclear@88: break; nuclear@88: } nuclear@88: continue; nuclear@88: } nuclear@88: nuclear@88: /* ignore extended partitions and setup sector index to read nuclear@88: * the next logical partition afterwards. nuclear@88: */ nuclear@88: if(prec[i].type == PTYPE_EXT || prec[i].type == PTYPE_EXT_LBA) { nuclear@88: /* all EBR start fields are relative to the first EBR offset */ nuclear@88: sidx = first_ebr_offs + prec[i].first_lba; nuclear@88: continue; nuclear@88: } nuclear@88: nuclear@88: pnode = malloc(sizeof *pnode); nuclear@88: assert(pnode); nuclear@88: nuclear@88: pnode->attr = prec[i].type; nuclear@88: nuclear@88: if(prec[i].stat & 0x80) { nuclear@88: pnode->attr |= PATTR_ACT_BIT; nuclear@88: } nuclear@88: if(IS_MBR) { nuclear@88: pnode->attr |= PATTR_PRIM_BIT; nuclear@88: } nuclear@88: pnode->start_sect = prec[i].first_lba + first_ebr_offs; nuclear@88: pnode->size_sect = prec[i].nsect_lba; nuclear@88: pnode->next = 0; nuclear@88: nuclear@88: /* append to the list */ nuclear@88: if(!phead) { nuclear@88: phead = ptail = pnode; nuclear@88: } else { nuclear@88: ptail->next = pnode; nuclear@88: ptail = pnode; nuclear@88: } nuclear@88: } nuclear@88: nuclear@88: num_bootrec++; nuclear@88: } while(sidx > 0); nuclear@88: nuclear@88: free(sect); nuclear@88: return phead; nuclear@88: nuclear@88: err: nuclear@88: free(sect); nuclear@88: while(phead) { nuclear@88: void *tmp = phead; nuclear@88: phead = phead->next; nuclear@88: free(tmp); nuclear@88: } nuclear@88: return 0; nuclear@88: } nuclear@88: nuclear@88: void free_part_list(struct partition *plist) nuclear@88: { nuclear@88: while(plist) { nuclear@88: struct partition *tmp = plist; nuclear@88: plist = plist->next; nuclear@88: free(tmp); nuclear@88: } nuclear@88: } nuclear@88: nuclear@88: int get_part_type(struct partition *p) nuclear@88: { nuclear@88: return PTYPE(p->attr); nuclear@88: } nuclear@88: nuclear@88: nuclear@88: static uint16_t bootsig(const char *sect) nuclear@88: { nuclear@88: return *(uint16_t*)(sect + BOOTSIG_OFFS); nuclear@88: } nuclear@88: