/* 获得硬盘参数信息 */ static void identify_disk(struct disk* hd) { char id_info[512]; select_disk(hd); cmd_out(hd->my_channel, CMD_IDENTIFY); /* 向硬盘发送指令后便通过信号量阻塞自己, * 待硬盘处理完成后,通过中断处理程序将自己唤醒 */ sema_down(&hd->my_channel->disk_done); /* 醒来后开始执行下面代码*/ if (!busy_wait(hd)) { // 若失败 char error[64]; sprintf(error, "%s identify failed!!!!!!\n", hd->name); PANIC(error); } read_from_sector(hd, id_info, 1); char buf[64]; uint8_t sn_start = 10 * 2, sn_len = 20, md_start = 27 * 2, md_len = 40; swap_pairs_bytes(&id_info[sn_start], buf, sn_len); printk(" disk %s info:\n SN: %s\n", hd->name, buf); memset(buf, 0, sizeof(buf)); swap_pairs_bytes(&id_info[md_start], buf, md_len); printk(" MODULE: %s\n", buf); uint32_t sectors = *(uint32_t*)&id_info[60 * 2]; printk(" SECTORS: %d\n", sectors); printk(" CAPACITY: %dMB\n", sectors * 512 / 1024 / 1024); }
QPhotorec::QPhotorec(QWidget *my_parent) : QWidget(my_parent) { const int verbose=1; const int testdisk_mode=TESTDISK_O_RDONLY|TESTDISK_O_READAHEAD_32K; list_disk_t *element_disk; list_disk=NULL; selected_disk=NULL; list_part=NULL; selected_partition=NULL; params=(struct ph_param *)MALLOC(sizeof(*params)); params->recup_dir=NULL; params->cmd_device=NULL; params->cmd_run=NULL; params->carve_free_space_only=1; params->disk=NULL; params->partition=NULL; options=(struct ph_options *)MALLOC(sizeof(*options)); options->paranoid=1; options->keep_corrupted_file=0; options->mode_ext2=0; options->expert=0; options->lowmem=0; options->verbose=0; options->list_file_format=list_file_enable; reset_list_file_enable(options->list_file_format); stop_the_recovery=false; setWindowIcon( QPixmap( ":res/photorec_64x64.png" ) ); this->setWindowTitle(tr("QPhotoRec")); QVBoxLayout *mainLayout = new QVBoxLayout(); this->setLayout(mainLayout); list_disk=hd_parse(NULL, verbose, testdisk_mode); hd_update_all_geometry(list_disk, verbose); /* Activate the cache, even if photorec has its own */ for(element_disk=list_disk;element_disk!=NULL;element_disk=element_disk->next) element_disk->disk=new_diskcache(element_disk->disk,testdisk_mode); if(list_disk==NULL) { no_disk_warning(); } else select_disk(list_disk->disk); setupUI(); }
//从硬盘读取sec_cnt个扇区到buf void ide_read(struct disk* hd,uint32_t lba,void* buf,uint32_t sec_cnt){ ASSERT(lba <= max_lba); ASSERT(sec_cnt > 0); lock_acquire(&hd->my_channel->lock); //1、先选择操作的硬盘 select_disk(hd); uint32_t secs_op; //每次操作的扇区数 uint32_t secs_done = 0; //已完成的扇区数 while(secs_done < sec_cnt){ if((secs_done + 256) <= sec_cnt){ secs_op = 256; }else{ secs_op = sec_cnt - secs_done; } //2、写入待读入的扇区数和起始扇区号 select_sector(hd,lba + secs_done,secs_op); //3、执行的命令写入reg_cmd寄存器 cmd_out(hd->my_channel,CMD_READ_SECTOR); //准备开始读数据 //------------ 阻塞自己的时机 -------------------- // 在硬盘已经开始工作(开始在内部读数据或写数据)后才能阻塞自己,现在硬盘已经开始忙 // 了,将自己阻塞,等待硬盘完成读操作后通过中断处理程序唤醒自己 sema_down(&hd->my_channel->disk_done); //------------------------------------------------- //4、检测硬盘状态是否可读 //醒来后开始执行下面代码 if(!busy_wait(hd)){ //若失败 char error[64]; sprintf(error,"%s read sector %d failed!!!!\n",hd->name,lba); PANIC(error); } //5、把数据从硬盘的缓冲区中读出 read_from_sector(hd,(void*)((uint32_t)buf + secs_done * 512),secs_op); secs_done += secs_op; } lock_release(&hd->my_channel->lock); }
/* 从硬盘读取sec_cnt个扇区到buf */ void ide_read(struct disk* hd, uint32_t lba, void* buf, uint32_t sec_cnt) { // 此处的sec_cnt为32位大小 ASSERT(lba <= max_lba); ASSERT(sec_cnt > 0); lock_acquire (&hd->my_channel->lock); /* 1 先选择操作的硬盘 */ select_disk(hd); uint32_t secs_op; // 每次操作的扇区数 uint32_t secs_done = 0; // 已完成的扇区数 while(secs_done < sec_cnt) { if ((secs_done + 256) <= sec_cnt) { secs_op = 256; } else { secs_op = sec_cnt - secs_done; } /* 2 写入待读入的扇区数和起始扇区号 */ select_sector(hd, lba + secs_done, secs_op); /* 3 执行的命令写入reg_cmd寄存器 */ cmd_out(hd->my_channel, CMD_READ_SECTOR); // 准备开始读数据 /********************* 阻塞自己的时机 *********************** 在硬盘已经开始工作(开始在内部读数据或写数据)后才能阻塞自己,现在硬盘已经开始忙了, 将自己阻塞,等待硬盘完成读操作后通过中断处理程序唤醒自己*/ sema_down(&hd->my_channel->disk_done); /*************************************************************/ /* 4 检测硬盘状态是否可读 */ /* 醒来后开始执行下面代码*/ if (!busy_wait(hd)) { // 若失败 char error[64]; sprintf(error, "%s read sector %d failed!!!!!!\n", hd->name, lba); PANIC(error); } /* 5 把数据从硬盘的缓冲区中读出 */ read_from_sector(hd, (void*)((uint32_t)buf + secs_done * 512), secs_op); secs_done += secs_op; } lock_release(&hd->my_channel->lock); }
void QPhotorec::disk_changed(int index) { int i; list_disk_t *element_disk; for(element_disk=list_disk, i=0; element_disk!=NULL; element_disk=element_disk->next, i++) { if(i==index) { select_disk(element_disk->disk); PartListWidget_updateUI(); return; } } if(i==index) { newSourceFile(); } }
void QPhotorec::newSourceFile() { const int testdisk_mode=TESTDISK_O_RDONLY|TESTDISK_O_READAHEAD_32K; QString filename = QFileDialog::getOpenFileName(this, tr("Please select a raw file"), "", tr("Raw Files (*.dd *.raw *.img)")); if(!filename.isEmpty()) { disk_t *new_disk=NULL; QByteArray filenameArray= (filename).toUtf8(); list_disk=insert_new_disk_aux(list_disk, file_test_availability(filenameArray.constData(), options->verbose, testdisk_mode), &new_disk); if(new_disk!=NULL) { select_disk(new_disk); HDDlistWidget_updateUI(); PartListWidget_updateUI(); } } }
//将buf中sec_cnt扇区数据写入硬盘 void ide_write(struct disk* hd,uint32_t lba,void* buf,uint32_t sec_cnt){ ASSERT(lba <= max_lba); ASSERT(sec_cnt > 0); lock_acquire(&hd->my_channel->lock); //1、先选择操作的硬盘 select_disk(hd); uint32_t secs_op; //每此操作的扇区数 uint32_t secs_done = 0; //以完成的扇区数 while(secs_done < sec_cnt){ if((secs_done + 256) <= sec_cnt){ secs_op = 256; }else{ secs_op = sec_cnt - secs_done; } //2、写入待写入的扇区数和起始扇区号 select_sector(hd,lba + secs_done , secs_op); //3、执行的命令写入reg_cmd寄存器 cmd_out(hd->my_channel,CMD_WRITE_SECTOR); //准备开始写数据 //4、检测硬盘状态是否可读 if(!busy_wait(hd)){ //若失败 char error[64]; sprintf(error,"%s write sector %d failed !!!!\n",hd->name,lba); PANIC(error); } //5、将数据写入硬盘 write2sector(hd,(void*)((uint32_t)buf + secs_done * 512),secs_op); //在硬盘响应期间阻塞自己 sema_down(&hd->my_channel->disk_done); secs_done += secs_op; } //醒来后开始释放锁 lock_release(&hd->my_channel->lock); }
/* 将buf中sec_cnt扇区数据写入硬盘 */ void ide_write(struct disk* hd, uint32_t lba, void* buf, uint32_t sec_cnt) { ASSERT(lba <= max_lba); ASSERT(sec_cnt > 0); lock_acquire (&hd->my_channel->lock); /* 1 先选择操作的硬盘 */ select_disk(hd); uint32_t secs_op; // 每次操作的扇区数 uint32_t secs_done = 0; // 已完成的扇区数 while(secs_done < sec_cnt) { if ((secs_done + 256) <= sec_cnt) { secs_op = 256; } else { secs_op = sec_cnt - secs_done; } /* 2 写入待写入的扇区数和起始扇区号 */ select_sector(hd, lba + secs_done, secs_op); // 先将待读的块号lba地址和待读入的扇区数写入lba寄存器 /* 3 执行的命令写入reg_cmd寄存器 */ cmd_out(hd->my_channel, CMD_WRITE_SECTOR); // 准备开始写数据 /* 4 检测硬盘状态是否可读 */ if (!busy_wait(hd)) { // 若失败 char error[64]; sprintf(error, "%s write sector %d failed!!!!!!\n", hd->name, lba); PANIC(error); } /* 5 将数据写入硬盘 */ write2sector(hd, (void*)((uint32_t)buf + secs_done * 512), secs_op); /* 在硬盘响应期间阻塞自己 */ sema_down(&hd->my_channel->disk_done); secs_done += secs_op; } /* 醒来后开始释放锁*/ lock_release(&hd->my_channel->lock); }