/* * работа с образами винчестера БК в форматах "Самара" и "Альтпро" * */ #include #include #include #include #include #define ahdd_cyl 255 #define ahdd_head 254 #define ahdd_sec 253 #define ahdd_ld_all 252 #define ahdd_part 251 #define shdd_boot 0 #define shdd_cyl 1 #define shdd_head_sec 2 #define shdd_part 3 #define shdd_nld 0 #define shdd_ld_len 1 #define shdd_adr_boot 2 #define shhd_adr_par 3 #define shdd_page 4 char p_invers = 0; unsigned short int cyl = 0; unsigned short int head = 0; unsigned short int sec = 0; unsigned short int boot = 2; unsigned short int ld_all = 0; unsigned short int ncyl = 0; unsigned short int nhead = 0; unsigned short int nsec = 0; unsigned short int nld = 2; unsigned short int crc = 012701; //mbr для Альтпро unsigned short int mbr[256] = { 0xA0, 0x15DF, 0xFF87, 0xFFEA, 0x15DF, 0x1C, 0xFFE0, 0x87, 0x0 }; unsigned short int part[256] = { 0 }; unsigned short int buf[256]; long int len = 0; long int lba = 3; // начальный сектор ld для hdd "Самара" char bkd[] = "0c.bkd"; char img[] = "bkhdd.img"; FILE* rfp, * wfp; // определение длины файла для чтения int lenfile() { fseek(rfp, 0, SEEK_END); len = ftell(rfp); printf("lenght = %ld byte, ", len); fseek(rfp, 0, SEEK_SET); len += 511; len /= 512; printf("blocks = %ld ", len); return (len); } // инверсия буфера пословная unsigned short int invers_buf(unsigned short int *buf) { if (p_invers == '\0') return (0); for (int i = 0; i < 256; i++) buf[i] = ~buf[i]; return (0); } // полное копирование из bkd и запись в образ hdd // возвращает номер последнего записанного сектора в nsec int wr_ld() { for (int i = 0; i < len; i++) { if ((fread(buf, 1, 512, rfp)) != 512) printf("Ошибка чтения %d блока из файла %s \n", i, bkd); invers_buf(buf); if ((fwrite(buf, 1, 512, wfp)) != 512) printf("Ошибка записи в файл %s \n", img); if (++nsec == sec) { nsec = 0; if (++nhead == head) { nhead = 0; if (++ncyl > cyl) { printf("Переполнение образа диска\n", img); exit(-1); } } } } return (nsec); } // полное копирование из образа hdd в образ bkd void wr_bkd() { for (int i = 0; i < len; i++) { if ((fread(buf, 1, 512, rfp)) != 512) printf("Ошибка чтения из файла %s \n", img); invers_buf(buf); if ((fwrite(buf, 1, 512, wfp)) != 512) printf("Ошибка записи в файл %s \n", bkd); } } // запись пустых секторов // nsec - текущий сектор // sec - конечный int wr_sectors() { for (int i = 0; i < 256; i++) if (p_invers == 0) buf[i] = 0; else buf[i] = 0177777; for (int i = nsec; i < sec; i++) { if ((fwrite(buf, 1, 512, wfp)) != 512) printf("Ошибка записи в файл %s \n", img); if (++nhead == head) { nhead = 0; if (++ncyl > cyl) { printf("Переполнение образа диска\n", img); return (-1); } } } return (0); } // подсчёт crc для altpro unsigned short int crc_alt() { for (int i = 0; i < (ld_all*2 + 4); i++) crc += part[255 - i]; printf("crc = %d \n", crc); return (crc); } void helpdoc() { printf("Программа для работы с образами винчестера БК0010-11\n"); printf("\t(c) 2010 Terra software\n\n"); printf("Использование: bkhdd -a или -m [-i -cN -hN -sN]\n\n"); printf("\t/a - формат образа диска 'АльтПро'\n"); printf("\t/m - формат образа диска 'Самара'\n"); printf("\t/i - включить инверсию данных\n"); printf("\t/cN - количество цилиндров (дорожек)\n"); printf("\t/hN - количество головок\n"); printf("\t/sN - количество секторов на дорожке\n\n"); printf("если параметры hdd не указаны, то производиться чтение из образа bkhdd.img\n\n"); printf("При создании образа данные пишуться в файл bkhdd.img, после чего их можно\n"); printf("записать с помошью бесплатной утилиты dd -http://www.chrysocome.net/dd\n"); } // создание образа hdd в формате Альтпро void bkd_img_alt() { if ((rfp = fopen(bkd, "rb")) == NULL) { printf("Невозможно открыть файл %s \n", bkd); exit(-1); } if ((wfp = fopen(img, "w+b")) == NULL) { printf("Невозможно открыть файл %s \n", img); exit(-1); } part[ahdd_cyl] = cyl; part[ahdd_head] = head; part[ahdd_sec] = sec; nsec = 0; nsec = wr_sectors(); // записать пустую нулевую дорожку for (; ;) { len = lenfile(); // получить длину файла в блоках printf("cyl = %d head = %d \n", ncyl, nhead); part[ahdd_part - ((nld - 2) * 2)] = nhead ^ (ncyl << 4); part[ahdd_part - 1 - ((nld - 2) * 2)] = len; nsec = wr_ld(); //посекторная чтение/запись nsec остаток секторов до конца дорожки nsec = wr_sectors(); //дозаписать нулями nsec = 0; fclose(rfp); bkd[1]++; if (bkd[1]=='{') { bkd[1]='c'; bkd[0]++; } nld++; ld_all = nld - 2; if ((rfp = fopen(bkd, "rb")) == NULL) break; } part[ahdd_ld_all] = ld_all ^ (boot << 8); part[ahdd_part - (ld_all * 2)] = crc_alt(); fseek(wfp, 0, SEEK_SET); invers_buf(mbr); if ((fwrite(mbr, 1, 512, wfp)) != 512) printf("Ошибка записи в файл %s \n", img); fseek(wfp, 7 * 512, SEEK_SET); invers_buf(part); if ((fwrite(part, 1, 512, wfp)) != 512) printf("Ошибка записи в файл %s \n", img); fclose(rfp); fclose(wfp); } // создание образа hdd в формате "Самара" void bkd_img_sam() { if ((rfp = fopen(bkd, "rb")) == NULL) { printf("Невожможно открыть файл %s \n", bkd); exit(-1); } if ((wfp = fopen(img, "w+b")) == NULL) { printf("Невозможно открыть файл %s \n", img); exit(-1); } part[shdd_boot] = boot; // boot part[shdd_cyl] = cyl; part[shdd_head_sec] = head ^ (sec << 8); nsec = sec - 3; wr_sectors(); // записать 3 пустых сектора for (; ;) { len = lenfile(); printf("lba = %ld len = %d \n", lba, len); for (int i = 0; i < 256; i++) if (p_invers == 0) buf[i] = 0; else buf[i] = 0177777; // создать начальный блок логического диска buf[shdd_nld] = nld; // номер ld buf[shdd_ld_len] = len; // длина ld buf[shdd_adr_boot] = 02000; // адрес загрузки загрузчика :) buf[shhd_adr_par] = 01000; // адрес блока параметров для загрузчика buf[shdd_page] = 014400; // состояние регистра страниц part[(nld - 2) * 2 + 3] = lba; lba += len + 1; invers_buf(buf); if ((fwrite(buf, 1, 512, wfp)) != 512) printf("Ошибка записи в файл %s \n", img); wr_ld(); fclose(rfp); bkd[1]++; if (bkd[1]=='{') { bkd[1]='c'; bkd[0]++; } nld++; if ((rfp = fopen(bkd, "rb")) == NULL) break; } invers_buf(part); fseek(wfp, 512, SEEK_SET); if ((fwrite(part, 1, 512, wfp)) != 512) printf("Ошибка записи в файл %s \n", img); fclose(rfp); fclose(wfp); } // чтение дисков из образа hdd "Альтпро" и запись в bkd void img_bkd_alt() { if ((rfp = fopen(img, "rb")) == NULL) { printf("Невозможно открыть файл %s \n", img); exit(-1); } fseek(rfp, 7 * 512, SEEK_SET); if ((fread(part, 1, 512, rfp)) != 512) printf("Ошибка запис в файл %s \n", img); invers_buf(part); cyl = part[ahdd_cyl]; head = part[ahdd_head]; sec = part[ahdd_sec]; ld_all = part[ahdd_ld_all] & 0377; printf("cyl = %d head = %d sec = %d ld = %d \n", cyl, head, sec, ld_all); if (part[ahdd_part - (ld_all * 2)] != crc_alt()) { printf("Образ диска %s не в формате 'Альтпро'\n", img); exit(-1); } for (int i = 0; i < ld_all; i++) { ncyl = part[ahdd_part - ((nld - 2) * 2)] >> 4; nhead = part[ahdd_part - ((nld - 2) * 2)] & 0xF; lba = (ncyl * head + nhead) * sec * 512; len = part[ahdd_part - 1 - ((nld - 2) * 2)]; printf("cyl = %d head = %d lba = %ld len = %d \n", ncyl, nhead, lba, len); fseek(rfp, lba, SEEK_SET); if ((wfp = fopen(bkd, "w+b")) == NULL) { printf("Невозможно открыть файл %s \n", bkd); exit(-1); } wr_bkd(); fclose(wfp); bkd[1]++; if (bkd[1]=='{') { bkd[1]='c'; bkd[0]++; } nld++; } fclose(rfp); } // чтение дисков из образа hdd "Самара" и запись в bkd void img_bkd_sam() { if ((rfp = fopen(img, "rb")) == NULL) { printf("Невозможно открыть файл %s \n", img); exit(-1); } fseek(rfp, 512, SEEK_SET); if ((fread(part, 1, 512, rfp)) != 512) printf("Ошибка записи в файл %s \n", img); invers_buf(part); cyl = part[shdd_cyl]; head = part[shdd_head_sec] & 0377; sec = part[shdd_head_sec] >> 8; for (ld_all = 0; ld_all < 64; ld_all++) { lba = part[shdd_part + (ld_all * 2)]; // подсчитать диски if (lba == 0) break; } printf("cyl = %d head = %d sec = %d ld = %d\n", cyl, head, sec, ld_all); for (int i = 0; i < ld_all; i++) { lba = part[shdd_part + ((nld - 2) * 2)]; printf("ld = %d lba = %ld \n", nld, lba); lba *= 512; fseek(rfp, lba, SEEK_SET); if ((fread(buf, 1, 512, rfp)) != 512) { printf("Ошибка чтения из файла %s \n", img); exit(-1); } invers_buf(buf); if (buf[shdd_nld] != nld) { printf("Образ диска %s не в формате 'Самара'\n", img); exit(-1); } if ((wfp = fopen(bkd, "w+b")) == NULL) { printf("Невозможно создать файл %s \n", bkd); exit(-1); } len = buf[shdd_ld_len]; wr_bkd(); fclose(wfp); bkd[1]++; if (bkd[1]=='{') { bkd[1]='c'; bkd[0]++; } nld++; } fclose(rfp); } int main(int argc, char** argv) { setlocale(LC_ALL,"rus"); char format_hdd = 0; int ch; while ((ch = getopt(argc, argv, "amic:h:s:")) != -1) switch (ch) { case 'a': format_hdd = 'a'; break; case 'm': format_hdd = 'm'; break; case 'i': p_invers++; break; case 'c': cyl = strtol(optarg, 0, 0); break; case 'h': head = strtol(optarg, 0, 0); break; case 's': sec = strtol(optarg, 0, 0); break; default: helpdoc(); exit(-1); } if (argc < 2) { helpdoc(); exit(-1); } if (format_hdd == 'a') { if (sec == 0 && head == 0 && cyl == 0) { printf("\nчитаем образ диска 'Альтпро'\n"); img_bkd_alt(); } else { printf("\nсоздаём образ диска 'Альтпро'\n"); printf("\nДорожек %d головок %d секторов %d \n", cyl, head, sec); bkd_img_alt(); } } if (format_hdd == 'm') { if (sec == 0 && head == 0 && cyl == 0) { printf("\nчитаем образ диска 'Самара'\n"); img_bkd_sam(); } else { printf("\nсоздаём образ диска 'Самара'\n"); bkd_img_sam(); } } return (0); } //TODO: // -I (-f) ключ для получения информации chs из образа диска // прямая запись образа на физический носитель