This source file includes following definitions.
- disksort
- dkcksum
- initdisklabel
- checkdisklabel
- readdoslabel
- setdisklabel
- bounds_check_with_label
- diskerr
- disk_init
- disk_construct
- disk_attach
- disk_detach
- disk_busy
- disk_unbusy
- disk_lock
- disk_unlock
- dk_mountroot
- bufq_default_alloc
- bufq_default_free
- bufq_default_add
- bufq_default_get
- getdisk
- parsedisk
- setroot
- findblkmajor
- findblkname
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #include <sys/fcntl.h>
46 #include <sys/buf.h>
47 #include <sys/stat.h>
48 #include <sys/syslog.h>
49 #include <sys/device.h>
50 #include <sys/time.h>
51 #include <sys/disklabel.h>
52 #include <sys/conf.h>
53 #include <sys/lock.h>
54 #include <sys/disk.h>
55 #include <sys/reboot.h>
56 #include <sys/dkio.h>
57 #include <sys/dkstat.h>
58 #include <sys/proc.h>
59 #include <uvm/uvm_extern.h>
60
61 #include <dev/rndvar.h>
62 #include <dev/cons.h>
63
64
65
66
67
68 struct disklist_head disklist;
69 int disk_count;
70 int disk_change;
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 void
92 disksort(struct buf *ap, struct buf *bp)
93 {
94 struct buf *bq;
95
96
97 if (ap->b_actf == NULL) {
98 bp->b_actf = NULL;
99 ap->b_actf = bp;
100 return;
101 }
102
103
104
105
106
107 bq = ap->b_actf;
108 if (bp->b_cylinder < bq->b_cylinder) {
109 while (bq->b_actf) {
110
111
112
113
114
115 if (bq->b_actf->b_cylinder < bq->b_cylinder) {
116
117
118
119
120
121
122 do {
123 if (bp->b_cylinder <
124 bq->b_actf->b_cylinder)
125 goto insert;
126 if (bp->b_cylinder ==
127 bq->b_actf->b_cylinder &&
128 bp->b_blkno < bq->b_actf->b_blkno)
129 goto insert;
130 bq = bq->b_actf;
131 } while (bq->b_actf);
132 goto insert;
133 }
134 bq = bq->b_actf;
135 }
136
137
138
139
140 goto insert;
141 }
142
143
144
145
146 while (bq->b_actf) {
147
148
149
150
151
152
153 if (bq->b_actf->b_cylinder < bq->b_cylinder ||
154 bp->b_cylinder < bq->b_actf->b_cylinder ||
155 (bp->b_cylinder == bq->b_actf->b_cylinder &&
156 bp->b_blkno < bq->b_actf->b_blkno))
157 goto insert;
158 bq = bq->b_actf;
159 }
160
161
162
163
164 insert: bp->b_actf = bq->b_actf;
165 bq->b_actf = bp;
166 }
167
168
169
170
171 u_int
172 dkcksum(struct disklabel *lp)
173 {
174 u_int16_t *start, *end;
175 u_int16_t sum = 0;
176
177 start = (u_int16_t *)lp;
178 end = (u_int16_t *)&lp->d_partitions[lp->d_npartitions];
179 while (start < end)
180 sum ^= *start++;
181 return (sum);
182 }
183
184 char *
185 initdisklabel(struct disklabel *lp)
186 {
187 int i;
188
189
190 if (lp->d_secsize < DEV_BSIZE)
191 lp->d_secsize = DEV_BSIZE;
192 if (DL_GETDSIZE(lp) == 0)
193 DL_SETDSIZE(lp, MAXDISKSIZE);
194 if (lp->d_secpercyl == 0)
195 return ("invalid geometry");
196 lp->d_npartitions = RAW_PART + 1;
197 for (i = 0; i < RAW_PART; i++) {
198 DL_SETPSIZE(&lp->d_partitions[i], 0);
199 DL_SETPOFFSET(&lp->d_partitions[i], 0);
200 }
201 if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) == 0)
202 DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
203 DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
204 lp->d_version = 1;
205 lp->d_bbsize = 8192;
206 lp->d_sbsize = 64*1024;
207 return (NULL);
208 }
209
210
211
212
213
214 char *
215 checkdisklabel(void *rlp, struct disklabel *lp)
216 {
217 struct disklabel *dlp = rlp;
218 struct __partitionv0 *v0pp;
219 struct partition *pp;
220 daddr64_t disksize;
221 char *msg = NULL;
222 int i;
223
224 if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
225 msg = "no disk label";
226 else if (dlp->d_npartitions > MAXPARTITIONS)
227 msg = "unreasonable partition count";
228 else if (dkcksum(dlp) != 0)
229 msg = "disk label corrupted";
230
231 if (msg) {
232 u_int16_t *start, *end, sum = 0;
233
234
235 if (swap32(dlp->d_magic) != DISKMAGIC ||
236 swap32(dlp->d_magic2) != DISKMAGIC ||
237 swap16(dlp->d_npartitions) > MAXPARTITIONS)
238 return (msg);
239
240
241
242
243
244 start = (u_int16_t *)dlp;
245 end = (u_int16_t *)&dlp->d_partitions[
246 swap16(dlp->d_npartitions)];
247 while (start < end)
248 sum ^= *start++;
249 if (sum != 0)
250 return (msg);
251
252 dlp->d_magic = swap32(dlp->d_magic);
253 dlp->d_type = swap16(dlp->d_type);
254 dlp->d_subtype = swap16(dlp->d_subtype);
255
256
257
258 dlp->d_secsize = swap32(dlp->d_secsize);
259 dlp->d_nsectors = swap32(dlp->d_nsectors);
260 dlp->d_ntracks = swap32(dlp->d_ntracks);
261 dlp->d_ncylinders = swap32(dlp->d_ncylinders);
262 dlp->d_secpercyl = swap32(dlp->d_secpercyl);
263 dlp->d_secperunit = swap32(dlp->d_secperunit);
264
265 dlp->d_sparespertrack = swap16(dlp->d_sparespertrack);
266 dlp->d_sparespercyl = swap16(dlp->d_sparespercyl);
267
268 dlp->d_acylinders = swap32(dlp->d_acylinders);
269
270 dlp->d_rpm = swap16(dlp->d_rpm);
271 dlp->d_interleave = swap16(dlp->d_interleave);
272 dlp->d_trackskew = swap16(dlp->d_trackskew);
273 dlp->d_cylskew = swap16(dlp->d_cylskew);
274 dlp->d_headswitch = swap32(dlp->d_headswitch);
275 dlp->d_trkseek = swap32(dlp->d_trkseek);
276 dlp->d_flags = swap32(dlp->d_flags);
277
278 for (i = 0; i < NDDATA; i++)
279 dlp->d_drivedata[i] = swap32(dlp->d_drivedata[i]);
280
281 dlp->d_secperunith = swap16(dlp->d_secperunith);
282 dlp->d_version = swap16(dlp->d_version);
283
284 for (i = 0; i < NSPARE; i++)
285 dlp->d_spare[i] = swap32(dlp->d_spare[i]);
286
287 dlp->d_magic2 = swap32(dlp->d_magic2);
288 dlp->d_checksum = swap16(dlp->d_checksum);
289
290 dlp->d_npartitions = swap16(dlp->d_npartitions);
291 dlp->d_bbsize = swap32(dlp->d_bbsize);
292 dlp->d_sbsize = swap32(dlp->d_sbsize);
293
294 for (i = 0; i < MAXPARTITIONS; i++) {
295 pp = &dlp->d_partitions[i];
296 pp->p_size = swap32(pp->p_size);
297 pp->p_offset = swap32(pp->p_offset);
298 if (dlp->d_version == 0) {
299 v0pp = (struct __partitionv0 *)pp;
300 v0pp->p_fsize = swap32(v0pp->p_fsize);
301 } else {
302 pp->p_offseth = swap16(pp->p_offseth);
303 pp->p_sizeh = swap16(pp->p_sizeh);
304 }
305 pp->p_cpg = swap16(pp->p_cpg);
306 }
307
308 dlp->d_checksum = 0;
309 dlp->d_checksum = dkcksum(dlp);
310 msg = NULL;
311 }
312
313
314
315 if (msg)
316 return (msg);
317
318
319 disksize = DL_GETDSIZE(lp);
320
321 if (lp != dlp)
322 *lp = *dlp;
323
324 if (lp->d_version == 0) {
325 lp->d_version = 1;
326 lp->d_secperunith = 0;
327
328 v0pp = (struct __partitionv0 *)lp->d_partitions;
329 pp = lp->d_partitions;
330 for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) {
331 pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp->
332 p_fsize, v0pp->p_frag);
333 pp->p_offseth = 0;
334 pp->p_sizeh = 0;
335 }
336 }
337
338 #ifdef DEBUG
339 if (DL_GETDSIZE(lp) != disksize)
340 printf("on-disk disklabel has incorrect disksize (%lld)\n",
341 DL_GETDSIZE(lp));
342 if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) != disksize)
343 printf("on-disk disklabel RAW_PART has incorrect size (%lld)\n",
344 DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
345 if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART]) != 0)
346 printf("on-disk disklabel RAW_PART offset != 0 (%lld)\n",
347 DL_GETPOFFSET(&lp->d_partitions[RAW_PART]));
348 #endif
349 DL_SETDSIZE(lp, disksize);
350 DL_SETPSIZE(&lp->d_partitions[RAW_PART], disksize);
351 DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
352
353 lp->d_checksum = 0;
354 lp->d_checksum = dkcksum(lp);
355 return (msg);
356 }
357
358
359
360
361
362
363
364
365
366
367 char *
368 readdoslabel(struct buf *bp, void (*strat)(struct buf *),
369 struct disklabel *lp, int *partoffp, int spoofonly)
370 {
371 struct dos_partition dp[NDOSPART], *dp2;
372 u_int32_t extoff = 0;
373 daddr64_t part_blkno = DOSBBSECTOR;
374 int dospartoff = 0, i, ourpart = -1;
375 int wander = 1, n = 0, loop = 0;
376
377 if (lp->d_secpercyl == 0)
378 return ("invalid label, d_secpercyl == 0");
379 if (lp->d_secsize == 0)
380 return ("invalid label, d_secsize == 0");
381
382
383
384
385
386
387
388 while (wander && n < 8 && loop < 8) {
389 loop++;
390 wander = 0;
391 if (part_blkno < extoff)
392 part_blkno = extoff;
393
394
395 bp->b_blkno = part_blkno;
396 bp->b_bcount = lp->d_secsize;
397 bp->b_flags = B_BUSY | B_READ;
398 (*strat)(bp);
399 if (biowait(bp)) {
400 if (partoffp)
401 *partoffp = -1;
402 return ("dos partition I/O error");
403 }
404
405 bcopy(bp->b_data + DOSPARTOFF, dp, sizeof(dp));
406
407 if (ourpart == -1 && part_blkno == DOSBBSECTOR) {
408
409 for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
410 i++, dp2++)
411 if (letoh32(dp2->dp_size) &&
412 dp2->dp_typ == DOSPTYP_OPENBSD)
413 ourpart = i;
414 if (ourpart == -1)
415 goto donot;
416
417
418
419
420
421 dp2 = &dp[ourpart];
422 dospartoff = letoh32(dp2->dp_start) + part_blkno;
423
424
425 if (partoffp)
426 goto notfat;
427
428 if (lp->d_ntracks == 0)
429 lp->d_ntracks = dp2->dp_ehd + 1;
430 if (lp->d_nsectors == 0)
431 lp->d_nsectors = DPSECT(dp2->dp_esect);
432 if (lp->d_secpercyl == 0)
433 lp->d_secpercyl = lp->d_ntracks *
434 lp->d_nsectors;
435 }
436 donot:
437
438
439
440
441 for (dp2=dp, i=0; i < NDOSPART && n < 8; i++, dp2++) {
442 struct partition *pp = &lp->d_partitions[8+n];
443
444 if (dp2->dp_typ == DOSPTYP_OPENBSD)
445 continue;
446 if (letoh32(dp2->dp_size) > DL_GETDSIZE(lp))
447 continue;
448 if (letoh32(dp2->dp_start) > DL_GETDSIZE(lp))
449 continue;
450 if (letoh32(dp2->dp_size) == 0)
451 continue;
452 if (letoh32(dp2->dp_start))
453 DL_SETPOFFSET(pp,
454 letoh32(dp2->dp_start) + part_blkno);
455
456 DL_SETPSIZE(pp, letoh32(dp2->dp_size));
457
458 switch (dp2->dp_typ) {
459 case DOSPTYP_UNUSED:
460 pp->p_fstype = FS_UNUSED;
461 n++;
462 break;
463
464 case DOSPTYP_LINUX:
465 pp->p_fstype = FS_EXT2FS;
466 n++;
467 break;
468
469 case DOSPTYP_FAT12:
470 case DOSPTYP_FAT16S:
471 case DOSPTYP_FAT16B:
472 case DOSPTYP_FAT16L:
473 case DOSPTYP_FAT32:
474 case DOSPTYP_FAT32L:
475 pp->p_fstype = FS_MSDOS;
476 n++;
477 break;
478 case DOSPTYP_EXTEND:
479 case DOSPTYP_EXTENDL:
480 part_blkno = letoh32(dp2->dp_start) + extoff;
481 if (!extoff) {
482 extoff = letoh32(dp2->dp_start);
483 part_blkno = 0;
484 }
485 wander = 1;
486 break;
487 default:
488 pp->p_fstype = FS_OTHER;
489 n++;
490 break;
491 }
492 }
493 }
494 lp->d_npartitions = MAXPARTITIONS;
495
496 if (n == 0 && part_blkno == DOSBBSECTOR) {
497 u_int16_t fattest;
498
499
500 fattest = ((bp->b_data[0] << 8) & 0xff00) |
501 (bp->b_data[2] & 0xff);
502 if (fattest != 0xeb90 && fattest != 0xe900)
503 goto notfat;
504
505
506 fattest = ((bp->b_data[12] << 8) & 0xff00) |
507 (bp->b_data[11] & 0xff);
508 if (fattest < 512 || fattest > 4096 || (fattest % 512 != 0))
509 goto notfat;
510
511
512 fattest = ((bp->b_data[510] << 8) & 0xff00) |
513 (bp->b_data[511] & 0xff);
514 if (fattest != 0x55aa)
515 goto notfat;
516
517
518 DL_SETPSIZE(&lp->d_partitions['i' - 'a'],
519 DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
520 DL_SETPOFFSET(&lp->d_partitions['i' - 'a'], 0);
521 lp->d_partitions['i' - 'a'].p_fstype = FS_MSDOS;
522 }
523 notfat:
524
525
526 if (partoffp)
527 *partoffp = dospartoff;
528
529
530 if (spoofonly)
531 return (NULL);
532
533 bp->b_blkno = dospartoff + DOS_LABELSECTOR;
534 bp->b_bcount = lp->d_secsize;
535 bp->b_flags = B_BUSY | B_READ;
536 (*strat)(bp);
537 if (biowait(bp))
538 return ("disk label I/O error");
539
540
541 return checkdisklabel(bp->b_data, lp);
542 }
543
544
545
546
547
548 int
549 setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_int openmask)
550 {
551 int i;
552 struct partition *opp, *npp;
553
554
555 if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
556 (nlp->d_secsize % DEV_BSIZE) != 0)
557 return (EINVAL);
558
559
560 if (nlp->d_magic == 0xffffffff) {
561 *olp = *nlp;
562 return (0);
563 }
564
565 if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
566 dkcksum(nlp) != 0)
567 return (EINVAL);
568
569
570
571 while (openmask != 0) {
572 i = ffs(openmask) - 1;
573 openmask &= ~(1 << i);
574 if (nlp->d_npartitions <= i)
575 return (EBUSY);
576 opp = &olp->d_partitions[i];
577 npp = &nlp->d_partitions[i];
578 if (DL_GETPOFFSET(npp) != DL_GETPOFFSET(opp) ||
579 DL_GETPSIZE(npp) < DL_GETPSIZE(opp))
580 return (EBUSY);
581
582
583
584
585 if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
586 npp->p_fstype = opp->p_fstype;
587 npp->p_fragblock = opp->p_fragblock;
588 npp->p_cpg = opp->p_cpg;
589 }
590 }
591 nlp->d_checksum = 0;
592 nlp->d_checksum = dkcksum(nlp);
593 *olp = *nlp;
594 return (0);
595 }
596
597
598
599
600
601
602 int
603 bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
604 {
605 #define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE))
606 struct partition *p = &lp->d_partitions[DISKPART(bp->b_dev)];
607 daddr64_t sz = howmany(bp->b_bcount, DEV_BSIZE);
608
609
610 if (lp->d_secpercyl == 0)
611 goto bad;
612
613
614 if (bp->b_blkno + sz > blockpersec(DL_GETPSIZE(p), lp)) {
615 sz = blockpersec(DL_GETPSIZE(p), lp) - bp->b_blkno;
616 if (sz == 0) {
617
618 bp->b_resid = bp->b_bcount;
619 return (-1);
620 }
621 if (sz < 0)
622
623 goto bad;
624
625
626 bp->b_bcount = sz << DEV_BSHIFT;
627 }
628
629
630 bp->b_cylinder = (bp->b_blkno + blockpersec(DL_GETPOFFSET(p), lp)) /
631 blockpersec(lp->d_secpercyl, lp);
632 return (1);
633
634 bad:
635 bp->b_error = EINVAL;
636 bp->b_flags |= B_ERROR;
637 return (-1);
638 }
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654 void
655 diskerr(struct buf *bp, char *dname, char *what, int pri, int blkdone,
656 struct disklabel *lp)
657 {
658 int unit = DISKUNIT(bp->b_dev), part = DISKPART(bp->b_dev);
659 int (*pr)(const char *, ...);
660 char partname = 'a' + part;
661 daddr64_t sn;
662
663 if (pri != LOG_PRINTF) {
664 static const char fmt[] = "";
665 log(pri, fmt);
666 pr = addlog;
667 } else
668 pr = printf;
669 (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
670 bp->b_flags & B_READ ? "read" : "writ");
671 sn = bp->b_blkno;
672 if (bp->b_bcount <= DEV_BSIZE)
673 (*pr)("%lld", sn);
674 else {
675 if (blkdone >= 0) {
676 sn += blkdone;
677 (*pr)("%lld of ", sn);
678 }
679 (*pr)("%lld-%lld", bp->b_blkno,
680 bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE);
681 }
682 if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
683 sn += DL_GETPOFFSET(&lp->d_partitions[part]);
684 (*pr)(" (%s%d bn %lld; cn %lld", dname, unit, sn,
685 sn / lp->d_secpercyl);
686 sn %= lp->d_secpercyl;
687 (*pr)(" tn %lld sn %lld)", sn / lp->d_nsectors,
688 sn % lp->d_nsectors);
689 }
690 }
691
692
693
694
695 void
696 disk_init(void)
697 {
698
699 TAILQ_INIT(&disklist);
700 disk_count = disk_change = 0;
701 }
702
703 int
704 disk_construct(struct disk *diskp, char *lockname)
705 {
706 rw_init(&diskp->dk_lock, lockname);
707
708 diskp->dk_flags |= DKF_CONSTRUCTED;
709
710 return (0);
711 }
712
713
714
715
716 void
717 disk_attach(struct disk *diskp)
718 {
719
720 if (!ISSET(diskp->dk_flags, DKF_CONSTRUCTED))
721 disk_construct(diskp, diskp->dk_name);
722
723
724
725
726
727
728 diskp->dk_label = malloc(sizeof(struct disklabel), M_DEVBUF, M_NOWAIT);
729 if (diskp->dk_label == NULL)
730 panic("disk_attach: can't allocate storage for disklabel");
731
732 bzero(diskp->dk_label, sizeof(struct disklabel));
733
734
735
736
737 microuptime(&diskp->dk_attachtime);
738
739
740
741
742 TAILQ_INSERT_TAIL(&disklist, diskp, dk_link);
743 ++disk_count;
744 disk_change = 1;
745 }
746
747
748
749
750 void
751 disk_detach(struct disk *diskp)
752 {
753
754
755
756
757 free(diskp->dk_label, M_DEVBUF);
758
759
760
761
762 TAILQ_REMOVE(&disklist, diskp, dk_link);
763 disk_change = 1;
764 if (--disk_count < 0)
765 panic("disk_detach: disk_count < 0");
766 }
767
768
769
770
771
772 void
773 disk_busy(struct disk *diskp)
774 {
775
776
777
778
779
780 if (diskp->dk_busy++ == 0) {
781 microuptime(&diskp->dk_timestamp);
782 }
783 }
784
785
786
787
788
789 void
790 disk_unbusy(struct disk *diskp, long bcount, int read)
791 {
792 struct timeval dv_time, diff_time;
793
794 if (diskp->dk_busy-- == 0)
795 printf("disk_unbusy: %s: dk_busy < 0\n", diskp->dk_name);
796
797 microuptime(&dv_time);
798
799 timersub(&dv_time, &diskp->dk_timestamp, &diff_time);
800 timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time);
801
802 diskp->dk_timestamp = dv_time;
803 if (bcount > 0) {
804 if (read) {
805 diskp->dk_rbytes += bcount;
806 diskp->dk_rxfer++;
807 } else {
808 diskp->dk_wbytes += bcount;
809 diskp->dk_wxfer++;
810 }
811 } else
812 diskp->dk_seek++;
813
814 add_disk_randomness(bcount ^ diff_time.tv_usec);
815 }
816
817 int
818 disk_lock(struct disk *dk)
819 {
820 int error;
821
822 error = rw_enter(&dk->dk_lock, RW_WRITE|RW_INTR);
823
824 return (error);
825 }
826
827 void
828 disk_unlock(struct disk *dk)
829 {
830 rw_exit(&dk->dk_lock);
831 }
832
833 int
834 dk_mountroot(void)
835 {
836 dev_t rawdev, rrootdev;
837 int part = DISKPART(rootdev);
838 int (*mountrootfn)(void);
839 struct disklabel dl;
840 int error;
841
842 rrootdev = blktochr(rootdev);
843 rawdev = MAKEDISKDEV(major(rrootdev), DISKUNIT(rootdev), RAW_PART);
844 #ifdef DEBUG
845 printf("rootdev=0x%x rrootdev=0x%x rawdev=0x%x\n", rootdev,
846 rrootdev, rawdev);
847 #endif
848
849
850
851
852 error = (cdevsw[major(rrootdev)].d_open)(rawdev, FREAD,
853 S_IFCHR, curproc);
854 if (error)
855 panic("cannot open disk, 0x%x/0x%x, error %d",
856 rootdev, rrootdev, error);
857 error = (cdevsw[major(rrootdev)].d_ioctl)(rawdev, DIOCGDINFO,
858 (caddr_t)&dl, FREAD, curproc);
859 if (error)
860 panic("cannot read disk label, 0x%x/0x%x, error %d",
861 rootdev, rrootdev, error);
862 (void) (cdevsw[major(rrootdev)].d_close)(rawdev, FREAD,
863 S_IFCHR, curproc);
864
865 if (DL_GETPSIZE(&dl.d_partitions[part]) == 0)
866 panic("root filesystem has size 0");
867 switch (dl.d_partitions[part].p_fstype) {
868 #ifdef EXT2FS
869 case FS_EXT2FS:
870 {
871 extern int ext2fs_mountroot(void);
872 mountrootfn = ext2fs_mountroot;
873 }
874 break;
875 #endif
876 #ifdef FFS
877 case FS_BSDFFS:
878 {
879 extern int ffs_mountroot(void);
880 mountrootfn = ffs_mountroot;
881 }
882 break;
883 #endif
884 #ifdef CD9660
885 case FS_ISO9660:
886 {
887 extern int cd9660_mountroot(void);
888 mountrootfn = cd9660_mountroot;
889 }
890 break;
891 #endif
892 default:
893 #ifdef FFS
894 {
895 extern int ffs_mountroot(void);
896
897 printf("filesystem type %d not known.. assuming ffs\n",
898 dl.d_partitions[part].p_fstype);
899 mountrootfn = ffs_mountroot;
900 }
901 #else
902 panic("disk 0x%x/0x%x filesystem type %d not known",
903 rootdev, rrootdev, dl.d_partitions[part].p_fstype);
904 #endif
905 }
906 return (*mountrootfn)();
907 }
908
909 struct bufq *
910 bufq_default_alloc(void)
911 {
912 struct bufq_default *bq;
913
914 bq = malloc(sizeof(*bq), M_DEVBUF, M_NOWAIT);
915 if (bq == NULL)
916 panic("bufq_default_alloc: no memory");
917
918 memset(bq, 0, sizeof(*bq));
919 bq->bufq.bufq_free = bufq_default_free;
920 bq->bufq.bufq_add = bufq_default_add;
921 bq->bufq.bufq_get = bufq_default_get;
922
923 return ((struct bufq *)bq);
924 }
925
926 void
927 bufq_default_free(struct bufq *bq)
928 {
929 free(bq, M_DEVBUF);
930 }
931
932 void
933 bufq_default_add(struct bufq *bq, struct buf *bp)
934 {
935 struct bufq_default *bufq = (struct bufq_default *)bq;
936 struct proc *p = bp->b_proc;
937 struct buf *head;
938
939 if (p == NULL || p->p_nice < NZERO)
940 head = &bufq->bufq_head[0];
941 else if (p->p_nice == NZERO)
942 head = &bufq->bufq_head[1];
943 else
944 head = &bufq->bufq_head[2];
945
946 disksort(head, bp);
947 }
948
949 struct buf *
950 bufq_default_get(struct bufq *bq)
951 {
952 struct bufq_default *bufq = (struct bufq_default *)bq;
953 struct buf *bp, *head;
954 int i;
955
956 for (i = 0; i < 3; i++) {
957 head = &bufq->bufq_head[i];
958 if ((bp = head->b_actf))
959 break;
960 }
961 if (bp == NULL)
962 return (NULL);
963 head->b_actf = bp->b_actf;
964 return (bp);
965 }
966
967 #ifdef RAMDISK_HOOKS
968 static struct device fakerdrootdev = { DV_DISK, {}, NULL, 0, "rd0", NULL };
969 #endif
970
971 struct device *
972 getdisk(char *str, int len, int defpart, dev_t *devp)
973 {
974 struct device *dv;
975
976 if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
977 printf("use one of: exit");
978 #ifdef RAMDISK_HOOKS
979 printf(" %s[a-p]", fakerdrootdev.dv_xname);
980 #endif
981 TAILQ_FOREACH(dv, &alldevs, dv_list) {
982 if (dv->dv_class == DV_DISK)
983 printf(" %s[a-p]", dv->dv_xname);
984 #if defined(NFSCLIENT)
985 if (dv->dv_class == DV_IFNET)
986 printf(" %s", dv->dv_xname);
987 #endif
988 }
989 printf("\n");
990 }
991 return (dv);
992 }
993
994 struct device *
995 parsedisk(char *str, int len, int defpart, dev_t *devp)
996 {
997 struct device *dv;
998 char c;
999 int majdev, part;
1000
1001 if (len == 0)
1002 return (NULL);
1003 c = str[len-1];
1004 if (c >= 'a' && (c - 'a') < MAXPARTITIONS) {
1005 part = c - 'a';
1006 len -= 1;
1007 } else
1008 part = defpart;
1009
1010 #ifdef RAMDISK_HOOKS
1011 if (strcmp(str, fakerdrootdev.dv_xname) == 0) {
1012 dv = &fakerdrootdev;
1013 goto gotdisk;
1014 }
1015 #endif
1016
1017 TAILQ_FOREACH(dv, &alldevs, dv_list) {
1018 if (dv->dv_class == DV_DISK &&
1019 strncmp(str, dv->dv_xname, len) == 0 &&
1020 dv->dv_xname[len] == '\0') {
1021 #ifdef RAMDISK_HOOKS
1022 gotdisk:
1023 #endif
1024 majdev = findblkmajor(dv);
1025 if (majdev < 0)
1026 panic("parsedisk");
1027 *devp = MAKEDISKDEV(majdev, dv->dv_unit, part);
1028 break;
1029 }
1030 #if defined(NFSCLIENT)
1031 if (dv->dv_class == DV_IFNET &&
1032 strncmp(str, dv->dv_xname, len) == 0 &&
1033 dv->dv_xname[len] == '\0') {
1034 *devp = NODEV;
1035 break;
1036 }
1037 #endif
1038 }
1039
1040 return (dv);
1041 }
1042
1043 void
1044 setroot(struct device *bootdv, int part, int exitflags)
1045 {
1046 int majdev, unit, len, s;
1047 struct swdevt *swp;
1048 struct device *rootdv, *dv;
1049 dev_t nrootdev, nswapdev = NODEV, temp = NODEV;
1050 char buf[128];
1051 #if defined(NFSCLIENT)
1052 extern char *nfsbootdevname;
1053 #endif
1054
1055 if (boothowto & RB_DFLTROOT)
1056 return;
1057
1058 #ifdef RAMDISK_HOOKS
1059 bootdv = &fakerdrootdev;
1060 mountroot = NULL;
1061 part = 0;
1062 #endif
1063
1064
1065
1066
1067
1068 if (mountroot == NULL && bootdv == NULL)
1069 boothowto |= RB_ASKNAME;
1070 if (boothowto & RB_ASKNAME) {
1071 while (1) {
1072 printf("root device");
1073 if (bootdv != NULL) {
1074 printf(" (default %s", bootdv->dv_xname);
1075 if (bootdv->dv_class == DV_DISK)
1076 printf("%c", 'a' + part);
1077 printf(")");
1078 }
1079 printf(": ");
1080 s = splhigh();
1081 cnpollc(TRUE);
1082 len = getsn(buf, sizeof(buf));
1083 cnpollc(FALSE);
1084 splx(s);
1085 if (strcmp(buf, "exit") == 0)
1086 boot(exitflags);
1087 if (len == 0 && bootdv != NULL) {
1088 strlcpy(buf, bootdv->dv_xname, sizeof buf);
1089 len = strlen(buf);
1090 }
1091 if (len > 0 && buf[len - 1] == '*') {
1092 buf[--len] = '\0';
1093 dv = getdisk(buf, len, part, &nrootdev);
1094 if (dv != NULL) {
1095 rootdv = dv;
1096 nswapdev = nrootdev;
1097 goto gotswap;
1098 }
1099 }
1100 dv = getdisk(buf, len, part, &nrootdev);
1101 if (dv != NULL) {
1102 rootdv = dv;
1103 break;
1104 }
1105 }
1106
1107 if (rootdv->dv_class == DV_IFNET)
1108 goto gotswap;
1109
1110
1111 while (1) {
1112 printf("swap device");
1113 if (rootdv != NULL)
1114 printf(" (default %s%s)", rootdv->dv_xname,
1115 rootdv->dv_class == DV_DISK ? "b" : "");
1116 printf(": ");
1117 s = splhigh();
1118 cnpollc(TRUE);
1119 len = getsn(buf, sizeof(buf));
1120 cnpollc(FALSE);
1121 splx(s);
1122 if (strcmp(buf, "exit") == 0)
1123 boot(exitflags);
1124 if (len == 0 && rootdv != NULL) {
1125 switch (rootdv->dv_class) {
1126 case DV_IFNET:
1127 nswapdev = NODEV;
1128 break;
1129 case DV_DISK:
1130 nswapdev = MAKEDISKDEV(major(nrootdev),
1131 DISKUNIT(nrootdev), 1);
1132 if (nswapdev == nrootdev)
1133 continue;
1134 break;
1135 default:
1136 break;
1137 }
1138 break;
1139 }
1140 dv = getdisk(buf, len, 1, &nswapdev);
1141 if (dv) {
1142 if (dv->dv_class == DV_IFNET)
1143 nswapdev = NODEV;
1144 if (nswapdev == nrootdev)
1145 continue;
1146 break;
1147 }
1148 }
1149 gotswap:
1150 rootdev = nrootdev;
1151 dumpdev = nswapdev;
1152 swdevt[0].sw_dev = nswapdev;
1153 swdevt[1].sw_dev = NODEV;
1154 #if defined(NFSCLIENT)
1155 } else if (mountroot == nfs_mountroot) {
1156 rootdv = bootdv;
1157 rootdev = dumpdev = swapdev = NODEV;
1158 #endif
1159 } else if (mountroot == NULL) {
1160
1161 rootdv = bootdv;
1162 majdev = findblkmajor(rootdv);
1163 if (majdev >= 0) {
1164
1165
1166
1167
1168 rootdev = MAKEDISKDEV(majdev, rootdv->dv_unit, part);
1169 nswapdev = MAKEDISKDEV(majdev, rootdv->dv_unit, 1);
1170 } else {
1171
1172
1173
1174 nswapdev = NODEV;
1175 }
1176 dumpdev = nswapdev;
1177 swdevt[0].sw_dev = nswapdev;
1178
1179 } else {
1180
1181 majdev = major(rootdev);
1182 if (findblkname(majdev) == NULL)
1183 return;
1184 unit = DISKUNIT(rootdev);
1185 part = DISKPART(rootdev);
1186 snprintf(buf, sizeof buf, "%s%d%c",
1187 findblkname(majdev), unit, 'a' + part);
1188 rootdv = parsedisk(buf, strlen(buf), 0, &nrootdev);
1189 }
1190
1191 switch (rootdv->dv_class) {
1192 #if defined(NFSCLIENT)
1193 case DV_IFNET:
1194 mountroot = nfs_mountroot;
1195 nfsbootdevname = rootdv->dv_xname;
1196 return;
1197 #endif
1198 case DV_DISK:
1199 mountroot = dk_mountroot;
1200 part = DISKPART(rootdev);
1201 break;
1202 default:
1203 printf("can't figure root, hope your kernel is right\n");
1204 return;
1205 }
1206
1207 printf("root on %s%c", rootdv->dv_xname, 'a' + part);
1208
1209
1210
1211
1212 for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
1213 if (major(rootdev) == major(swp->sw_dev) &&
1214 DISKUNIT(rootdev) == DISKUNIT(swp->sw_dev)) {
1215 temp = swdevt[0].sw_dev;
1216 swdevt[0].sw_dev = swp->sw_dev;
1217 swp->sw_dev = temp;
1218 break;
1219 }
1220 }
1221 if (swp->sw_dev != NODEV) {
1222
1223
1224
1225
1226 if (temp == dumpdev)
1227 dumpdev = swdevt[0].sw_dev;
1228 }
1229 if (swdevt[0].sw_dev != NODEV)
1230 printf(" swap on %s%d%c", findblkname(major(swdevt[0].sw_dev)),
1231 DISKUNIT(swdevt[0].sw_dev),
1232 'a' + DISKPART(swdevt[0].sw_dev));
1233 if (dumpdev != NODEV)
1234 printf(" dump on %s%d%c", findblkname(major(dumpdev)),
1235 DISKUNIT(dumpdev), 'a' + DISKPART(dumpdev));
1236 printf("\n");
1237 }
1238
1239 extern struct nam2blk nam2blk[];
1240
1241 int
1242 findblkmajor(struct device *dv)
1243 {
1244 char *name = dv->dv_xname;
1245 int i;
1246
1247 for (i = 0; nam2blk[i].name; i++)
1248 if (!strncmp(name, nam2blk[i].name, strlen(nam2blk[i].name)))
1249 return (nam2blk[i].maj);
1250 return (-1);
1251 }
1252
1253 char *
1254 findblkname(int maj)
1255 {
1256 int i;
1257
1258 for (i = 0; nam2blk[i].name; i++)
1259 if (nam2blk[i].maj == maj)
1260 return (nam2blk[i].name);
1261 return (NULL);
1262 }