1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: pc_hd_label.c,v $
29 * Revision 2.2 93/08/10 15:56:36 mrt
30 * Created by Robert Baron from hc.c
31 *
32 */
33
34 #include <hd.h>
35
36 #include <sys/types.h>
37 #define PRIBIO 20
38 #include <device/buf.h>
39 #include <device/errno.h>
40 #include <device/device_types.h>
41 #include <device/disk_status.h>
42 #include <sys/ioctl.h>
43 #include <i386/pio.h>
44 #include <i386/ipl.h>
45 #include <i386at/disk.h>
46 #include <chips/busses.h>
47 #include <i386at/hdreg.h>
48
49 /* From sys/systm.h */
50 struct buf *geteblk();
51
52 extern int hdgotvtoc[NHD];
53 extern struct alt_info alt_info[NHD];
54 extern struct disklabel label[NHD];
55 extern int labeloffset[NHD];
56 extern int labelsector[NHD];
57
58 extern int label_flag;
59 extern int allow_bsd_label;
60
61 #define LABEL_DEBUG(x,y) if (label_flag&x) y
62 unsigned dkcksum();
63
64
65 hdreadlabel(unit, badblocks)
66 unsigned char unit;
67 {
68 struct disklabel *lp = &label[unit];
69 struct evtoc *evp;
70 struct buf *bp;
71 struct ipart part[FD_NUMPART];
72 struct ipart *bpart,
73 *ospart = (struct ipart *)0;
74 u_int i, n;
75
76 if (hdgotvtoc[unit]) {
77 if (hdgotvtoc[unit] == -1)
78 sleep(&hdgotvtoc[unit],PRIBIO);
79 return;
80 }
81 setcontroller(unit); /* start sane */
82 hdgotvtoc[unit] = -1;
83 bp = geteblk(SECSIZE); /* for evtoc */
84 /* make partition 0 the whole disk in case of failure then get pdinfo*/
85 lp->d_partitions[PART_DISK].p_offset = 0;
86 lp->d_partitions[PART_DISK].p_size = lp->d_secperunit;
87 /* get active partition */
88 bp->b_flags = B_READ | B_MD1;
89 bp->b_blkno = 0;
90 bp->b_dev = WHOLE_DISK(unit); /* C partition */
91 bp->b_bcount = SECSIZE;
92 hdstrategy(bp);
93 biowait(bp);
94 if (bp->b_flags & B_ERROR) {
95 printf("hd%d: can't read sector 0 boot record\n",unit);
96 goto done;
97 }
98 if (((struct mboot *)bp->b_un.b_addr)->signature != 0xaa55) {
99 printf("hd%d: sector 0 corrupt, can't read boot record\n",unit);
100 goto done;
101 }
102 bcopy(((struct mboot *)bp->b_un.b_addr)->parts,
103 part, FD_NUMPART * sizeof (struct ipart));
104 /*
105 * In search of the bios partition
106 */
107 bpart = part;
108 #ifdef old
109 {
110 int nmach = 0;
111 struct ipart *mabr = (struct ipart *) 0,
112 *mbr = (struct ipart *) 0;
113 for (i = 0; i < 4; i++, bpart++) {
114 if (bpart->sys_ind == UNIXOS) {
115 if (!nmach++)
116 mabr = bpart;
117 if (bpart->boot_ind == ACTIVE)
118 mbr = bpart;
119 }
120 }
121 if ((int)mabr)
122 bpart = mabr;
123 else if (nmach == 1)
124 bpart = mbr;
125 else if (!nmach)
126 bpart = &mempty;
127 else {
128 printf("More than one mach partition and none active.\n");
129 printf("Try to fix this from floppies or DOS.\n");
130 for (;;);
131 }
132 }
133 #else /* old */
134 for (i = 0; i < 4; i++, bpart++) {
135 LABEL_DEBUG(1,print_dos_partition(i, bpart));
136 if (bpart->systid == UNIXOS || bpart->systid == BSDOS) {
137 if ((int)ospart) {
138 if (bpart->bootid == ACTIVE)
139 ospart = bpart;
140 } else
141 ospart = bpart;
142 }
143
144 }
145 if (!ospart)
146 goto done;
147 #endif /* old */
148 OS = ospart->systid;
149 if (OS == UNIXOS)
150 printf("hd%d: MACH OS ", unit);
151 if (OS == BSDOS)
152 printf("hd%d: XXXBSD OS ", unit);
153 /* set correct partition information */
154 lp->d_partitions[PART_DISK].p_offset = ospart->relsect;
155 lp->d_partitions[PART_DISK].p_size = ospart->numsect;
156 if (hd_bios_bsd_label(unit, bp, lp, ospart))
157 goto done;
158 /* get evtoc out of active unix partition */
159 bp->b_flags = B_READ;
160 bp->b_blkno = PDLOCATION;
161 hdstrategy(bp);
162 biowait(bp);
163 if (bp->b_flags & B_ERROR) {
164 printf("hd%d: can't read evtoc\n", unit);
165 goto done;
166 }
167 if ((evp = (struct evtoc *)bp->b_un.b_addr)->sanity != VTOC_SANE) {
168 printf("hd%d: evtoc corrupt\n",unit);
169 goto done;
170 }
171 printf("LOCAL LABEL\n");
172 LABEL_DEBUG(0x40,print_local_label(evp, "ev:"));
173
174 /* pd info from disk must be more accurate than that in cmos thus
175 override hdparm and re- setcontroller() */
176 n = evp->nparts;
177 if (n >= MAXPARTITIONS)
178 n = MAXPARTITIONS;
179 fudge_bsd_label(lp, DTYPE_ESDI, evp->cyls, evp->tracks, evp->sectors, n);
180 setcontroller(unit);
181
182 /* copy info on all valid partition, zero the others */
183 for (i = 0; i < n; i++) {
184 if (i == PART_DISK)
185 continue;
186 bzero(&(lp->d_partitions[i]), sizeof (struct partition));
187 lp->d_partitions[i].p_size = evp->part[i].p_size;
188 lp->d_partitions[i].p_offset = evp->part[i].p_start;
189 lp->d_partitions[i].p_fstype = FS_BSDFFS;
190 }
191 for ( ; i < MAXPARTITIONS; i++) {
192 if (i == PART_DISK)
193 continue;
194 bzero(&(lp->d_partitions[i]), sizeof (struct partition));
195 }
196 if (badblocks) {
197 /* get alternate sectors out of active unix partition */
198 bp->b_blkno = evp->alt_ptr/SECSIZE;
199 for (i = 0; i < 4; i++) {
200 bp->b_flags = B_READ;
201 hdstrategy(bp);
202 biowait(bp);
203 if (bp->b_flags & B_ERROR) {
204 printf("hd%d: can't read alternate sectors\n", unit);
205 goto done;
206 }
207 bcopy(bp->b_un.b_addr,(char *)&alt_info[unit]+i*SECSIZE,
208 SECSIZE);
209 bp->b_blkno++;
210 }
211 if (alt_info[unit].alt_sanity != ALT_SANITY)
212 printf("hd%d: alternate sectors corrupt\n", unit);
213 }
214 /*
215 * Just in case
216 */
217 labeloffset[unit] = 0;
218 labelsector[unit] = (ospart->relsect + LBLLOC);
219 lp->d_checksum = dkcksum(lp);
220 LABEL_DEBUG(2,print_bsd_label(lp, " "));
221
222 done:
223 brelse(bp);
224 hdgotvtoc[unit]=1;
225 wakeup(&hdgotvtoc[unit]);
226 }
227
228 hd_bios_bsd_label(unit, bp, label, ospart)
229 int unit;
230 struct buf *bp;
231 struct disklabel *label;
232 struct ipart *ospart;
233 {
234 struct disklabel *dlp;
235 int i;
236
237 bp->b_flags = B_READ;
238 bp->b_blkno = LBLLOC;
239 hdstrategy(bp);
240 biowait(bp);
241 if (bp->b_flags & B_ERROR) {
242 printf("hd%d: can't read bsd label\n", unit);
243 return FALSE;
244 }
245 dlp = (struct disklabel *) bp->b_un.b_addr;
246 if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
247 if (ospart->systid == BSDOS) {
248 printf("NO BSD LABEL!!\n");
249 }
250 return FALSE;
251 }
252 printf("BSD LABEL\n");
253 LABEL_DEBUG(2,print_bsd_label(dlp, "dk:"));
254 if (dlp->d_flags & D_BADSECT) {
255 printf("hd%d: DISK NEEDS BAD144 SUPPORT. WILL TRY FOR LOCAL LABEL.\n",
256 unit);
257 return FALSE;
258 }
259
260 /*
261 * here's were we dump label
262 */
263 if (allow_bsd_label == 0)
264 return FALSE;
265
266 *label = *dlp;
267 setcontroller(unit);
268 bzero(&alt_info[unit], sizeof (struct alt_info));
269
270 labeloffset[unit] = 0;
271 labelsector[unit] = (ospart->relsect + LBLLOC);
272
273 LABEL_DEBUG(0x20,print_bsd_label(label, " "));
274 return TRUE;
275 }
276
277 hdwritelabel(unit)
278 {
279 struct buf *bp;
280
281 if (alt_info[unit].alt_trk.alt_used || alt_info[unit].alt_sec.alt_used) {
282 printf("hd%x: can not write label: alt trk = %d, alt sec = %d\n",
283 unit, alt_info[unit].alt_trk.alt_used, alt_info[unit].alt_sec.alt_used);
284 return (EINVAL);
285 }
286 printf("hd%x: hdwritelabel replacing label at %d\n", unit, labelsector[unit]);
287
288 bp = geteblk(SECSIZE);
289 bp->b_flags = B_READ | B_MD1; /* MD1 is be absolute */
290 bp->b_blkno = labelsector[unit];
291 bp->b_dev = WHOLE_DISK(unit); /* C partition */
292 bp->b_bcount = SECSIZE;
293 hdstrategy(bp);
294 biowait(bp);
295 if (bp->b_flags & B_ERROR) {
296 printf("hd%d hdwritelabel(): read failure\n", unit);
297 brelse(bp);
298 return (ENXIO);
299 }
300
301 *((struct disklabel *) &(((char *)bp->b_un.b_addr)[labeloffset[unit]]))
302 = label[unit];
303
304 bp->b_flags = B_WRITE | B_MD1; /* MD1 is be absolute */
305 bp->b_blkno = labelsector[unit];
306 bp->b_dev = WHOLE_DISK(unit); /* C partition */
307 bp->b_bcount = SECSIZE;
308 hdstrategy(bp);
309 biowait(bp);
310 if (bp->b_flags & B_ERROR) {
311 printf("hd%d: hdwritelabel() write failure\n", unit);
312 brelse(bp);
313 return ENXIO;
314 }
315 brelse(bp);
316
317 return D_SUCCESS;
318 }
319
320 io_return_t
321 hdsetlabel(dev_t dev, int flavor, int *data, unsigned int count)
322 {
323 io_return_t errcode = D_SUCCESS;
324 int unit = UNIT(dev);
325 struct disklabel*lp = &label[unit];
326
327 switch (flavor) {
328 /* set */
329 case DIOCWLABEL:
330 case DIOCWLABEL - (0x10<<16):
331 if (*(int*)data)
332 /*
333 tgt->flags |= TGT_WRITE_LABEL;
334 else
335 tgt->flags &= ~TGT_WRITE_LABEL;
336 */ break;
337 case DIOCSDINFO:
338 case DIOCSDINFO - (0x10<<16):
339 case DIOCWDINFO:
340 case DIOCWDINFO - (0x10<<16):
341 if (count != sizeof(struct disklabel) / sizeof(int))
342 return D_INVALID_SIZE;
343 /*
344 * setdisklabel is in scsi/rz_disk.c; but is generic
345 */
346 errcode = setdisklabel(lp, (struct disklabel*) data);
347 if (errcode || (flavor == DIOCSDINFO) || (flavor == DIOCSDINFO - (0x10<<16)))
348 return errcode;
349 errcode = hdwritelabel(unit);
350 break;
351 }
352 return errcode;
353 }
Cache object: 1174f1e3887df9f039b767bae693efc5
|