static void partition_generate_gpt_entry(struct gpt_ent* gpt_entry, const partition_t *partition, const disk_t *disk_car) { guid_cpy(&gpt_entry->ent_type, &partition->part_type_gpt); gpt_entry->ent_lba_start=le64(partition->part_offset / disk_car->sector_size); gpt_entry->ent_lba_end=le64((partition->part_offset + partition->part_size - 1) / disk_car->sector_size); str2UCSle((uint16_t *)&gpt_entry->ent_name, partition->partname, sizeof(gpt_entry->ent_name)/2); if(guid_cmp(partition->part_uuid, GPT_ENT_TYPE_UNUSED)!=0) guid_cpy(&gpt_entry->ent_uuid, &partition->part_uuid); else efi_generate_uuid(&gpt_entry->ent_uuid); gpt_entry->ent_attr=le64(0); /* May need fixing */ }
int recover_rfs(disk_t *disk_car, const struct reiserfs_super_block *sb,partition_t *partition,const int verbose, const int dump_ind) { const struct reiser4_master_sb *sb4=(const struct reiser4_master_sb *)sb; if(test_rfs(disk_car, sb, partition, verbose)==0) { if(verbose>0 || dump_ind!=0) { log_info("\nrecover_rfs\n"); log_info("block_count=%u\n",(unsigned int)le32(sb->s_block_count)); log_info("block_size=%u\n",le16(sb->s_blocksize)); if(dump_ind!=0) { dump_log(sb,DEFAULT_SECTOR_SIZE); } } partition->part_size = (uint64_t)le32(sb->s_block_count) * le16(sb->s_blocksize); partition->part_type_i386 = P_LINUX; partition->part_type_mac= PMAC_LINUX; partition->part_type_sun= PSUN_LINUX; partition->part_type_gpt=GPT_ENT_TYPE_LINUX_DATA; guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb->s_uuid); set_rfs_info(sb, partition); return 0; } if(test_rfs4(disk_car, sb4, partition, verbose)==0) { const struct format40_super *fmt40_super=(const struct format40_super *)((const char*)sb4+le16(sb4->blocksize)); if(verbose>0 || dump_ind!=0) { log_info("\nrecover_rfs\n"); log_info("block_count=%lu\n",(unsigned long int)le64(fmt40_super->sb_block_count)); log_info("block_size=%u\n",le16(sb4->blocksize)); if(dump_ind!=0) { dump_log(sb,DEFAULT_SECTOR_SIZE); } } partition->part_size = (uint64_t)le64(fmt40_super->sb_block_count) * le16(sb4->blocksize); partition->part_type_i386 = P_LINUX; partition->part_type_mac= PMAC_LINUX; partition->part_type_sun= PSUN_LINUX; partition->part_type_gpt=GPT_ENT_TYPE_LINUX_DATA; guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb4->uuid); set_rfs4_info(sb4, partition); return 0; } return 1; }
/* Primary superblock is at 0x8000 */ int recover_JFS(disk_t *disk_car, const struct jfs_superblock *sb,partition_t *partition,const int verbose, const int dump_ind) { if(test_JFS(disk_car, sb, partition, dump_ind)!=0) return 1; set_JFS_info(sb, partition); partition->part_type_i386=P_LINUX; partition->part_type_sun=PSUN_LINUX; partition->part_type_mac=PMAC_LINUX; partition->part_type_gpt=GPT_ENT_TYPE_LINUX_DATA; partition->part_size=(uint64_t)le32(sb->s_pbsize) * le64(sb->s_size) + le32(sb->s_bsize) * (le24(sb->s_fsckpxd.len)+le24(sb->s_logpxd.len)); partition->sborg_offset=64*512; partition->sb_size=JFS_SUPERBLOCK_SIZE; partition->sb_offset=0; guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb->s_uuid); if(verbose>0) { log_info("\n"); log_info("recover_JFS: s_blocksize=%u\n",partition->blocksize); log_info("recover_JFS: s_size %lu\n",(long unsigned int)le64(sb->s_size)); log_info("recover_JFS: s_fsckpxd.len:%d\n", (int)le24(sb->s_fsckpxd.len)); log_info("recover_JFS: s_logpxd.len:%d\n", (int)le24(sb->s_logpxd.len)); log_info("recover_JFS: part_size %lu\n",(long unsigned)(partition->part_size/disk_car->sector_size)); } return 0; }
int recover_LVM(disk_t *disk_car, const pv_disk_t *pv,partition_t *partition,const int verbose, const int dump_ind) { if(test_LVM(disk_car,pv,partition,verbose,dump_ind)!=0) return 1; set_LVM_info(partition); partition->part_type_i386=P_LVM; partition->part_type_sun=PSUN_LVM; partition->part_type_gpt=GPT_ENT_TYPE_LINUX_LVM; partition->part_size=(uint64_t)le32(pv->pv_size)*disk_car->sector_size; /* pv_uuid is bigger than part_uuid */ guid_cpy(&partition->part_uuid, (const efi_guid_t *)&pv->pv_uuid); if(verbose>0) { log_info("part_size %lu\n",(long unsigned)(partition->part_size/disk_car->sector_size)); } return 0; }
int recover_xfs(disk_t *disk_car, const struct xfs_sb *sb,partition_t *partition,const int verbose, const int dump_ind) { if(test_xfs(disk_car, sb, partition, verbose)!=0) return 1; if(verbose>0 || dump_ind!=0) { log_info("\nrecover_xfs\n"); if(dump_ind!=0) { dump_log(sb,DEFAULT_SECTOR_SIZE); } } set_xfs_info(sb, partition); partition->part_size = (uint64_t)be64(sb->sb_dblocks) * be32(sb->sb_blocksize); partition->part_type_i386=P_LINUX; partition->part_type_mac=PMAC_LINUX; partition->part_type_sun=PSUN_LINUX; partition->part_type_gpt=GPT_ENT_TYPE_LINUX_DATA; guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb->sb_uuid); return 0; }
void partition_reset(partition_t *partition, const arch_fnct_t *arch) { /* partition->lba=0; Don't reset lba, used by search_part */ partition->part_size=(uint64_t)0; partition->sborg_offset=0; partition->sb_offset=0; partition->sb_size=0; partition->blocksize=0; partition->part_type_i386=P_NO_OS; partition->part_type_sun=PSUN_UNK; partition->part_type_mac=PMAC_UNK; partition->part_type_xbox=PXBOX_UNK; partition->part_type_gpt=GPT_ENT_TYPE_UNUSED; guid_cpy(&partition->part_uuid, &GPT_ENT_TYPE_UNUSED); partition->upart_type=UP_UNK; partition->status=STATUS_DELETED; partition->order=NO_ORDER; partition->errcode=BAD_NOERR; partition->fsname[0]='\0'; partition->partname[0]='\0'; partition->info[0]='\0'; partition->arch=arch; }
/* Primary superblock is at 1024 (SUPERBLOCK_OFFSET) Group 0 begin at s_first_data_block */ int recover_btrfs(disk_t *disk, const struct btrfs_super_block *sb, partition_t *partition, const int verbose, const int dump_ind) { if(test_btrfs(sb)!=0) return 1; if(dump_ind!=0) { if(partition!=NULL && disk!=NULL) log_info("\nbtrfs magic value at %u/%u/%u\n", offset2cylinder(disk,partition->part_offset), offset2head(disk,partition->part_offset), offset2sector(disk,partition->part_offset)); dump_log(sb, BTRFS_SUPER_INFO_SIZE); } if(partition==NULL) return 0; set_btrfs_info(sb, partition); partition->part_type_i386=P_LINUX; partition->part_type_mac=PMAC_LINUX; partition->part_type_sun=PSUN_LINUX; partition->part_type_gpt=GPT_ENT_TYPE_LINUX_DATA; partition->part_size=(uint64_t)le64(sb->dev_item.total_bytes); guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb->fsid); if(verbose>0) { log_info("\n"); } partition->sborg_offset=BTRFS_SUPER_INFO_OFFSET; partition->sb_size=BTRFS_SUPER_INFO_SIZE; if(verbose>0) { if(disk==NULL) log_info("recover_btrfs: part_size %lu\n", (long unsigned)(partition->part_size / le32(sb->dev_item.sector_size))); else log_info("recover_btrfs: part_size %lu\n", (long unsigned)(partition->part_size / disk->sector_size)); } return 0; }
list_part_t *read_part_gpt(disk_t *disk_car, const int verbose, const int saveheader) { struct gpt_hdr *gpt; struct gpt_ent* gpt_entries; list_part_t *new_list_part=NULL; unsigned int i; uint32_t gpt_entries_size; uint64_t gpt_entries_offset; gpt=(struct gpt_hdr*)MALLOC(disk_car->sector_size); screen_buffer_reset(); if((unsigned)disk_car->pread(disk_car, gpt, disk_car->sector_size, disk_car->sector_size) != disk_car->sector_size) { free(gpt); return NULL; } if(memcmp(gpt->hdr_sig, GPT_HDR_SIG, 8)!=0) { screen_buffer_add("Bad GPT partition, invalid signature.\n"); free(gpt); return NULL; } if(verbose>0) { log_info("hdr_size=%llu\n", (long long unsigned)le32(gpt->hdr_size)); log_info("hdr_lba_self=%llu\n", (long long unsigned)le64(gpt->hdr_lba_self)); log_info("hdr_lba_alt=%llu (expected %llu)\n", (long long unsigned)le64(gpt->hdr_lba_alt), (long long unsigned)((disk_car->disk_size-1)/disk_car->sector_size)); log_info("hdr_lba_start=%llu\n", (long long unsigned)le64(gpt->hdr_lba_start)); log_info("hdr_lba_end=%llu\n", (long long unsigned)le64(gpt->hdr_lba_end)); log_info("hdr_lba_table=%llu\n", (long long unsigned)le64(gpt->hdr_lba_table)); log_info("hdr_entries=%llu\n", (long long unsigned)le32(gpt->hdr_entries)); log_info("hdr_entsz=%llu\n", (long long unsigned)le32(gpt->hdr_entsz)); } /* Check header size */ if(le32(gpt->hdr_size)<92 || le32(gpt->hdr_size) > disk_car->sector_size) { screen_buffer_add("GPT: invalid header size.\n"); free(gpt); return NULL; } { /* CRC check */ uint32_t crc; uint32_t origcrc; origcrc=le32(gpt->hdr_crc_self); gpt->hdr_crc_self=le32(0); crc=get_crc32(gpt, le32(gpt->hdr_size), 0xFFFFFFFF)^0xFFFFFFFF; if(crc!=origcrc) { screen_buffer_add("Bad GPT partition, invalid header checksum.\n"); free(gpt); return NULL; } gpt->hdr_crc_self=le32(origcrc); } if(le64(gpt->hdr_lba_self)!=1) { screen_buffer_add("Bad GPT partition, invalid LBA self location.\n"); free(gpt); return NULL; } if(le64(gpt->hdr_lba_start) >= le64(gpt->hdr_lba_end)) { screen_buffer_add("Bad GPT partition, invalid LBA start/end location.\n"); free(gpt); return NULL; } if(le32(gpt->hdr_revision)!=GPT_HDR_REVISION) { screen_buffer_add("GPT: Warning - not revision 1.0\n"); } if(le32(gpt->__reserved)!=0) { screen_buffer_add("GPT: Warning - __reserved!=0\n"); } if(le32(gpt->hdr_entries)==0 || le32(gpt->hdr_entries)>4096) { screen_buffer_add("GPT: invalid number (%u) of partition entries.\n", (unsigned int)le32(gpt->hdr_entries)); free(gpt); return NULL; } /* le32(gpt->hdr_entsz)==128 */ if(le32(gpt->hdr_entsz)%8!=0 || le32(gpt->hdr_entsz)<128 || le32(gpt->hdr_entsz)>4096) { screen_buffer_add("GPT: invalid partition entry size.\n"); free(gpt); return NULL; } gpt_entries_size=le32(gpt->hdr_entries) * le32(gpt->hdr_entsz); if(gpt_entries_size<16384) { screen_buffer_add("GPT: A minimum of 16,384 bytes of space must be reserved for the GUID Partition Entry array.\n"); free(gpt); return NULL; } gpt_entries_offset=(uint64_t)le64(gpt->hdr_lba_table) * disk_car->sector_size; if((uint64_t) le64(gpt->hdr_lba_self) + le32(gpt->hdr_size) - 1 >= gpt_entries_offset || gpt_entries_offset >= le64(gpt->hdr_lba_start) * disk_car->sector_size) { screen_buffer_add( "GPT: The primary GUID Partition Entry array must be located after the primary GUID Partition Table Header and end before the FirstUsableLBA.\n"); free(gpt); return NULL; } gpt_entries=(struct gpt_ent*)MALLOC(gpt_entries_size); if((unsigned)disk_car->pread(disk_car, gpt_entries, gpt_entries_size, gpt_entries_offset) != gpt_entries_size) { free(gpt_entries); free(gpt); return new_list_part; } { /* CRC check */ uint32_t crc; crc=get_crc32(gpt_entries, gpt_entries_size, 0xFFFFFFFF)^0xFFFFFFFF; if(crc!=le32(gpt->hdr_crc_table)) { screen_buffer_add("Bad GPT partition entries, invalid checksum.\n"); free(gpt_entries); free(gpt); return NULL; } } for(i=0;i<le32(gpt->hdr_entries);i++) { const struct gpt_ent* gpt_entry; gpt_entry=(const struct gpt_ent*)((const char*)gpt_entries + (unsigned long)i*le32(gpt->hdr_entsz)); if(guid_cmp(gpt_entry->ent_type, GPT_ENT_TYPE_UNUSED)!=0 && le64(gpt_entry->ent_lba_start) < le64(gpt_entry->ent_lba_end)) { int insert_error=0; partition_t *new_partition=partition_new(&arch_gpt); new_partition->order=i+1; guid_cpy(&new_partition->part_uuid, &gpt_entry->ent_uuid); guid_cpy(&new_partition->part_type_gpt, &gpt_entry->ent_type); new_partition->part_offset=(uint64_t)le64(gpt_entry->ent_lba_start)*disk_car->sector_size; new_partition->part_size=(uint64_t)(le64(gpt_entry->ent_lba_end) - le64(gpt_entry->ent_lba_start)+1) * disk_car->sector_size; new_partition->status=STATUS_PRIM; UCSle2str(new_partition->partname, (const uint16_t *)&gpt_entry->ent_name, sizeof(gpt_entry->ent_name)/2); new_partition->arch->check_part(disk_car,verbose,new_partition,saveheader); /* log_debug("%u ent_attr %08llx\n", new_partition->order, (long long unsigned)le64(gpt_entry->ent_attr)); */ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition); new_list_part=insert_new_partition(new_list_part, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } } /* TODO: The backup GUID Partition Entry array must be located after the LastUsableLBA and end before the backup GUID Partition Table Header. */ free(gpt_entries); free(gpt); return new_list_part; }
/* Primary superblock is at 1024 (SUPERBLOCK_OFFSET) Group 0 begin at s_first_data_block */ int recover_EXT2(disk_t *disk, const struct ext2_super_block *sb,partition_t *partition,const int verbose, const int dump_ind) { if(test_EXT2(sb, partition)!=0) return 1; if(dump_ind!=0) { if(partition!=NULL && disk!=NULL) log_info("\nEXT2/EXT3 magic value at %u/%u/%u\n", offset2cylinder(disk,partition->part_offset), offset2head(disk,partition->part_offset), offset2sector(disk,partition->part_offset)); /* There is a little offset ... */ dump_log(sb,DEFAULT_SECTOR_SIZE); } if(partition==NULL) return 0; set_EXT2_info(sb, partition, verbose); partition->part_type_i386=P_LINUX; partition->part_type_mac=PMAC_LINUX; partition->part_type_sun=PSUN_LINUX; partition->part_type_gpt=GPT_ENT_TYPE_LINUX_DATA; partition->part_size=td_ext2fs_blocks_count(sb) * EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size); guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb->s_uuid); if(verbose>0) { log_info("\n"); } partition->sborg_offset=0x400; partition->sb_size=EXT2_SUPERBLOCK_SIZE; if(le16(sb->s_block_group_nr)>0) { const unsigned long int block_nr=(le32(sb->s_first_data_block)+le16(sb->s_block_group_nr)*le32(sb->s_blocks_per_group)); if(partition->part_offset< (uint64_t)block_nr * (EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size))) { log_error("recover_EXT2: part_offset problem\n"); return 1; } partition->sb_offset=(uint64_t)block_nr * (EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size)); partition->part_offset-=partition->sb_offset; log_warning("recover_EXT2: \"e2fsck -b %lu -B %u device\" may be needed\n", block_nr, partition->blocksize); } else { partition->sb_offset=0; } if(verbose>0) { log_info("recover_EXT2: s_block_group_nr=%u/%u, s_mnt_count=%u/%u, s_blocks_per_group=%u, s_inodes_per_group=%u\n", le16(sb->s_block_group_nr), (unsigned int)(td_ext2fs_blocks_count(sb) /le32(sb->s_blocks_per_group)), le16(sb->s_mnt_count), le16(sb->s_max_mnt_count), (unsigned int)le32(sb->s_blocks_per_group), (unsigned int)le32(sb->s_inodes_per_group)); log_info("recover_EXT2: s_blocksize=%u\n", partition->blocksize); log_info("recover_EXT2: s_blocks_count %lu\n", (long unsigned int)td_ext2fs_blocks_count(sb)); if(disk==NULL) log_info("recover_EXT2: part_size %lu\n", (long unsigned)(partition->part_size / DEFAULT_SECTOR_SIZE)); else log_info("recover_EXT2: part_size %lu\n", (long unsigned)(partition->part_size / disk->sector_size)); } return 0; }
static void gpt_change_part_type(const disk_t *disk_car, partition_t *partition) { unsigned int offset=0; unsigned int i,j; unsigned int current_element_num=0; log_info("gpt_change_part_type\n"); aff_copy(stdscr); wmove(stdscr,4,0); aff_part(stdscr, AFF_PART_ORDER|AFF_PART_STATUS, disk_car, partition); wmove(stdscr,INTER_CHGTYPE_Y, INTER_CHGTYPE_X); wattrset(stdscr, A_REVERSE); wprintw(stdscr, "[ Proceed ]"); wattroff(stdscr, A_REVERSE); /* By default, select the current type */ for(i=0;gpt_sys_types[i].name!=NULL;i++) { if(guid_cmp(partition->part_type_gpt, gpt_sys_types[i].part_type)==0) { current_element_num=i; while(current_element_num >= offset+3*INTER_CHGTYPE) offset++; } } while(1) { wmove(stdscr,5,0); wprintw(stdscr, "Please choose the partition type, press Enter when done."); wmove(stdscr,5+1,1); wclrtoeol(stdscr); if(offset>0) wprintw(stdscr, "Previous"); for(i=offset;gpt_sys_types[i].name!=NULL && (i-offset)<3*INTER_CHGTYPE;i++) { if(i-offset<INTER_CHGTYPE) wmove(stdscr,5+2+i-offset,0); else if(i-offset<2*INTER_CHGTYPE) wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,26); else wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,52); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(i==current_element_num) { wattrset(stdscr, A_REVERSE); wprintw(stdscr,">%s", gpt_sys_types[i].name); wattroff(stdscr, A_REVERSE); } else { wprintw(stdscr," %s", gpt_sys_types[i].name); } } if(i-offset<INTER_CHGTYPE) wmove(stdscr,5+2+i-offset,1); else if(i-offset<2*INTER_CHGTYPE) wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,27); else wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,53); wclrtoeol(stdscr); if(gpt_sys_types[i].name!=NULL) wprintw(stdscr, "Next"); switch(wgetch(stdscr)) { case 'p': case 'P': case KEY_UP: if(current_element_num>0) current_element_num--; break; case 'n': case 'N': case KEY_DOWN: if(gpt_sys_types[current_element_num].name!=NULL && gpt_sys_types[current_element_num+1].name!=NULL) current_element_num++; break; case KEY_LEFT: if(current_element_num > INTER_CHGTYPE) current_element_num-=INTER_CHGTYPE; else current_element_num=0; break; case KEY_PPAGE: if(current_element_num > 3*INTER_CHGTYPE-1) current_element_num-=3*INTER_CHGTYPE-1; else current_element_num=0; break; case KEY_RIGHT: for(j=0;j<INTER_CHGTYPE;j++) { if(gpt_sys_types[current_element_num].name!=NULL && gpt_sys_types[current_element_num+1].name!=NULL) current_element_num++; } break; case KEY_NPAGE: for(j=0;j<3*INTER_CHGTYPE;j++) { if(gpt_sys_types[current_element_num].name!=NULL && gpt_sys_types[current_element_num+1].name!=NULL) current_element_num++; } break; case 'Q': case 'q': case key_CR: #ifdef PADENTER case PADENTER: #endif guid_cpy(&partition->part_type_gpt, &gpt_sys_types[current_element_num].part_type); return; } if(current_element_num<offset) offset=current_element_num; if(current_element_num >= offset+3*INTER_CHGTYPE) offset=current_element_num-3*INTER_CHGTYPE+1; } }