1 /* $NetBSD: disks.c,v 1.109 2009/10/18 12:09:48 ahoka Exp $ */
4 * Copyright 1997 Piermont Information Systems Inc.
7 * Written by Philip A. Nelson for Piermont Information Systems Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Piermont Information Systems Inc.
21 * 4. The name of Piermont Information Systems Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35 * THE POSSIBILITY OF SUCH DAMAGE.
39 /* disks.c -- routines to deal with finding disks and labeling disks. */
49 #include <sys/param.h>
51 #include <ufs/ufs/dinode.h>
52 #include <ufs/ffs/fs.h>
56 #include <sys/disklabel.h>
59 #include <dev/scsipi/scsipi_all.h>
60 #include <sys/scsiio.h>
62 #include <dev/ata/atareg.h>
63 #include <sys/ataio.h>
68 #include "menu_defs.h"
71 /* Disk descriptions */
74 char dd_name
[SSTRSIZE
];
84 /* Local prototypes */
85 static int foundffs(struct data
*, size_t);
87 static int foundsysvbfs(struct data
*, size_t);
89 static int fsck_preen(const char *, int, const char *);
90 static void fixsb(const char *, const char *, char);
93 #define DISK_NAMES "wd", "sd", "ld", "raid"
96 static const char *disk_names
[] = { DISK_NAMES
, "vnd", NULL
};
98 /* from src/sbin/atactl/atactl.c
99 * extract_string: copy a block of bytes out of ataparams and make
100 * a proper string out of it, truncating trailing spaces and preserving
101 * strict typing. And also, not doing unaligned accesses.
104 ata_extract_string(char *buf
, size_t bufmax
,
105 uint8_t *bytes
, unsigned numbytes
,
110 unsigned char ch1
, ch2
;
112 for (i
= 0, j
= 0; i
< numbytes
; i
+= 2) {
115 if (needswap
&& j
< bufmax
-1) {
121 if (!needswap
&& j
< bufmax
-1) {
125 while (j
> 0 && buf
[j
-1] == ' ') {
132 * from src/sbin/scsictl/scsi_subr.c
134 #define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377')
137 scsi_strvis(char *sdst
, size_t dlen
, const char *ssrc
, size_t slen
)
139 u_char
*dst
= (u_char
*)sdst
;
140 const u_char
*src
= (const u_char
*)ssrc
;
142 /* Trim leading and trailing blanks and NULs. */
143 while (slen
> 0 && STRVIS_ISWHITE(src
[0]))
145 while (slen
> 0 && STRVIS_ISWHITE(src
[slen
- 1]))
149 if (*src
< 0x20 || *src
>= 0x80) {
150 /* non-printable characters */
155 *dst
++ = ((*src
& 0300) >> 6) + '0';
156 *dst
++ = ((*src
& 0070) >> 3) + '0';
157 *dst
++ = ((*src
& 0007) >> 0) + '0';
158 } else if (*src
== '\\') {
159 /* quote characters */
166 /* normal characters */
179 get_descr_scsi(struct disk_desc
*dd
, int fd
)
181 struct scsipi_inquiry_data inqbuf
;
182 struct scsipi_inquiry cmd
;
184 /* x4 in case every character is escaped, +1 for NUL. */
185 char vendor
[(sizeof(inqbuf
.vendor
) * 4) + 1],
186 product
[(sizeof(inqbuf
.product
) * 4) + 1],
187 revision
[(sizeof(inqbuf
.revision
) * 4) + 1];
191 memset(&inqbuf
, 0, sizeof(inqbuf
));
192 memset(&cmd
, 0, sizeof(cmd
));
193 memset(&req
, 0, sizeof(req
));
195 cmd
.opcode
= INQUIRY
;
196 cmd
.length
= sizeof(inqbuf
);
197 memcpy(req
.cmd
, &cmd
, sizeof(cmd
));
198 req
.cmdlen
= sizeof(cmd
);
199 req
.databuf
= &inqbuf
;
200 req
.datalen
= sizeof(inqbuf
);
202 req
.flags
= SCCMD_READ
;
203 req
.senselen
= SENSEBUFLEN
;
205 error
= ioctl(fd
, SCIOCCOMMAND
, &req
);
206 if (error
== -1 || req
.retsts
!= SCCMD_OK
)
209 scsi_strvis(vendor
, sizeof(vendor
), inqbuf
.vendor
,
210 sizeof(inqbuf
.vendor
));
211 scsi_strvis(product
, sizeof(product
), inqbuf
.product
,
212 sizeof(inqbuf
.product
));
213 scsi_strvis(revision
, sizeof(revision
), inqbuf
.revision
,
214 sizeof(inqbuf
.revision
));
216 humanize_number(size
, sizeof(size
),
217 (uint64_t)dd
->dd_secsize
* (uint64_t)dd
->dd_totsec
,
218 "", HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
);
220 snprintf(dd
->dd_descr
, sizeof(dd
->dd_descr
),
222 dd
->dd_name
, size
, vendor
, product
);
228 get_descr_ata(struct disk_desc
*dd
, int fd
)
232 unsigned char inbuf
[DEV_BSIZE
];
233 struct ataparams inqbuf
;
235 struct ataparams
*inqbuf
= &inbuf
.inqbuf
;
236 char model
[sizeof(inqbuf
->atap_model
)+1];
238 int error
, needswap
= 0;
240 memset(&inbuf
, 0, sizeof(inbuf
));
241 memset(&req
, 0, sizeof(req
));
243 req
.flags
= ATACMD_READ
;
244 req
.command
= WDCC_IDENTIFY
;
245 req
.databuf
= (void *)&inbuf
;
246 req
.datalen
= sizeof(inbuf
);
249 error
= ioctl(fd
, ATAIOCCOMMAND
, &req
);
250 if (error
== -1 || req
.retsts
!= ATACMD_OK
)
253 #if BYTE_ORDER == LITTLE_ENDIAN
255 * On little endian machines, we need to shuffle the string
256 * byte order. However, we don't have to do this for NEC or
257 * Mitsumi ATAPI devices
260 if (!((inqbuf
->atap_config
& WDC_CFG_ATAPI_MASK
) == WDC_CFG_ATAPI
&&
261 ((inqbuf
->atap_model
[0] == 'N' &&
262 inqbuf
->atap_model
[1] == 'E') ||
263 (inqbuf
->atap_model
[0] == 'F' &&
264 inqbuf
->atap_model
[1] == 'X')))) {
269 ata_extract_string(model
, sizeof(model
),
270 inqbuf
->atap_model
, sizeof(inqbuf
->atap_model
), needswap
);
271 humanize_number(size
, sizeof(size
),
272 (uint64_t)dd
->dd_secsize
* (uint64_t)dd
->dd_totsec
,
273 "", HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
);
275 snprintf(dd
->dd_descr
, sizeof(dd
->dd_descr
), "%s (%s, %s)",
276 dd
->dd_name
, size
, model
);
282 get_descr(struct disk_desc
*dd
)
284 char diskpath
[MAXPATHLEN
];
287 fd
= opendisk(dd
->dd_name
, O_RDONLY
, diskpath
, sizeof(diskpath
), 0);
291 dd
->dd_descr
[0] = '\0';
294 if (get_descr_ata(dd
, fd
))
297 if (get_descr_scsi(dd
, fd
))
303 if (strlen(dd
->dd_descr
) == 0)
304 strcpy(dd
->dd_descr
, dd
->dd_name
);
308 get_disks(struct disk_desc
*dd
)
319 for (xd
= disk_names
; *xd
!= NULL
; xd
++) {
320 for (i
= 0; i
< MAX_DISKS
; i
++) {
321 strlcpy(dd
->dd_name
, *xd
, sizeof dd
->dd_name
- 2);
322 cp
= strchr(dd
->dd_name
, ':');
324 dd
->dd_no_mbr
= !strcmp(cp
, ":no_mbr");
327 cp
= strchr(dd
->dd_name
, 0);
330 snprintf(cp
, 2 + 1, "%d", i
);
331 if (!get_geom(dd
->dd_name
, &l
)) {
336 dd
->dd_cyl
= l
.d_ncylinders
;
337 dd
->dd_head
= l
.d_ntracks
;
338 dd
->dd_sec
= l
.d_nsectors
;
339 dd
->dd_secsize
= l
.d_secsize
;
340 dd
->dd_totsec
= l
.d_secperunit
;
344 if (numdisks
>= MAX_DISKS
)
352 set_dsk_select(menudesc
*m
, void *arg
)
354 *(int *)arg
= m
->cursel
;
359 find_disks(const char *doingwhat
)
361 struct disk_desc disks
[MAX_DISKS
];
362 menu_ent dsk_menu
[nelem(disks
)];
363 struct disk_desc
*disk
;
366 int selected_disk
= 0;
370 numdisks
= get_disks(disks
);
372 /* need a redraw here, kernel messages hose everything */
375 /* Kill typeahead, it won't be what the user had in mind */
379 /* No disks found! */
380 msg_display(MSG_nodisk
);
381 process_menu(MENU_ok
, NULL
);
387 /* One disk found! */
388 msg_display(MSG_onedisk
, disks
[0].dd_descr
, doingwhat
);
389 process_menu(MENU_ok
, NULL
);
391 /* Multiple disks found! */
392 for (i
= 0; i
< numdisks
; i
++) {
393 dsk_menu
[i
].opt_name
= disks
[i
].dd_descr
;
394 dsk_menu
[i
].opt_menu
= OPT_NOMENU
;
395 dsk_menu
[i
].opt_flags
= OPT_EXIT
;
396 dsk_menu
[i
].opt_action
= set_dsk_select
;
398 menu_no
= new_menu(MSG_Available_disks
,
399 dsk_menu
, numdisks
, -1, 4, 0, 0,
400 MC_SCROLL
| MC_NOEXITOPT
,
401 NULL
, NULL
, NULL
, NULL
, NULL
);
404 msg_display(MSG_ask_disk
);
405 process_menu(menu_no
, &selected_disk
);
409 disk
= disks
+ selected_disk
;
410 strlcpy(diskdev
, disk
->dd_name
, sizeof diskdev
);
412 /* Use as a default disk if the user has the sets on a local disk */
413 strlcpy(localfs_dev
, disk
->dd_name
, sizeof localfs_dev
);
415 sectorsize
= disk
->dd_secsize
;
416 dlcyl
= disk
->dd_cyl
;
417 dlhead
= disk
->dd_head
;
418 dlsec
= disk
->dd_sec
;
419 dlsize
= disk
->dd_totsec
;
420 no_mbr
= disk
->dd_no_mbr
;
422 dlsize
= disk
->dd_cyl
* disk
->dd_head
* disk
->dd_sec
;
423 if (dlsize
> UINT32_MAX
) {
424 msg_display(MSG_toobigdisklabel
);
425 process_menu(MENU_ok
, NULL
);
428 dlcylsize
= dlhead
* dlsec
;
430 /* Get existing/default label */
431 memset(&oldlabel
, 0, sizeof oldlabel
);
432 incorelabel(diskdev
, oldlabel
);
434 /* Set 'target' label to current label in case we don't change it */
435 memcpy(&bsdlabel
, &oldlabel
, sizeof bsdlabel
);
441 fmt_fspart(menudesc
*m
, int ptn
, void *arg
)
443 unsigned int poffset
, psize
, pend
;
445 static const char *Yes
, *No
;
446 partinfo
*p
= bsdlabel
+ ptn
;
449 Yes
= msg_string(MSG_Yes
);
450 No
= msg_string(MSG_No
);
453 poffset
= p
->pi_offset
/ sizemult
;
454 psize
= p
->pi_size
/ sizemult
;
458 pend
= (p
->pi_offset
+ p
->pi_size
) / sizemult
- 1;
460 if (p
->pi_fstype
== FS_BSDFFS
)
461 if (p
->pi_flags
& PIF_FFSv2
)
466 desc
= fstypenames
[p
->pi_fstype
];
469 if (ptn
== PART_BOOT
)
470 desc
= msg_string(MSG_Boot_partition_cant_change
);
472 if (ptn
== getrawpartition())
473 desc
= msg_string(MSG_Whole_disk_cant_change
);
476 desc
= msg_string(MSG_NetBSD_partition_cant_change
);
479 wprintw(m
->mw
, msg_string(MSG_fspart_row
),
480 poffset
, pend
, psize
, desc
,
481 p
->pi_flags
& PIF_NEWFS
? Yes
: "",
482 p
->pi_flags
& PIF_MOUNT
? Yes
: "",
487 * Label a disk using an MD-specific string DISKLABEL_CMD for
488 * to invoke disklabel.
489 * if MD code does not define DISKLABEL_CMD, this is a no-op.
491 * i386 port uses "/sbin/disklabel -w -r", just like i386
492 * miniroot scripts, though this may leave a bogus incore label.
494 * Sun ports should use DISKLABEL_CMD "/sbin/disklabel -w"
495 * to get incore to ondisk inode translation for the Sun proms.
498 write_disklabel (void)
502 /* disklabel the disk */
503 return run_program(RUN_DISPLAY
, "%s -f /tmp/disktab %s '%s'",
504 DISKLABEL_CMD
, diskdev
, bsddiskname
);
512 ptn_sort(const void *a
, const void *b
)
514 return strcmp(bsdlabel
[*(const int *)a
].pi_mount
,
515 bsdlabel
[*(const int *)b
].pi_mount
);
519 make_filesystems(void)
523 int ptn_order
[nelem(bsdlabel
)];
525 unsigned int maxpart
= getmaxpartitions();
527 const char *mnt_opts
;
531 if (maxpart
> nelem(bsdlabel
))
532 maxpart
= nelem(bsdlabel
);
534 /* Making new file systems and mounting them */
536 /* sort to ensure /usr/local is mounted after /usr (etc) */
537 for (i
= 0; i
< maxpart
; i
++)
539 qsort(ptn_order
, maxpart
, sizeof ptn_order
[0], ptn_sort
);
541 for (i
= 0; i
< maxpart
; i
++) {
543 * newfs and mount. For now, process only BSD filesystems.
544 * but if this is the mounted-on root, has no mount
545 * point defined, or is marked preserve, don't touch it!
548 lbl
= bsdlabel
+ ptn
;
550 if (is_active_rootpart(diskdev
, ptn
))
553 if (*lbl
->pi_mount
== 0)
560 switch (lbl
->pi_fstype
) {
562 asprintf(&newfs
, "/sbin/newfs %s%.0d",
563 lbl
->pi_isize
!= 0 ? "-i" : "", lbl
->pi_isize
);
564 mnt_opts
= "-tffs -o async";
569 "/sbin/newfs -V2 -O %d -b %d -f %d%s%.0d",
570 lbl
->pi_flags
& PIF_FFSv2
? 2 : 1,
571 lbl
->pi_fsize
* lbl
->pi_frag
, lbl
->pi_fsize
,
572 lbl
->pi_isize
!= 0 ? " -i " : "", lbl
->pi_isize
);
573 if (lbl
->pi_flags
& PIF_LOG
)
574 mnt_opts
= "-tffs -o log";
576 mnt_opts
= "-tffs -o async";
580 asprintf(&newfs
, "/sbin/newfs_lfs -b %d",
581 lbl
->pi_fsize
* lbl
->pi_frag
);
586 #ifdef USE_NEWFS_MSDOS
587 asprintf(&newfs
, "/sbin/newfs_msdos");
589 mnt_opts
= "-tmsdos";
594 asprintf(&newfs
, "/sbin/newfs_sysvbfs");
595 mnt_opts
= "-tsysvbfs";
601 asprintf(&newfs
, "/sbin/newfs_ext2fs");
602 mnt_opts
= "-text2fs";
607 if (lbl
->pi_flags
& PIF_NEWFS
&& newfs
!= NULL
) {
608 #ifdef USE_NEWFS_MSDOS
609 if (lbl
->pi_fstype
== FS_MSDOS
) {
610 /* newfs only if mount fails */
611 if (run_program(RUN_SILENT
| RUN_ERROR_OK
,
612 "mount -rt msdos /dev/%s%c /mnt2",
613 diskdev
, 'a' + ptn
) != 0)
615 RUN_DISPLAY
| RUN_PROGRESS
,
617 newfs
, diskdev
, 'a' + ptn
);
619 run_program(RUN_SILENT
| RUN_ERROR_OK
,
625 error
= run_program(RUN_DISPLAY
| RUN_PROGRESS
,
626 "%s /dev/r%s%c", newfs
, diskdev
, 'a' + ptn
);
628 /* We'd better check it isn't dirty */
629 error
= fsck_preen(diskdev
, ptn
, fsname
);
635 if (lbl
->pi_flags
& PIF_MOUNT
&& mnt_opts
!= NULL
) {
636 make_target_dir(lbl
->pi_mount
);
637 error
= target_mount(mnt_opts
, diskdev
, ptn
,
640 msg_display(MSG_mountfail
,
641 diskdev
, 'a' + ptn
, lbl
->pi_mount
);
642 process_menu(MENU_ok
, NULL
);
654 int i
, swap_dev
= -1;
655 const char *dump_dev
;
657 /* Create the fstab. */
658 make_target_dir("/etc");
659 f
= target_fopen("/etc/fstab", "w");
662 "Creating %s/etc/fstab.\n", target_prefix());
663 scripting_fprintf(NULL
, "cat <<EOF >%s/etc/fstab\n", target_prefix());
667 msg_display(MSG_createfstab
);
669 (void)fprintf(logfp
, "Failed to make /etc/fstab!\n");
670 process_menu(MENU_ok
, NULL
);
677 scripting_fprintf(f
, "# NetBSD /etc/fstab\n# See /usr/share/examples/"
678 "fstab/ for more examples.\n", target_prefix());
679 for (i
= 0; i
< getmaxpartitions(); i
++) {
681 const char *mp
= bsdlabel
[i
].pi_mount
;
682 const char *fstype
= "ffs";
683 int fsck_pass
= 0, dump_freq
= 0;
687 * No mount point specified, comment out line and
688 * use /mnt as a placeholder for the mount point.
694 switch (bsdlabel
[i
].pi_fstype
) {
698 /* If there is no LFS, just comment it out. */
699 if (!check_lfs_progs())
704 fsck_pass
= (strcmp(mp
, "/") == 0) ? 1 : 2;
711 if (swap_dev
== -1) {
717 scripting_fprintf(f
, "/dev/%s%c\t\tnone\tswap\tsw%s\t\t 0 0\n",
718 diskdev
, 'a' + i
, dump_dev
);
723 make_target_dir("/stand");
731 /* The code that remounts root rw doesn't check the partition */
732 if (strcmp(mp
, "/") == 0 && !(bsdlabel
[i
].pi_flags
& PIF_MOUNT
))
736 "%s/dev/%s%c\t\t%s\t%s\trw%s%s%s%s%s%s%s%s\t\t %d %d\n",
737 s
, diskdev
, 'a' + i
, mp
, fstype
,
738 bsdlabel
[i
].pi_flags
& PIF_LOG
? ",log" : "",
739 bsdlabel
[i
].pi_flags
& PIF_MOUNT
? "" : ",noauto",
740 bsdlabel
[i
].pi_flags
& PIF_ASYNC
? ",async" : "",
741 bsdlabel
[i
].pi_flags
& PIF_NOATIME
? ",noatime" : "",
742 bsdlabel
[i
].pi_flags
& PIF_NODEV
? ",nodev" : "",
743 bsdlabel
[i
].pi_flags
& PIF_NODEVMTIME
? ",nodevmtime" : "",
744 bsdlabel
[i
].pi_flags
& PIF_NOEXEC
? ",noexec" : "",
745 bsdlabel
[i
].pi_flags
& PIF_NOSUID
? ",nosuid" : "",
746 dump_freq
, fsck_pass
);
749 if (tmp_ramdisk_size
!= 0) {
751 scripting_fprintf(f
, "tmpfs\t\t/tmp\ttmpfs\trw,-m=1777,-s=%d\n",
752 tmp_ramdisk_size
* 512);
755 scripting_fprintf(f
, "/dev/%s%c\t\t/tmp\tmfs\trw,-s=%d\n",
756 diskdev
, 'a' + swap_dev
, tmp_ramdisk_size
);
758 scripting_fprintf(f
, "swap\t\t/tmp\tmfs\trw,-s=%d\n",
763 /* Add /kern, /proc and /dev/pts to fstab and make mountpoint. */
764 scripting_fprintf(f
, "kernfs\t\t/kern\tkernfs\trw\n");
765 scripting_fprintf(f
, "ptyfs\t\t/dev/pts\tptyfs\trw\n");
766 scripting_fprintf(f
, "procfs\t\t/proc\tprocfs\trw\n");
767 scripting_fprintf(f
, "/dev/cd0a\t\t/cdrom\tcd9660\tro,noauto\n");
768 make_target_dir("/kern");
769 make_target_dir("/proc");
770 make_target_dir("/dev/pts");
771 make_target_dir("/cdrom");
773 scripting_fprintf(NULL
, "EOF\n");
786 foundffs(struct data
*list
, size_t num
)
790 if (num
< 2 || strcmp(list
[1].u
.s_val
, "/") == 0 ||
791 strstr(list
[2].u
.s_val
, "noauto") != NULL
)
794 error
= fsck_preen(list
[0].u
.s_val
, ' '-'a', "ffs");
798 error
= target_mount("", list
[0].u
.s_val
, ' '-'a', list
[1].u
.s_val
);
807 foundsysvbfs(struct data
*list
, size_t num
)
811 if (num
< 2 || strcmp(list
[1].u
.s_val
, "/") == 0 ||
812 strstr(list
[2].u
.s_val
, "noauto") != NULL
)
815 error
= target_mount("", list
[0].u
.s_val
, ' '-'a', list
[1].u
.s_val
);
823 * Do an fsck. On failure, inform the user by showing a warning
824 * message and doing menu_ok() before proceeding.
825 * Returns 0 on success, or nonzero return code from fsck() on failure.
828 fsck_preen(const char *disk
, int ptn
, const char *fsname
)
836 /* first check fsck program exists, if not assue ok */
837 asprintf(&prog
, "/sbin/fsck_%s", fsname
);
840 if (access(prog
, X_OK
) != 0)
842 if (!strcmp(fsname
,"ffs"))
843 fixsb(prog
, disk
, ptn
);
844 error
= run_program(0, "%s -p -q /dev/r%s%c", prog
, disk
, ptn
);
847 msg_display(MSG_badfs
, disk
, ptn
, error
);
848 process_menu(MENU_ok
, NULL
);
849 /* XXX at this point maybe we should run a full fsck? */
854 /* This performs the same function as the etc/rc.d/fixsb script
855 * which attempts to correct problems with ffs1 filesystems
856 * which may have been introduced by booting a netbsd-current kernel
857 * from between April of 2003 and January 2004. For more information
858 * This script was developed as a response to NetBSD pr install/25138
859 * Additional prs regarding the original issue include:
860 * bin/17910 kern/21283 kern/21404 port-macppc/23925 port-macppc/23926
863 fixsb(const char *prog
, const char *disk
, char ptn
)
869 char buf
[SBLOCKSIZE
];
871 struct fs
*fs
= &sblk
.fs
;
873 snprintf(sblk
.buf
, sizeof(sblk
.buf
), "/dev/r%s%c",
874 disk
, ptn
== ' ' ? 0 : ptn
);
875 fd
= open(sblk
.buf
, O_RDONLY
);
879 /* Read ffsv1 main superblock */
880 rval
= pread(fd
, sblk
.buf
, sizeof sblk
.buf
, SBLOCK_UFS1
);
882 if (rval
!= sizeof sblk
.buf
)
885 if (fs
->fs_magic
!= FS_UFS1_MAGIC
&&
886 fs
->fs_magic
!= FS_UFS1_MAGIC_SWAPPED
)
889 if (fs
->fs_old_flags
& FS_FLAGS_UPDATED
)
890 /* properly updated fslevel 4 */
892 if (fs
->fs_bsize
!= fs
->fs_maxbsize
)
897 * OK we have a munged fs, first 'upgrade' to fslevel 4,
898 * We specify -b16 in order to stop fsck bleating that the
899 * sb doesn't match the first alternate.
901 run_program(RUN_DISPLAY
| RUN_PROGRESS
,
902 "%s -p -b 16 -c 4 /dev/r%s%c", prog
, disk
, ptn
);
903 /* Then downgrade to fslevel 3 */
904 run_program(RUN_DISPLAY
| RUN_PROGRESS
,
905 "%s -p -c 3 /dev/r%s%c", prog
, disk
, ptn
);
909 * fsck and mount the root partition.
916 error
= fsck_preen(diskdev
, rootpart
, "ffs");
920 /* Mount /dev/<diskdev>a on target's "".
921 * If we pass "" as mount-on, Prefixing will DTRT.
922 * for now, use no options.
923 * XXX consider -o remount in case target root is
924 * current root, still readonly from single-user?
926 return target_mount("", diskdev
, rootpart
, "");
929 /* Get information on the file systems mounted from the root filesystem.
930 * Offer to convert them into 4.4BSD inodes if they are not 4.4BSD
931 * inodes. Fsck them. Mount them.
941 static struct lookfor fstabbuf
[] = {
942 {"/dev/", "/dev/%s %s ffs %s", "c", NULL
, 0, 0, foundffs
},
943 {"/dev/", "/dev/%s %s ufs %s", "c", NULL
, 0, 0, foundffs
},
945 {"/dev/", "/dev/%s %s sysvbfs %s", "c", NULL
, 0, 0,
949 static size_t numfstabbuf
= sizeof(fstabbuf
) / sizeof(struct lookfor
);
951 /* First the root device. */
952 if (target_already_root())
953 /* avoid needing to call target_already_root() again */
954 targetroot_mnt
[0] = 0;
956 error
= mount_root();
957 if (error
!= 0 && error
!= EBUSY
)
961 /* Check the target /etc/fstab exists before trying to parse it. */
962 if (target_dir_exists_p("/etc") == 0 ||
963 target_file_exists_p("/etc/fstab") == 0) {
964 msg_display(MSG_noetcfstab
, diskdev
);
965 process_menu(MENU_ok
, NULL
);
970 /* Get fstab entries from the target-root /etc/fstab. */
971 fstabsize
= target_collect_file(T_FILE
, &fstab
, "/etc/fstab");
974 msg_display(MSG_badetcfstab
, diskdev
);
975 process_menu(MENU_ok
, NULL
);
978 error
= walk(fstab
, (size_t)fstabsize
, fstabbuf
, numfstabbuf
);
985 set_swap(const char *disk
, partinfo
*pp
)
994 for (i
= 0; i
< MAXPARTITIONS
; i
++) {
995 if (pp
[i
].pi_fstype
!= FS_SWAP
)
997 asprintf(&cp
, "/dev/%s%c", disk
, 'a' + i
);
998 rval
= swapctl(SWAP_ON
, cp
, 0);
1008 check_swap(const char *disk
, int remove_swap
)
1010 struct swapent
*swap
;
1016 nswap
= swapctl(SWAP_NSWAP
, 0, 0);
1020 swap
= malloc(nswap
* sizeof *swap
);
1024 nswap
= swapctl(SWAP_STATS
, swap
, nswap
);
1029 while (--nswap
>= 0) {
1030 /* Should we check the se_dev or se_path? */
1031 cp
= swap
[nswap
].se_path
;
1032 if (memcmp(cp
, "/dev/", 5) != 0)
1034 if (memcmp(cp
+ 5, disk
, l
) != 0)
1036 if (!isalpha(*(unsigned char *)(cp
+ 5 + l
)))
1038 if (cp
[5 + l
+ 1] != 0)
1040 /* ok path looks like it is for this device */
1042 /* count active swap areas */
1046 if (swapctl(SWAP_OFF
, cp
, 0) == -1)
1059 #ifdef HAVE_BOOTXX_xFS
1064 const char *bootxxname
;
1067 /* check we have boot code for the root partition type */
1068 fstype
= bsdlabel
[rootpart
].pi_fstype
;
1070 #if defined(BOOTXX_FFSV1) || defined(BOOTXX_FFSV2)
1072 if (bsdlabel
[rootpart
].pi_flags
& PIF_FFSv2
) {
1074 bootxxname
= BOOTXX_FFSV2
;
1080 bootxxname
= BOOTXX_FFSV1
;
1089 bootxxname
= BOOTXX_LFS
;
1097 if (bootxxname
== NULL
)
1100 asprintf(&bootxx
, "%s/%s", BOOTXXDIR
, bootxxname
);