nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "ptype.h" nuclear@0: nuclear@0: #define PATTR_ACT_BIT (1 << 9) nuclear@0: #define PATTR_PRIM_BIT (1 << 10) nuclear@0: nuclear@0: #define PTYPE(attr) ((attr) & 0xff) nuclear@0: #define IS_ACT(attr) ((attr) & PATTR_ACT_BIT) nuclear@0: #define IS_PRIM(attr) ((attr) & PATTR_PRIM_BIT) nuclear@0: nuclear@0: struct partition { nuclear@0: uint32_t start_sect; nuclear@0: size_t size_sect; nuclear@0: nuclear@0: unsigned int attr; nuclear@0: nuclear@0: struct partition *next; nuclear@0: }; nuclear@0: nuclear@0: struct part_record { nuclear@0: uint8_t stat; nuclear@0: uint8_t first_head, first_cyl, first_sect; nuclear@0: uint8_t type; nuclear@0: uint8_t last_head, last_cyl, last_sect; nuclear@0: uint32_t first_lba; nuclear@0: uint32_t nsect_lba; nuclear@0: } __attribute__((packed)); nuclear@0: nuclear@0: static void print_parlist(struct partition *plist); nuclear@0: nuclear@0: static struct partition *load_parlist(void); nuclear@0: static uint16_t bootsig(const char *sect); nuclear@0: static int read_sector(void *buf, uint32_t sector); nuclear@0: static const char *printsz(unsigned int sz); nuclear@0: static const char *ptype_name(int type); nuclear@0: nuclear@0: int bdev; nuclear@0: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@0: struct partition *plist; nuclear@0: nuclear@0: if(argc != 2) { nuclear@0: fprintf(stderr, "usage: %s \n", argv[0]); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: if((bdev = open(argv[1], O_RDONLY)) == -1) { nuclear@0: fprintf(stderr, "failed to open %s: %s\n", argv[1], strerror(errno)); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: if((plist = load_parlist())) { nuclear@0: printf("partitions:\n"); nuclear@0: print_parlist(plist); nuclear@0: } nuclear@0: nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static void print_parlist(struct partition *plist) nuclear@0: { nuclear@0: int idx = 0; nuclear@0: nuclear@0: while(plist) { nuclear@0: printf("%d%c ", idx++, IS_ACT(plist->attr) ? '*' : ' '); nuclear@0: printf("(%s) %-20s ", IS_PRIM(plist->attr) ? "pri" : "log", ptype_name(PTYPE(plist->attr))); nuclear@0: printf("start: %-10lu ", (unsigned long)plist->start_sect); nuclear@0: printf("size: %-10lu [%s]\n", (unsigned long)plist->size_sect, printsz(plist->size_sect)); nuclear@0: plist = plist->next; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: nuclear@0: #define BOOTSIG_OFFS 510 nuclear@0: #define PTABLE_OFFS 0x1be nuclear@0: nuclear@0: #define BOOTSIG 0xaa55 nuclear@0: nuclear@0: #define IS_MBR (sidx == 0) nuclear@0: #define IS_FIRST_EBR (!IS_MBR && (first_ebr_offs == 0)) nuclear@0: static struct partition *load_parlist(void) nuclear@0: { nuclear@0: char *sect; nuclear@0: struct partition *phead = 0, *ptail = 0; nuclear@0: uint32_t sidx = 0; nuclear@0: uint32_t first_ebr_offs = 0; nuclear@0: int i, num_bootrec = 0; nuclear@0: nuclear@0: if(!(sect = malloc(512))) { nuclear@0: perror("failed to allocate sector buffer"); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: nuclear@0: do { nuclear@0: int num_rec; nuclear@0: struct part_record *prec; nuclear@0: nuclear@0: if(IS_FIRST_EBR) { nuclear@0: first_ebr_offs = sidx; nuclear@0: } nuclear@0: nuclear@0: if(read_sector(sect, sidx) == -1) { nuclear@0: goto err; nuclear@0: } nuclear@0: if(bootsig(sect) != BOOTSIG) { nuclear@0: fprintf(stderr, "invalid/corrupted partition table, sector %lu has no magic\n", (unsigned long)sidx); nuclear@0: goto err; nuclear@0: } nuclear@0: prec = (struct part_record*)(sect + PTABLE_OFFS); nuclear@0: nuclear@0: /* MBR has 4 records, EBRs have 2 */ nuclear@0: num_rec = IS_MBR ? 4 : 2; nuclear@0: nuclear@0: for(i=0; i 0) { nuclear@0: sidx = 0; nuclear@0: break; nuclear@0: } nuclear@0: continue; nuclear@0: } nuclear@0: nuclear@0: /* ignore extended partitions and setup sector index to read nuclear@0: * the next logical partition afterwards. nuclear@0: */ nuclear@0: if(prec[i].type == PTYPE_EXT || prec[i].type == PTYPE_EXT_LBA) { nuclear@0: /* all EBR start fields are relative to the first EBR offset */ nuclear@0: sidx = first_ebr_offs + prec[i].first_lba; nuclear@0: continue; nuclear@0: } nuclear@0: nuclear@0: if(!(pnode = malloc(sizeof *pnode))) { nuclear@0: perror("failed to allocate partition list node"); nuclear@0: goto err; nuclear@0: } nuclear@0: nuclear@0: pnode->attr = prec[i].type; nuclear@0: nuclear@0: if(prec[i].stat & 0x80) { nuclear@0: pnode->attr |= PATTR_ACT_BIT; nuclear@0: } nuclear@0: if(IS_MBR) { nuclear@0: pnode->attr |= PATTR_PRIM_BIT; nuclear@0: } nuclear@0: pnode->start_sect = prec[i].first_lba + first_ebr_offs; nuclear@0: pnode->size_sect = prec[i].nsect_lba; nuclear@0: pnode->next = 0; nuclear@0: nuclear@0: /* append to the list */ nuclear@0: if(!phead) { nuclear@0: phead = ptail = pnode; nuclear@0: } else { nuclear@0: ptail->next = pnode; nuclear@0: ptail = pnode; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: num_bootrec++; nuclear@0: } while(sidx > 0); nuclear@0: nuclear@0: free(sect); nuclear@0: return phead; nuclear@0: nuclear@0: err: nuclear@0: free(sect); nuclear@0: while(phead) { nuclear@0: void *tmp = phead; nuclear@0: phead = phead->next; nuclear@0: free(tmp); nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static uint16_t bootsig(const char *sect) nuclear@0: { nuclear@0: return *(uint16_t*)(sect + BOOTSIG_OFFS); nuclear@0: } nuclear@0: nuclear@0: static int read_sector(void *buf, uint32_t sector) nuclear@0: { nuclear@0: if(lseek(bdev, (off_t)sector * 512, SEEK_SET) == -1) { nuclear@0: fprintf(stderr, "read_sector: failed to seek: %s\n", strerror(errno)); nuclear@0: return -1; nuclear@0: } nuclear@0: if(read(bdev, buf, 512) != 512) { nuclear@0: fprintf(stderr, "failed to read sector %lu: %s\n", (unsigned long)sector, strerror(errno)); nuclear@0: return -1; nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: const char *printsz(unsigned int sz) nuclear@0: { nuclear@0: int i = 0; nuclear@0: const char *suffix[] = { "kb", "mb", "gb", "tb", "pb", 0 }; nuclear@0: static char buf[512]; nuclear@0: nuclear@0: while(sz > 1024 && suffix[i + 1]) { nuclear@0: sz /= 1024; nuclear@0: i++; nuclear@0: } nuclear@0: nuclear@0: sprintf(buf, "%u %s", sz, suffix[i]); nuclear@0: return buf; nuclear@0: } nuclear@0: nuclear@0: static const char *ptype_name(int type) nuclear@0: { nuclear@0: int i; nuclear@0: nuclear@0: for(i=0; i