1/* make_bad_sector.c v3.03 by Mark Lord */ 2#include <stdio.h> 3#include <stdlib.h> 4#include <unistd.h> 5#include <fcntl.h> 6#include <errno.h> 7#include <string.h> 8#include <sys/ioctl.h> 9#include <sys/stat.h> 10#include <sys/types.h> 11#include <linux/fs.h> 12#include <scsi/scsi.h> 13#include <scsi/sg.h> 14 15#include "hdparm.h" 16#include "sgio.h" 17 18#define READ 0 19#define WRITE 1 20 21int verbose = 0; // used by sgio.c 22 23#if 0 24static void init_hdio_taskfile (struct hdio_taskfile *r, __u8 ata_op, int rw, int force_lba48, 25 __u64 lba, unsigned int nsect, int data_bytes) 26{ 27 const __u64 lba28_mask = 0x0fffffff; 28 29 memset(r, 0, sizeof(struct hdio_taskfile) + data_bytes); 30 r->xfer_method = TASKFILE_XFER_METHOD_PIO_OUT; 31 if (!data_bytes) { 32 r->cmd_req = TASKFILE_CMD_REQ_NODATA; 33 } else { 34 r->cmd_req = rw ? TASKFILE_CMD_REQ_OUT : TASKFILE_CMD_REQ_IN; 35 if (rw) 36 r->out_bytes = data_bytes; 37 else 38 r->in_bytes = data_bytes; 39 } 40 r->lob.command = ata_op; 41 r->out_flags.lob.b.command = 1; 42 r->out_flags.lob.b.dev = 1; 43 r->out_flags.lob.b.lbal = 1; 44 r->out_flags.lob.b.lbam = 1; 45 r->out_flags.lob.b.lbah = 1; 46 r->out_flags.lob.b.nsect = 1; 47 48 r->lob.nsect = nsect; 49 r->lob.lbal = lba; 50 r->lob.lbam = lba >> 8; 51 r->lob.lbah = lba >> 16; 52 r->lob.dev = ATA_USING_LBA; 53 54 if ((lba & ~lba28_mask) == 0 && nsect <= 256 && !force_lba48) { 55 r->lob.dev |= lba >> 24; 56 } else { 57 r->hob.nsect = nsect >> 8; 58 r->hob.lbal = lba >> 24; 59 r->hob.lbam = lba >> 32; 60 r->hob.lbah = lba >> 40; 61 r->out_flags.hob.b.nsect = 1; 62 r->out_flags.hob.b.lbal = 1; 63 r->out_flags.hob.b.lbam = 1; 64 r->out_flags.hob.b.lbah = 1; 65 } 66} 67#endif 68 69int main (int argc, char *argv[]) 70{ 71 /* 72 * Note: the extra bytes are transfered ONE-PER_WORD after the sector data, 73 * so for 4 extra bytes, we must transfer 4 extra WORDs. 74 */ 75 const char *devpath, *myname = argv[0];; 76 int rc = 0, fd, do_rewrite = 0, do_readback = 0; 77 __u8 ata_op; 78 __u64 lba; 79 unsigned char bad_pattern = 0x00; 80 struct hdio_taskfile *r; 81 const int ten_seconds = 10; 82 83 r = malloc(sizeof(struct hdio_taskfile) + 520); 84 if (!r) { 85 perror("malloc()"); 86 exit(1); 87 } 88 89 while (argc-- > 1 && **++argv == '-') { 90 if (!strcmp("--readback", argv[0])) { 91 do_readback = 1; 92 } else if (!strcmp("--rewrite", argv[0])) { 93 do_rewrite = 1; 94 } else { 95 fprintf(stderr, "%s: unknown flag: %s\n", myname, argv[0]); 96 exit(1); 97 } 98 } 99 if (argc != 2) { 100 fprintf(stderr, "%s: bad/missing parms: expected [--rewrite|--readback] <devpath> <lba>\n", myname); 101 exit(1); 102 } 103 devpath = argv[0]; 104 lba = strtol(argv[1], NULL, 0); 105 106 fd = open(devpath, O_RDWR); 107 if (fd == -1) { 108 perror(devpath); 109 exit(1); 110 } 111 112 // Try and ensure that the system doesn't have our sector in cache: 113 (void) ioctl(fd, BLKFLSBUF, NULL); 114 115 if (do_rewrite) { 116 fprintf(stderr, "%s: overwriting LBA=%llu (this should succeed!)\n", 117 devpath, (unsigned long long)lba); 118 ata_op = (lba >> 28) ? ATA_OP_WRITE_PIO_EXT : ATA_OP_WRITE_PIO; 119 init_hdio_taskfile(r, ata_op, WRITE, 0, lba, 1, 512); 120 rc = do_taskfile_cmd(fd, r, ten_seconds); 121 fprintf(stderr, "%s: %s\n", devpath, rc ? "error" : "success"); 122 } 123 if (rc == 0 || do_readback) { 124 fprintf(stderr, "%s: readback test LBA=%llu%s\n", 125 devpath, (unsigned long long)lba, 126 do_rewrite ? " (this should succeed!)" : ""); 127 ata_op = (lba >> 28) ? ATA_OP_READ_PIO_EXT : ATA_OP_READ_PIO; 128 init_hdio_taskfile(r, ata_op, READ, 0, lba, 1, 512); 129 rc = do_taskfile_cmd(fd, r, ten_seconds); 130 fprintf(stderr, "%s: %s\n", devpath, rc ? "error" : "success"); 131 } 132 if (do_rewrite || do_readback) 133 exit(rc); 134 135 do { 136 int i; 137 138 init_hdio_taskfile(r, ATA_OP_WRITE_LONG_ONCE, WRITE, 0, lba, 1, 520); 139 --bad_pattern; 140 // Corrupt and rewrite the sector: 141 for (i = 0; i < 520; ++i) 142 r->data[i] = bad_pattern; 143 fprintf(stderr, "%s: writing LBA=%llu\n", devpath, (unsigned long long)lba); 144 rc = do_taskfile_cmd(fd, r, ten_seconds); 145 if (rc) { 146 fprintf(stderr, "%s: WRITE_LONG failed\n", devpath); 147 } else { 148 fprintf(stderr, "%s: readback test LBA=%llu (this should fail!)\n", 149 devpath, (unsigned long long)lba); 150 //init_hdio_taskfile(r, ATA_OP_READ_VERIFY_ONCE, READ, 0, lba, 1, 0); 151 init_hdio_taskfile(r, ATA_OP_READ_PIO_EXT, READ, 1, lba, 1, 512); 152 rc = do_taskfile_cmd(fd, r, ten_seconds); 153 if (rc) 154 fprintf(stderr, "%s: readback failed\n", devpath); 155 } 156 } while (rc == 0); 157 exit (0); 158} 159