|
|
1.1 root 1: /*
2: * Copyright (c) 1980,1986,1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1980,1986,1988 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif not lint
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)bad144.c 5.15 (Berkeley) 7/12/88";
26: #endif not lint
27:
28: /*
29: * bad144
30: *
31: * This program prints and/or initializes a bad block record for a pack,
32: * in the format used by the DEC standard 144.
33: * It can also add bad sector(s) to the record, moving the sector
34: * replacements as necessary.
35: *
36: * It is preferable to write the bad information with a standard formatter,
37: * but this program will do.
38: *
39: * RP06 sectors are marked as bad by inverting the format bit in the
40: * header; on other drives the valid-sector bit is cleared.
41: */
42: #include <sys/param.h>
43: #include <sys/dkbad.h>
44: #include <sys/ioctl.h>
45: #include <sys/fs.h>
46: #include <sys/file.h>
47:
48: #include <stdio.h>
49: #include <sys/disklabel.h>
50:
51: #define RETRIES 10 /* number of retries on reading old sectors */
52: #define RAWPART "c" /* disk partition containing badsector tables */
53:
54: int fflag, add, copy, verbose, nflag;
55: int compare();
56: int dups;
57: int badfile = -1; /* copy of badsector table to use, -1 if any */
58: #define MAXSECSIZE 1024
59: struct dkbad curbad, oldbad;
60: #define DKBAD_MAGIC 0
61:
62: char label[BBSIZE];
63: daddr_t size, getold(), badsn();
64: struct disklabel *dp;
65: char name[BUFSIZ];
66: char *malloc();
67: off_t lseek();
68:
69: main(argc, argv)
70: int argc;
71: char *argv[];
72: {
73: register struct bt_bad *bt;
74: daddr_t sn, bn[126];
75: int i, f, nbad, new, bad, errs;
76:
77: argc--, argv++;
78: while (argc > 0 && **argv == '-') {
79: (*argv)++;
80: while (**argv) {
81: switch (**argv) {
82: #if vax
83: case 'f':
84: fflag++;
85: break;
86: #endif
87: case 'a':
88: add++;
89: break;
90: case 'c':
91: copy++;
92: break;
93: case 'v':
94: verbose++;
95: break;
96: case 'n':
97: nflag++;
98: verbose++;
99: break;
100: default:
101: if (**argv >= '0' && **argv <= '4') {
102: badfile = **argv - '0';
103: break;
104: }
105: goto usage;
106: }
107: (*argv)++;
108: }
109: argc--, argv++;
110: }
111: if (argc < 1) {
112: usage:
113: fprintf(stderr,
114: "usage: bad144 [ -f ] disk [ snum [ bn ... ] ]\n");
115: fprintf(stderr,
116: "to read or overwrite bad-sector table, e.g.: bad144 hp0\n");
117: fprintf(stderr,
118: "or bad144 -a [ -f ] [ -c ] disk bn ...\n");
119: fprintf(stderr, "where options are:\n");
120: fprintf(stderr, "\t-a add new bad sectors to the table\n");
121: fprintf(stderr, "\t-f reformat listed sectors as bad\n");
122: fprintf(stderr, "\t-c copy original sector to replacement\n");
123: exit(1);
124: }
125: if (argv[0][0] != '/')
126: (void)sprintf(name, "/dev/r%s%s", argv[0], RAWPART);
127: else
128: strcpy(name, argv[0]);
129: f = open(name, argc == 1? O_RDONLY : O_RDWR);
130: if (f < 0)
131: Perror(name);
132: if (read(f, label, sizeof(label)) < 0)
133: Perror("read");
134: for (dp = (struct disklabel *)(label + LABELOFFSET);
135: dp < (struct disklabel *)
136: (label + sizeof(label) - sizeof(struct disklabel));
137: dp = (struct disklabel *)((char *)dp + 64))
138: if (dp->d_magic == DISKMAGIC && dp->d_magic2 == DISKMAGIC)
139: break;
140: if (dp->d_magic != DISKMAGIC || dp->d_magic2 != DISKMAGIC) {
141: fprintf(stderr, "Bad pack magic number (pack is unlabeled)\n");
142: exit(1);
143: }
144: if (dp->d_secsize > MAXSECSIZE || dp->d_secsize <= 0) {
145: fprintf(stderr, "Disk sector size too large/small (%d)\n",
146: dp->d_secsize);
147: exit(7);
148: }
149: size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders;
150: argc--;
151: argv++;
152: if (argc == 0) {
153: sn = getold(f, &oldbad);
154: printf("bad block information at sector %d in %s:\n",
155: sn, name);
156: printf("cartridge serial number: %d(10)\n", oldbad.bt_csn);
157: switch (oldbad.bt_flag) {
158:
159: case (u_short)-1:
160: printf("alignment cartridge\n");
161: break;
162:
163: case DKBAD_MAGIC:
164: break;
165:
166: default:
167: printf("bt_flag=%x(16)?\n", oldbad.bt_flag);
168: break;
169: }
170: bt = oldbad.bt_bad;
171: for (i = 0; i < 126; i++) {
172: bad = (bt->bt_cyl<<16) + bt->bt_trksec;
173: if (bad < 0)
174: break;
175: printf("sn=%d, cn=%d, tn=%d, sn=%d\n", badsn(bt),
176: bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
177: bt++;
178: }
179: (void) checkold(&oldbad);
180: exit(0);
181: }
182: if (add) {
183: /*
184: * Read in the old badsector table.
185: * Verify that it makes sense, and the bad sectors
186: * are in order. Copy the old table to the new one.
187: */
188: (void) getold(f, &oldbad);
189: i = checkold(&oldbad);
190: if (verbose)
191: printf("Had %d bad sectors, adding %d\n", i, argc);
192: if (i + argc > 126) {
193: printf("bad144: not enough room for %d more sectors\n",
194: argc);
195: printf("limited to 126 by information format\n");
196: exit(1);
197: }
198: curbad = oldbad;
199: } else {
200: curbad.bt_csn = atoi(*argv++);
201: argc--;
202: curbad.bt_mbz = 0;
203: curbad.bt_flag = DKBAD_MAGIC;
204: if (argc > 126) {
205: printf("bad144: too many bad sectors specified\n");
206: printf("limited to 126 by information format\n");
207: exit(1);
208: }
209: i = 0;
210: }
211: errs = 0;
212: new = argc;
213: while (argc > 0) {
214: daddr_t sn = atoi(*argv++);
215: argc--;
216: if (sn < 0 || sn >= size) {
217: printf("%d: out of range [0,%d) for disk %s\n",
218: sn, size, dp->d_typename);
219: errs++;
220: continue;
221: }
222: bn[i] = sn;
223: curbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks);
224: sn %= (dp->d_nsectors*dp->d_ntracks);
225: curbad.bt_bad[i].bt_trksec =
226: ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors);
227: i++;
228: }
229: if (errs)
230: exit(1);
231: nbad = i;
232: while (i < 126) {
233: curbad.bt_bad[i].bt_trksec = -1;
234: curbad.bt_bad[i].bt_cyl = -1;
235: i++;
236: }
237: if (add) {
238: /*
239: * Sort the new bad sectors into the list.
240: * Then shuffle the replacement sectors so that
241: * the previous bad sectors get the same replacement data.
242: */
243: qsort((char *)curbad.bt_bad, nbad, sizeof (struct bt_bad),
244: compare);
245: if (dups) {
246: fprintf(stderr,
247: "bad144: bad sectors have been duplicated; can't add existing sectors\n");
248: exit(3);
249: }
250: shift(f, nbad, nbad-new);
251: }
252: if (badfile == -1)
253: i = 0;
254: else
255: i = badfile * 2;
256: for (; i < 10 && i < dp->d_nsectors; i += 2) {
257: if (lseek(f, dp->d_secsize * (size - dp->d_nsectors + i),
258: L_SET) < 0)
259: Perror("lseek");
260: if (verbose)
261: printf("write badsect file at %d\n",
262: size - dp->d_nsectors + i);
263: if (nflag == 0 && write(f, (caddr_t)&curbad, sizeof(curbad)) !=
264: sizeof(curbad)) {
265: char msg[80];
266: (void)sprintf(msg, "bad144: write bad sector file %d",
267: i/2);
268: perror(msg);
269: }
270: if (badfile != -1)
271: break;
272: }
273: #ifdef vax
274: if (nflag == 0 && fflag)
275: for (i = nbad - new; i < nbad; i++)
276: format(f, bn[i]);
277: #endif
278: #ifdef DIOCSBAD
279: if (nflag == 0 && ioctl(f, DIOCSBAD, (caddr_t)&curbad) < 0)
280: fprintf(stderr,
281: "Can't sync bad-sector file; reboot for changes to take effect\n");
282: #endif
283: exit(0);
284: }
285:
286: daddr_t
287: getold(f, bad)
288: struct dkbad *bad;
289: {
290: register int i;
291: daddr_t sn;
292: char msg[80];
293:
294: if (badfile == -1)
295: i = 0;
296: else
297: i = badfile * 2;
298: for (; i < 10 && i < dp->d_nsectors; i += 2) {
299: sn = size - dp->d_nsectors + i;
300: if (lseek(f, sn * dp->d_secsize, L_SET) < 0)
301: Perror("lseek");
302: if (read(f, (char *) bad, dp->d_secsize) == dp->d_secsize) {
303: if (i > 0)
304: printf("Using bad-sector file %d\n", i/2);
305: return(sn);
306: }
307: (void)sprintf(msg, "bad144: read bad sector file at sn %d", sn);
308: perror(msg);
309: if (badfile != -1)
310: break;
311: }
312: fprintf(stderr, "bad144: %s: can't read bad block info\n", name);
313: exit(1);
314: /*NOTREACHED*/
315: }
316:
317: checkold()
318: {
319: register int i;
320: register struct bt_bad *bt;
321: daddr_t sn, lsn;
322: int errors = 0, warned = 0;
323:
324: if (oldbad.bt_flag != DKBAD_MAGIC) {
325: fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n",
326: name);
327: errors++;
328: }
329: if (oldbad.bt_mbz != 0) {
330: fprintf(stderr, "bad144: %s: bad magic number\n", name);
331: errors++;
332: }
333: bt = oldbad.bt_bad;
334: for (i = 0; i < 126; i++, bt++) {
335: if (bt->bt_cyl == 0xffff && bt->bt_trksec == 0xffff)
336: break;
337: if ((bt->bt_cyl >= dp->d_ncylinders) ||
338: ((bt->bt_trksec >> 8) >= dp->d_ntracks) ||
339: ((bt->bt_trksec & 0xff) >= dp->d_nsectors)) {
340: fprintf(stderr,
341: "bad144: cyl/trk/sect out of range in existing entry: ");
342: fprintf(stderr, "sn=%d, cn=%d, tn=%d, sn=%d\n",
343: badsn(bt), bt->bt_cyl, bt->bt_trksec>>8,
344: bt->bt_trksec & 0xff);
345: errors++;
346: }
347: sn = (bt->bt_cyl * dp->d_ntracks +
348: (bt->bt_trksec >> 8)) *
349: dp->d_nsectors + (bt->bt_trksec & 0xff);
350: if (i > 0 && sn < lsn && !warned) {
351: fprintf(stderr,
352: "bad144: bad sector file is out of order\n");
353: errors++;
354: warned++;
355: }
356: if (i > 0 && sn == lsn) {
357: fprintf(stderr,
358: "bad144: bad sector file contains duplicates (sn %d)\n",
359: sn);
360: errors++;
361: }
362: lsn = sn;
363: }
364: if (errors)
365: exit(1);
366: return (i);
367: }
368:
369: /*
370: * Move the bad sector replacements
371: * to make room for the new bad sectors.
372: * new is the new number of bad sectors, old is the previous count.
373: */
374: shift(f, new, old)
375: {
376: daddr_t repl;
377:
378: /*
379: * First replacement is last sector of second-to-last track.
380: */
381: repl = size - dp->d_nsectors - 1;
382: new--; old--;
383: while (new >= 0 && new != old) {
384: if (old < 0 ||
385: compare(&curbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) {
386: /*
387: * Insert new replacement here-- copy original
388: * sector if requested and possible,
389: * otherwise write a zero block.
390: */
391: if (!copy ||
392: !blkcopy(f, badsn(&curbad.bt_bad[new]), repl - new))
393: blkzero(f, repl - new);
394: } else {
395: if (blkcopy(f, repl - old, repl - new) == 0)
396: fprintf(stderr,
397: "Can't copy replacement sector %d to %d\n",
398: repl-old, repl-new);
399: old--;
400: }
401: new--;
402: }
403: }
404:
405: char *buf;
406:
407: /*
408: * Copy disk sector s1 to s2.
409: */
410: blkcopy(f, s1, s2)
411: daddr_t s1, s2;
412: {
413: register tries, n;
414:
415: if (buf == (char *)NULL) {
416: buf = malloc((unsigned)dp->d_secsize);
417: if (buf == (char *)NULL) {
418: fprintf(stderr, "Out of memory\n");
419: exit(20);
420: }
421: }
422: for (tries = 0; tries < RETRIES; tries++) {
423: if (lseek(f, dp->d_secsize * s1, L_SET) < 0)
424: Perror("lseek");
425: if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize)
426: break;
427: }
428: if (n != dp->d_secsize) {
429: fprintf(stderr, "bad144: can't read sector, %d: ", s1);
430: if (n < 0)
431: perror((char *)0);
432: return(0);
433: }
434: if (lseek(f, dp->d_secsize * s2, L_SET) < 0)
435: Perror("lseek");
436: if (verbose)
437: printf("copying %d to %d\n", s1, s2);
438: if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) {
439: fprintf(stderr,
440: "bad144: can't write replacement sector, %d: ", s2);
441: perror((char *)0);
442: return(0);
443: }
444: return(1);
445: }
446:
447: char *zbuf;
448:
449: blkzero(f, sn)
450: daddr_t sn;
451: {
452:
453: if (zbuf == (char *)NULL) {
454: zbuf = malloc((unsigned)dp->d_secsize);
455: if (zbuf == (char *)NULL) {
456: fprintf(stderr, "Out of memory\n");
457: exit(20);
458: }
459: }
460: if (lseek(f, dp->d_secsize * sn, L_SET) < 0)
461: Perror("lseek");
462: if (verbose)
463: printf("zeroing %d\n", sn);
464: if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) {
465: fprintf(stderr,
466: "bad144: can't write replacement sector, %d: ", sn);
467: perror((char *)0);
468: }
469: }
470:
471: compare(b1, b2)
472: register struct bt_bad *b1, *b2;
473: {
474: if (b1->bt_cyl > b2->bt_cyl)
475: return(1);
476: if (b1->bt_cyl < b2->bt_cyl)
477: return(-1);
478: if (b1->bt_trksec == b2->bt_trksec)
479: dups++;
480: return (b1->bt_trksec - b2->bt_trksec);
481: }
482:
483: daddr_t
484: badsn(bt)
485: register struct bt_bad *bt;
486: {
487: return ((bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors
488: + (bt->bt_trksec&0xff));
489: }
490:
491: #ifdef vax
492: #include <machine/dkio.h>
493:
494: struct rp06hdr {
495: short h_cyl;
496: short h_trksec;
497: short h_key1;
498: short h_key2;
499: char h_data[512];
500: #define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */
501: };
502:
503: /*
504: * Most massbus and unibus drives
505: * have headers of this form
506: */
507: struct hpuphdr {
508: u_short hpup_cyl;
509: u_char hpup_sect;
510: u_char hpup_track;
511: char hpup_data[512];
512: #define HPUP_OKSECT 0xc000 /* this normally means sector is good */
513: #define HPUP_16BIT 0x1000 /* 1 == 16 bit format */
514: };
515: int rp06format(), hpupformat();
516:
517: struct formats {
518: char *f_name; /* disk name */
519: int f_bufsize; /* size of sector + header */
520: int f_bic; /* value to bic in hpup_cyl */
521: int (*f_routine)(); /* routine for special handling */
522: } formats[] = {
523: { "rp06", sizeof (struct rp06hdr), RP06_FMT, rp06format },
524: { "eagle", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
525: { "capricorn", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
526: { "rm03", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
527: { "rm05", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
528: { "9300", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
529: { "9766", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
530: { 0, 0, 0, 0 }
531: };
532:
533: /*ARGSUSED*/
534: hpupformat(fp, dp, blk, buf, count)
535: struct formats *fp;
536: struct disklabel *dp;
537: daddr_t blk;
538: char *buf;
539: int count;
540: {
541: struct hpuphdr *hdr = (struct hpuphdr *)buf;
542: int sect;
543:
544: if (count < sizeof(struct hpuphdr)) {
545: hdr->hpup_cyl = (HPUP_OKSECT | HPUP_16BIT) |
546: (blk / (dp->d_nsectors * dp->d_ntracks));
547: sect = blk % (dp->d_nsectors * dp->d_ntracks);
548: hdr->hpup_track = (u_char)(sect / dp->d_nsectors);
549: hdr->hpup_sect = (u_char)(sect % dp->d_nsectors);
550: }
551: return (0);
552: }
553:
554: /*ARGSUSED*/
555: rp06format(fp, dp, blk, buf, count)
556: struct formats *fp;
557: struct disklabel *dp;
558: daddr_t blk;
559: char *buf;
560: int count;
561: {
562:
563: if (count < sizeof(struct rp06hdr)) {
564: fprintf(stderr, "Can't read header on blk %d, can't reformat\n",
565: blk);
566: return (-1);
567: }
568: return (0);
569: }
570:
571: format(fd, blk)
572: int fd;
573: daddr_t blk;
574: {
575: register struct formats *fp;
576: static char *buf;
577: static char bufsize;
578: struct format_op fop;
579: int n;
580:
581: for (fp = formats; fp->f_name; fp++)
582: if (strcmp(dp->d_typename, fp->f_name) == 0)
583: break;
584: if (fp->f_name == 0) {
585: fprintf(stderr, "bad144: don't know how to format %s disks\n",
586: dp->d_typename);
587: exit(2);
588: }
589: if (buf && bufsize < fp->f_bufsize) {
590: free(buf);
591: buf = NULL;
592: }
593: if (buf == NULL)
594: buf = malloc((unsigned)fp->f_bufsize);
595: if (buf == NULL) {
596: fprintf(stderr, "bad144: can't allocate sector buffer\n");
597: exit(3);
598: }
599: bufsize = fp->f_bufsize;
600: /*
601: * Here we do the actual formatting. All we really
602: * do is rewrite the sector header and flag the bad sector
603: * according to the format table description. If a special
604: * purpose format routine is specified, we allow it to
605: * process the sector as well.
606: */
607: if (verbose)
608: printf("format blk %d\n", blk);
609: bzero((char *)&fop, sizeof(fop));
610: fop.df_buf = buf;
611: fop.df_count = fp->f_bufsize;
612: fop.df_startblk = blk;
613: bzero(buf, fp->f_bufsize);
614: if (ioctl(fd, DIOCRFORMAT, &fop) < 0)
615: perror("bad144: read format");
616: if (fp->f_routine &&
617: (*fp->f_routine)(fp, dp, blk, buf, fop.df_count) != 0)
618: return;
619: if (fp->f_bic) {
620: struct hpuphdr *xp = (struct hpuphdr *)buf;
621:
622: xp->hpup_cyl &= ~fp->f_bic;
623: }
624: if (nflag)
625: return;
626: bzero((char *)&fop, sizeof(fop));
627: fop.df_buf = buf;
628: fop.df_count = fp->f_bufsize;
629: fop.df_startblk = blk;
630: if (ioctl(fd, DIOCWFORMAT, &fop) < 0)
631: Perror("write format");
632: if (fop.df_count != fp->f_bufsize) {
633: char msg[80];
634: (void)sprintf(msg, "bad144: write format %d", blk);
635: perror(msg);
636: }
637: }
638: #endif
639:
640: Perror(op)
641: char *op;
642: {
643:
644: fprintf(stderr, "bad144: "); perror(op);
645: exit(4);
646: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.